1 /*
2 * Copyright (C) 2021-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ipc_dev_auth_stub.h"
17
18 #include "common_defs.h"
19 #include "hc_log.h"
20 #include "ipc_adapt.h"
21 #include "ipc_callback_stub.h"
22 #include "ipc_sdk_defines.h"
23 #include "permission_adapter.h"
24 #include "securec.h"
25 #include "system_ability_definition.h"
26 #include "hc_string_vector.h"
27 #include "hidump_adapter.h"
28 #include "string_ex.h"
29 #include "critical_handler.h"
30
31 #ifdef DEV_AUTH_SERVICE_BUILD
32 #include "account_task_manager.h"
33 #include "group_data_manager.h"
34 #include "hisysevent_adapter.h"
35 #endif
36
37 #ifdef DEV_AUTH_USE_JEMALLOC
38 #include "malloc.h"
39 #endif
40
41 using namespace std;
42 namespace OHOS {
43 static std::mutex g_cBMutex;
44
45 struct CbStubInfo {
46 sptr<IRemoteObject> cbStub;
47 bool inUse;
48 };
49 static struct CbStubInfo g_cbStub[MAX_CBSTUB_SIZE];
50 static bool g_cbStubInited = false;
51 static const uint32_t RESTORE_CODE = 14701;
52 static const std::vector<int32_t> IPC_CALL_ID_UN_CRITICAL = {
53 IPC_CALL_ID_APPLY_REG_INFO,
54 IPC_CALL_ID_CHECK_ACCESS_TO_GROUP,
55 IPC_CALL_ID_GET_PK_INFO_LIST,
56 IPC_CALL_ID_GET_GROUP_INFO,
57 IPC_CALL_ID_SEARCH_GROUPS,
58 IPC_CALL_ID_GET_JOINED_GROUPS,
59 IPC_CALL_ID_GET_RELATED_GROUPS,
60 IPC_CALL_ID_GET_DEV_INFO_BY_ID,
61 IPC_CALL_ID_GET_TRUST_DEVICES,
62 IPC_CALL_ID_IS_DEV_IN_GROUP,
63 IPC_CALL_ID_GET_REAL_INFO,
64 IPC_CALL_ID_GET_PSEUDONYM_ID,
65 IPC_CALL_ID_CM_QUERY_CREDENTIAL_BY_PARAMS,
66 IPC_CALL_ID_CM_QUERY_CREDENTIAL_BY_CRED_ID
67 };
68
69 #ifdef DEV_AUTH_SERVICE_BUILD
70 static const uint32_t DEFAULT_UPGRADE_OS_ACCOUNT_ID = 100;
71 #endif
72
73 #define MAX_DATA_LEN 102400
74
ServiceDevAuth(bool serialInvokeFlag)75 ServiceDevAuth::ServiceDevAuth(bool serialInvokeFlag) : IRemoteStub(serialInvokeFlag)
76 {}
77
~ServiceDevAuth()78 ServiceDevAuth::~ServiceDevAuth()
79 {
80 maxCallMapSz = MAX_CALLMAP_SIZE;
81 if (standardCallMapTable != nullptr) {
82 delete[] standardCallMapTable;
83 standardCallMapTable = nullptr;
84 }
85 callMapElemNum = 0;
86 }
87
Dump(int32_t fd,const std::vector<std::u16string> & args)88 int32_t ServiceDevAuth::Dump(int32_t fd, const std::vector<std::u16string> &args)
89 {
90 std::vector<std::string> strArgs;
91 for (auto arg : args) {
92 strArgs.emplace_back(Str16ToStr8(arg));
93 }
94 uint32_t argc = strArgs.size();
95 StringVector strArgVec = CreateStrVector();
96 for (uint32_t i = 0; i < argc; i++) {
97 HcString strArg = CreateString();
98 if (!StringSetPointer(&strArg, strArgs[i].c_str())) {
99 LOGE("Failed to set strArg!");
100 DeleteString(&strArg);
101 continue;
102 }
103 if (strArgVec.pushBackT(&strArgVec, strArg) == NULL) {
104 LOGE("Failed to push strArg to strArgVec!");
105 DeleteString(&strArg);
106 }
107 }
108 DEV_AUTH_DUMP(fd, &strArgVec);
109 DestroyStrVector(&strArgVec);
110 return 0;
111 }
112
GetCallMethodByMethodId(int32_t methodId)113 IpcServiceCall ServiceDevAuth::GetCallMethodByMethodId(int32_t methodId)
114 {
115 int32_t i;
116
117 if (standardCallMapTable == nullptr) {
118 return nullptr;
119 }
120
121 for (i = 0; i < maxCallMapSz; i++) {
122 if ((standardCallMapTable[i].methodId == methodId) && (standardCallMapTable[i].method != nullptr)) {
123 return standardCallMapTable[i].method;
124 }
125 }
126 return nullptr;
127 }
128
DecodeCallRequest(MessageParcel & data,IpcDataInfo * paramsCache,int32_t cacheNum,int32_t & inParamNum)129 static int32_t DecodeCallRequest(MessageParcel &data, IpcDataInfo *paramsCache, int32_t cacheNum, int32_t &inParamNum)
130 {
131 int32_t dataLen = 0;
132 int32_t i;
133 int32_t ret;
134
135 if (data.GetReadableBytes() == 0) {
136 return HC_SUCCESS;
137 }
138
139 if (data.GetReadableBytes() > MAX_DATA_LEN) {
140 LOGE("Data len over MAX_DATA_LEN");
141 return HC_ERR_IPC_BAD_MESSAGE_LENGTH;
142 }
143
144 if (data.GetReadableBytes() < sizeof(int32_t)) {
145 LOGE("Insufficient data available in IPC container. [Data]: dataLen");
146 return HC_ERR_IPC_BAD_MESSAGE_LENGTH;
147 }
148 data.ReadInt32(dataLen);
149 if (dataLen > static_cast<int32_t>(data.GetReadableBytes())) {
150 LOGE("Insufficient data available in IPC container. [Data]: data");
151 return HC_ERR_IPC_BAD_MESSAGE_LENGTH;
152 }
153
154 if (data.GetReadableBytes() < sizeof(int32_t)) {
155 LOGE("Insufficient data available in IPC container. [Data]: inParamNum");
156 return HC_ERR_IPC_BAD_MESSAGE_LENGTH;
157 }
158 data.ReadInt32(inParamNum);
159 if ((inParamNum < 0) || (inParamNum > cacheNum)) {
160 LOGE("param number invalid, inParamNum - %" LOG_PUB "d", inParamNum);
161 return HC_ERR_IPC_BAD_PARAM_NUM;
162 }
163
164 for (i = 0; i < inParamNum; i++) {
165 ret = DecodeIpcData(reinterpret_cast<uintptr_t>(&data), &(paramsCache[i].type),
166 &(paramsCache[i].val), &(paramsCache[i].valSz));
167 if (ret != HC_SUCCESS) {
168 LOGE("decode failed, ret %" LOG_PUB "d", ret);
169 return ret;
170 }
171 }
172 return HC_SUCCESS;
173 }
174
GetMethodId(MessageParcel & data,int32_t & methodId)175 static int32_t GetMethodId(MessageParcel &data, int32_t &methodId)
176 {
177 if (data.GetDataSize() < sizeof(int32_t)) {
178 LOGE("Insufficient data available in IPC container. [Data]: methodId");
179 return HC_ERR_IPC_CALL_DATA_LENGTH;
180 }
181 methodId = data.ReadInt32();
182 return HC_SUCCESS;
183 }
184
WithObject(int32_t methodId,MessageParcel & data,IpcDataInfo & ipcData,int32_t & cnt)185 static void WithObject(int32_t methodId, MessageParcel &data, IpcDataInfo &ipcData, int32_t &cnt)
186 {
187 if (!IsCallbackMethod(methodId)) {
188 return;
189 }
190 if (data.GetReadableBytes() < sizeof(int32_t)) {
191 LOGE("Insufficient data available in IPC container. [Data]: type");
192 return;
193 }
194 ipcData.type = data.ReadInt32();
195 ipcData.valSz = sizeof(StubDevAuthCb);
196 sptr<IRemoteObject> tmp = data.ReadRemoteObject();
197 if (!tmp) {
198 LOGE("should with remote object, but read failed");
199 return;
200 }
201 ipcData.idx = ServiceDevAuth::SetRemoteObject(tmp);
202 if (ipcData.idx >= 0) {
203 ipcData.val = reinterpret_cast<uint8_t *>(&(ipcData.idx));
204 LOGI("object trans success, set id %" LOG_PUB "d", ipcData.idx);
205 cnt++;
206 }
207 }
208
InitCbStubTable()209 static void InitCbStubTable()
210 {
211 int32_t i;
212 if (g_cbStubInited) {
213 return;
214 }
215 std::lock_guard<std::mutex> autoLock(g_cBMutex);
216 if (g_cbStubInited) { /* for first init at the same time */
217 return;
218 }
219 for (i = 0; i < MAX_CBSTUB_SIZE; i++) {
220 g_cbStub[i].inUse = false;
221 }
222 g_cbStubInited = true;
223 return;
224 }
225
HandleRestoreCall(MessageParcel & data,MessageParcel & reply)226 int32_t ServiceDevAuth::HandleRestoreCall(MessageParcel &data, MessageParcel &reply)
227 {
228 IncreaseCriticalCnt(ADD_ONE);
229 #ifdef DEV_AUTH_SERVICE_BUILD
230 int32_t osAccountId = DEFAULT_UPGRADE_OS_ACCOUNT_ID;
231 data.ReadInt32(osAccountId);
232 LOGI("Begin to upgrade data for osAccountId: %" LOG_PUB "d.", osAccountId);
233 int32_t res = ExecuteAccountAuthCmd(osAccountId, UPGRADE_DATA, nullptr, nullptr);
234 ReloadOsAccountDb(osAccountId);
235 if (res != HC_SUCCESS) {
236 LOGE("Failed to upgrade data!");
237 DEV_AUTH_REPORT_FAULT_EVENT_WITH_ERR_CODE(UPGRADE_DATA_EVENT, PROCESS_UPDATE, res);
238 }
239 reply.WriteInt32(res);
240 #else
241 (void)data;
242 (void)reply;
243 #endif
244 DecreaseCriticalCnt();
245 return 0;
246 }
247
SetMethodCritical(int32_t methodId,bool criticalSwitch)248 static void SetMethodCritical(int32_t methodId, bool criticalSwitch)
249 {
250 if (std::count(IPC_CALL_ID_UN_CRITICAL.begin(), IPC_CALL_ID_UN_CRITICAL.end(), methodId) != 0) {
251 return;
252 }
253 if (criticalSwitch) {
254 IncreaseCriticalCnt(ADD_ONE);
255 } else {
256 DecreaseCriticalCnt();
257 }
258 }
259
HandleDeviceAuthCall(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)260 int32_t ServiceDevAuth::HandleDeviceAuthCall(uint32_t code, MessageParcel &data, MessageParcel &reply,
261 MessageOption &option)
262 {
263 SET_LOG_MODE(NORMAL_MODE);
264 int32_t ret = HC_ERR_IPC_UNKNOW_OPCODE;
265 uint32_t dataLen;
266 int32_t methodId = 0;
267 int32_t reqParamNum = 0;
268 MessageParcel replyCache;
269 IpcDataInfo reqParams[MAX_REQUEST_PARAMS_NUM] = { { 0 } };
270 IpcServiceCall serviceCall = nullptr;
271 switch (code) {
272 case static_cast<uint32_t>(DevAuthInterfaceCode::DEV_AUTH_CALL_REQUEST):
273 ret = GetMethodId(data, methodId);
274 if (ret != HC_SUCCESS) {
275 break;
276 }
277 ret = CheckPermission(methodId);
278 if (ret != HC_SUCCESS) {
279 return ret;
280 }
281 serviceCall = GetCallMethodByMethodId(methodId);
282 if (serviceCall == nullptr) {
283 LOGE("ServiceDevAuth::HandleDeviceAuthCall serviceCall is nullptr, methodId: %" LOG_PUB "d", methodId);
284 ret = HC_ERR_IPC_METHOD_ID_INVALID;
285 break;
286 }
287 ret = DecodeCallRequest(data, reqParams, MAX_REQUEST_PARAMS_NUM, reqParamNum);
288 if (ret != HC_SUCCESS) {
289 LOGE("ServiceDevAuth::HandleDeviceAuthCall DecodeCallRequest ret: %" LOG_PUB "d", ret);
290 break;
291 }
292 if (reqParamNum < (MAX_REQUEST_PARAMS_NUM - 1)) {
293 InitCbStubTable();
294 WithObject(methodId, data, reqParams[reqParamNum], reqParamNum);
295 }
296 SetMethodCritical(methodId, true);
297 ret = serviceCall(reqParams, reqParamNum, reinterpret_cast<uintptr_t>(&replyCache));
298 SetMethodCritical(methodId, false);
299 break;
300 default:
301 return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
302 }
303 reply.WriteInt32(ret);
304 dataLen = replyCache.GetDataSize();
305 if (dataLen > 0) {
306 reply.WriteInt32(dataLen);
307 reply.WriteBuffer(reinterpret_cast<const void *>(replyCache.GetData()), dataLen);
308 }
309 return 0;
310 }
311
DevAuthInitMemoryPolicy(void)312 static void DevAuthInitMemoryPolicy(void)
313 {
314 #ifdef DEV_AUTH_USE_JEMALLOC
315 (void)mallopt(M_SET_THREAD_CACHE, M_THREAD_CACHE_DISABLE);
316 (void)mallopt(M_DELAYED_FREE, M_DELAYED_FREE_DISABLE);
317 #endif
318 }
319
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)320 int32_t ServiceDevAuth::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply,
321 MessageOption &option)
322 {
323 DevAuthInitMemoryPolicy();
324 std::u16string readToken = data.ReadInterfaceToken();
325 bool isRestoreCall = ((code == RESTORE_CODE) && (readToken == std::u16string(u"OHOS.Updater.RestoreData")));
326 if (readToken != GetDescriptor() && !isRestoreCall) {
327 LOGE("[IPC][C->S]: The proxy interface token is invalid!");
328 return -1;
329 }
330 if (isRestoreCall) {
331 return HandleRestoreCall(data, reply);
332 } else {
333 return HandleDeviceAuthCall(code, data, reply, option);
334 }
335 }
336
SetCallMap(IpcServiceCall method,int32_t methodId)337 int32_t ServiceDevAuth::SetCallMap(IpcServiceCall method, int32_t methodId)
338 {
339 int32_t len;
340 errno_t eno;
341 IpcServiceCallMap *callMapTmp = nullptr;
342
343 if ((1 + callMapElemNum) > maxCallMapSz) {
344 maxCallMapSz += MAX_CALLMAP_SIZE;
345 if (standardCallMapTable != nullptr) {
346 callMapTmp = standardCallMapTable;
347 standardCallMapTable = nullptr;
348 }
349 }
350 if (standardCallMapTable == nullptr) {
351 standardCallMapTable = new(std::nothrow) IpcServiceCallMap[maxCallMapSz];
352 if (standardCallMapTable == nullptr) {
353 return HC_ERR_ALLOC_MEMORY;
354 }
355 len = sizeof(IpcServiceCallMap) * maxCallMapSz;
356 (void)memset_s(standardCallMapTable, len, 0, len);
357 if (callMapTmp != nullptr) {
358 eno = memcpy_s(standardCallMapTable, len, callMapTmp, (sizeof(IpcServiceCallMap) * callMapElemNum));
359 if (eno != EOK) {
360 delete[] standardCallMapTable;
361 standardCallMapTable = callMapTmp;
362 maxCallMapSz -= MAX_CALLMAP_SIZE;
363 return HC_ERR_MEMORY_COPY;
364 }
365 delete[] callMapTmp;
366 callMapTmp = nullptr;
367 }
368 }
369
370 standardCallMapTable[callMapElemNum].method = method;
371 standardCallMapTable[callMapElemNum].methodId = methodId;
372 callMapElemNum++;
373 return HC_SUCCESS;
374 }
375
SetRemoteObject(sptr<IRemoteObject> & object)376 int32_t ServiceDevAuth::SetRemoteObject(sptr<IRemoteObject> &object)
377 {
378 int32_t idx = -1;
379 int32_t i;
380
381 std::lock_guard<std::mutex> autoLock(g_cBMutex);
382 for (i = 0; i < MAX_CBSTUB_SIZE; i++) {
383 if (!g_cbStub[i].inUse) {
384 idx = i;
385 break;
386 }
387 }
388 LOGI("remote object cache index %" LOG_PUB "d", idx);
389 if (idx == -1) {
390 return -1;
391 }
392 g_cbStub[idx].cbStub = object;
393 g_cbStub[idx].inUse = true;
394 return idx;
395 }
396
AddCbDeathRecipient(int32_t cbStubIdx,int32_t cbDataIdx)397 void ServiceDevAuth::AddCbDeathRecipient(int32_t cbStubIdx, int32_t cbDataIdx)
398 {
399 bool bRet = false;
400 if ((cbStubIdx < 0) || (cbStubIdx >= MAX_CBSTUB_SIZE) || (!g_cbStub[cbStubIdx].inUse)) {
401 return;
402 }
403
404 std::lock_guard<std::mutex> autoLock(g_cBMutex);
405 DevAuthDeathRecipient *deathRecipient = new(std::nothrow) DevAuthDeathRecipient(cbDataIdx);
406 if (deathRecipient == nullptr) {
407 LOGE("Failed to create death recipient");
408 return;
409 }
410 bRet = g_cbStub[cbStubIdx].cbStub->AddDeathRecipient(deathRecipient);
411 LOGI("AddDeathRecipient %" LOG_PUB "s, callback stub idx %" LOG_PUB "d", bRet ? "success" : "failed", cbStubIdx);
412 return;
413 }
414
ResetRemoteObject(int32_t idx)415 void ServiceDevAuth::ResetRemoteObject(int32_t idx)
416 {
417 if ((idx >= 0) && (idx < MAX_CBSTUB_SIZE)) {
418 LOGI("remote object used done, idx %" LOG_PUB "d", idx);
419 std::lock_guard<std::mutex> autoLock(g_cBMutex);
420 g_cbStub[idx].inUse = false;
421 }
422 return;
423 }
424
ActCallback(int32_t objIdx,int32_t callbackId,bool sync,uintptr_t cbHook,MessageParcel & dataParcel,MessageParcel & reply)425 void ServiceDevAuth::ActCallback(int32_t objIdx, int32_t callbackId, bool sync,
426 uintptr_t cbHook, MessageParcel &dataParcel, MessageParcel &reply)
427 {
428 if ((objIdx < 0) || (objIdx >= MAX_CBSTUB_SIZE) || (!g_cbStub[objIdx].inUse)) {
429 LOGW("nothing to do, callback id %" LOG_PUB "d, remote object id %" LOG_PUB "d", callbackId, objIdx);
430 return;
431 }
432 MessageOption option(MessageOption::TF_SYNC);
433 if (!sync) {
434 option.SetFlags(MessageOption::TF_ASYNC);
435 }
436 std::lock_guard<std::mutex> autoLock(g_cBMutex);
437 sptr<ICommIpcCallback> proxy = iface_cast<ICommIpcCallback>(g_cbStub[objIdx].cbStub);
438 proxy->DoCallBack(callbackId, cbHook, dataParcel, reply, option);
439 return;
440 }
441
DevAuthDeathRecipient(int32_t cbIdx)442 DevAuthDeathRecipient::DevAuthDeathRecipient(int32_t cbIdx)
443 {
444 callbackIdx = cbIdx;
445 }
446 }
447