• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
30 #ifdef DEV_AUTH_SERVICE_BUILD
31 #include "account_task_manager.h"
32 #include "group_data_manager.h"
33 #include "hisysevent_adapter.h"
34 #endif
35 
36 #ifdef DEV_AUTH_USE_JEMALLOC
37 #include "malloc.h"
38 #endif
39 
40 using namespace std;
41 namespace OHOS {
42 static std::mutex g_cBMutex;
43 
44 struct CbStubInfo {
45     sptr<IRemoteObject> cbStub;
46     bool inUse;
47 };
48 static struct CbStubInfo g_cbStub[MAX_CBSTUB_SIZE];
49 static bool g_cbStubInited = false;
50 static const uint32_t RESTORE_CODE = 14701;
51 
52 #ifdef DEV_AUTH_SERVICE_BUILD
53 static const uint32_t DEFAULT_UPGRADE_OS_ACCOUNT_ID = 100;
54 #endif
55 
56 #define MAX_DATA_LEN 102400
57 
ServiceDevAuth(bool serialInvokeFlag)58 ServiceDevAuth::ServiceDevAuth(bool serialInvokeFlag) : IRemoteStub(serialInvokeFlag)
59 {}
60 
~ServiceDevAuth()61 ServiceDevAuth::~ServiceDevAuth()
62 {
63     maxCallMapSz = MAX_CALLMAP_SIZE;
64     if (standardCallMapTable != nullptr) {
65         delete[] standardCallMapTable;
66         standardCallMapTable = nullptr;
67     }
68     callMapElemNum = 0;
69 }
70 
Dump(int32_t fd,const std::vector<std::u16string> & args)71 int32_t ServiceDevAuth::Dump(int32_t fd, const std::vector<std::u16string> &args)
72 {
73     std::vector<std::string> strArgs;
74     for (auto arg : args) {
75         strArgs.emplace_back(Str16ToStr8(arg));
76     }
77     uint32_t argc = strArgs.size();
78     StringVector strArgVec = CreateStrVector();
79     for (uint32_t i = 0; i < argc; i++) {
80         HcString strArg = CreateString();
81         if (!StringSetPointer(&strArg, strArgs[i].c_str())) {
82             LOGE("Failed to set strArg!");
83             DeleteString(&strArg);
84             continue;
85         }
86         if (strArgVec.pushBackT(&strArgVec, strArg) == NULL) {
87             LOGE("Failed to push strArg to strArgVec!");
88             DeleteString(&strArg);
89         }
90     }
91     DEV_AUTH_DUMP(fd, &strArgVec);
92     DestroyStrVector(&strArgVec);
93     return 0;
94 }
95 
GetCallMethodByMethodId(int32_t methodId)96 IpcServiceCall ServiceDevAuth::GetCallMethodByMethodId(int32_t methodId)
97 {
98     int32_t i;
99 
100     if (standardCallMapTable == nullptr) {
101         return nullptr;
102     }
103 
104     for (i = 0; i < maxCallMapSz; i++) {
105         if ((standardCallMapTable[i].methodId == methodId) && (standardCallMapTable[i].method != nullptr)) {
106             return standardCallMapTable[i].method;
107         }
108     }
109     return nullptr;
110 }
111 
DecodeCallRequest(MessageParcel & data,IpcDataInfo * paramsCache,int32_t cacheNum,int32_t & inParamNum)112 static int32_t DecodeCallRequest(MessageParcel &data, IpcDataInfo *paramsCache, int32_t cacheNum, int32_t &inParamNum)
113 {
114     int32_t dataLen = 0;
115     int32_t i;
116     int32_t ret;
117 
118     if (data.GetReadableBytes() == 0) {
119         return HC_SUCCESS;
120     }
121 
122     if (data.GetReadableBytes() > MAX_DATA_LEN) {
123         LOGE("Data len over MAX_DATA_LEN");
124         return HC_ERR_IPC_BAD_MESSAGE_LENGTH;
125     }
126 
127     if (data.GetReadableBytes() < sizeof(int32_t)) {
128         LOGE("Insufficient data available in IPC container. [Data]: dataLen");
129         return HC_ERR_IPC_BAD_MESSAGE_LENGTH;
130     }
131     data.ReadInt32(dataLen);
132     if (dataLen > static_cast<int32_t>(data.GetReadableBytes())) {
133         LOGE("Insufficient data available in IPC container. [Data]: data");
134         return HC_ERR_IPC_BAD_MESSAGE_LENGTH;
135     }
136 
137     if (data.GetReadableBytes() < sizeof(int32_t)) {
138         LOGE("Insufficient data available in IPC container. [Data]: inParamNum");
139         return HC_ERR_IPC_BAD_MESSAGE_LENGTH;
140     }
141     data.ReadInt32(inParamNum);
142     if ((inParamNum < 0) || (inParamNum > cacheNum)) {
143         LOGE("param number invalid, inParamNum - %" LOG_PUB "d", inParamNum);
144         return HC_ERR_IPC_BAD_PARAM_NUM;
145     }
146 
147     for (i = 0; i < inParamNum; i++) {
148         ret = DecodeIpcData(reinterpret_cast<uintptr_t>(&data), &(paramsCache[i].type),
149             &(paramsCache[i].val), &(paramsCache[i].valSz));
150         if (ret != HC_SUCCESS) {
151             LOGE("decode failed, ret %" LOG_PUB "d", ret);
152             return ret;
153         }
154     }
155     return HC_SUCCESS;
156 }
157 
GetMethodId(MessageParcel & data,int32_t & methodId)158 static int32_t GetMethodId(MessageParcel &data, int32_t &methodId)
159 {
160     if (data.GetDataSize() < sizeof(int32_t)) {
161         LOGE("Insufficient data available in IPC container. [Data]: methodId");
162         return HC_ERR_IPC_CALL_DATA_LENGTH;
163     }
164     methodId = data.ReadInt32();
165     return HC_SUCCESS;
166 }
167 
WithObject(int32_t methodId,MessageParcel & data,IpcDataInfo & ipcData,int32_t & cnt)168 static void WithObject(int32_t methodId, MessageParcel &data, IpcDataInfo &ipcData, int32_t &cnt)
169 {
170     if (!IsCallbackMethod(methodId)) {
171         return;
172     }
173     if (data.GetReadableBytes() < sizeof(int32_t)) {
174         LOGE("Insufficient data available in IPC container. [Data]: type");
175         return;
176     }
177     ipcData.type = data.ReadInt32();
178     ipcData.valSz = sizeof(StubDevAuthCb);
179     sptr<IRemoteObject> tmp = data.ReadRemoteObject();
180     if (!tmp) {
181         LOGE("should with remote object, but read failed");
182         return;
183     }
184     ipcData.idx = ServiceDevAuth::SetRemoteObject(tmp);
185     if (ipcData.idx >= 0) {
186         ipcData.val = reinterpret_cast<uint8_t *>(&(ipcData.idx));
187         LOGI("object trans success, set id %" LOG_PUB "d", ipcData.idx);
188         cnt++;
189     }
190 }
191 
InitCbStubTable()192 static void InitCbStubTable()
193 {
194     int32_t i;
195     if (g_cbStubInited) {
196         return;
197     }
198     std::lock_guard<std::mutex> autoLock(g_cBMutex);
199     if (g_cbStubInited) { /* for first init at the same time */
200         return;
201     }
202     for (i = 0; i < MAX_CBSTUB_SIZE; i++) {
203         g_cbStub[i].inUse = false;
204     }
205     g_cbStubInited = true;
206     return;
207 }
208 
HandleRestoreCall(MessageParcel & data,MessageParcel & reply)209 int32_t ServiceDevAuth::HandleRestoreCall(MessageParcel &data, MessageParcel &reply)
210 {
211 #ifdef DEV_AUTH_SERVICE_BUILD
212     int32_t osAccountId = DEFAULT_UPGRADE_OS_ACCOUNT_ID;
213     data.ReadInt32(osAccountId);
214     LOGI("Begin to upgrade data for osAccountId: %" LOG_PUB "d.", osAccountId);
215     int32_t res = ExecuteAccountAuthCmd(osAccountId, UPGRADE_DATA, nullptr, nullptr);
216     ReloadOsAccountDb(osAccountId);
217     if (res != HC_SUCCESS) {
218         LOGE("Failed to upgrade data!");
219         DEV_AUTH_REPORT_FAULT_EVENT_WITH_ERR_CODE(UPGRADE_DATA_EVENT, PROCESS_UPDATE, res);
220     }
221     reply.WriteInt32(res);
222 #else
223     (void)data;
224     (void)reply;
225 #endif
226     return 0;
227 }
228 
HandleDeviceAuthCall(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)229 int32_t ServiceDevAuth::HandleDeviceAuthCall(uint32_t code, MessageParcel &data, MessageParcel &reply,
230     MessageOption &option)
231 {
232     SET_LOG_MODE(NORMAL_MODE);
233     int32_t ret = HC_ERR_IPC_UNKNOW_OPCODE;
234     uint32_t dataLen;
235     int32_t methodId = 0;
236     int32_t reqParamNum = 0;
237     MessageParcel replyCache;
238     IpcDataInfo reqParams[MAX_REQUEST_PARAMS_NUM] = { { 0 } };
239     IpcServiceCall serviceCall = nullptr;
240 
241     switch (code) {
242         case static_cast<uint32_t>(DevAuthInterfaceCode::DEV_AUTH_CALL_REQUEST):
243             ret = GetMethodId(data, methodId);
244             if (ret != HC_SUCCESS) {
245                 break;
246             }
247             if (CheckPermission(methodId) != HC_SUCCESS) {
248                 return -1;
249             }
250             serviceCall = GetCallMethodByMethodId(methodId);
251             if (serviceCall == nullptr) {
252                 LOGE("ServiceDevAuth::HandleDeviceAuthCall serviceCall is nullptr, methodId: %" LOG_PUB "d", methodId);
253                 ret = HC_ERR_IPC_METHOD_ID_INVALID;
254                 break;
255             }
256             ret = DecodeCallRequest(data, reqParams, MAX_REQUEST_PARAMS_NUM, reqParamNum);
257             if (ret != HC_SUCCESS) {
258                 LOGE("ServiceDevAuth::HandleDeviceAuthCall DecodeCallRequest ret: %" LOG_PUB "d", ret);
259                 break;
260             }
261             if (reqParamNum < (MAX_REQUEST_PARAMS_NUM - 1)) {
262                 InitCbStubTable();
263                 WithObject(methodId, data, reqParams[reqParamNum], reqParamNum);
264             }
265             ret = serviceCall(reqParams, reqParamNum, reinterpret_cast<uintptr_t>(&replyCache));
266             break;
267         default:
268             return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
269     }
270     reply.WriteInt32(ret);
271     dataLen = replyCache.GetDataSize();
272     if (dataLen > 0) {
273         reply.WriteInt32(dataLen);
274         reply.WriteBuffer(reinterpret_cast<const void *>(replyCache.GetData()), dataLen);
275     }
276     return 0;
277 }
278 
DevAuthInitMemoryPolicy(void)279 static void DevAuthInitMemoryPolicy(void)
280 {
281 #ifdef DEV_AUTH_USE_JEMALLOC
282     (void)mallopt(M_SET_THREAD_CACHE, M_THREAD_CACHE_DISABLE);
283     (void)mallopt(M_DELAYED_FREE, M_DELAYED_FREE_DISABLE);
284 #endif
285 }
286 
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)287 int32_t ServiceDevAuth::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply,
288     MessageOption &option)
289 {
290     DevAuthInitMemoryPolicy();
291     std::u16string readToken = data.ReadInterfaceToken();
292     bool isRestoreCall = ((code == RESTORE_CODE) && (readToken == std::u16string(u"OHOS.Updater.RestoreData")));
293     if (readToken != GetDescriptor() && !isRestoreCall) {
294         LOGE("[IPC][C->S]: The proxy interface token is invalid!");
295         return -1;
296     }
297     if (isRestoreCall) {
298         return HandleRestoreCall(data, reply);
299     } else {
300         return HandleDeviceAuthCall(code, data, reply, option);
301     }
302 }
303 
SetCallMap(IpcServiceCall method,int32_t methodId)304 int32_t ServiceDevAuth::SetCallMap(IpcServiceCall method, int32_t methodId)
305 {
306     int32_t len;
307     errno_t eno;
308     IpcServiceCallMap *callMapTmp = nullptr;
309 
310     if ((1 + callMapElemNum) > maxCallMapSz) {
311         maxCallMapSz += MAX_CALLMAP_SIZE;
312         if (standardCallMapTable != nullptr) {
313             callMapTmp = standardCallMapTable;
314             standardCallMapTable = nullptr;
315         }
316     }
317     if (standardCallMapTable == nullptr) {
318         standardCallMapTable = new(std::nothrow) IpcServiceCallMap[maxCallMapSz];
319         if (standardCallMapTable == nullptr) {
320             return HC_ERR_ALLOC_MEMORY;
321         }
322         len = sizeof(IpcServiceCallMap) * maxCallMapSz;
323         (void)memset_s(standardCallMapTable, len, 0, len);
324         if (callMapTmp != nullptr) {
325             eno = memcpy_s(standardCallMapTable, len, callMapTmp, (sizeof(IpcServiceCallMap) * callMapElemNum));
326             if (eno != EOK) {
327                 delete[] standardCallMapTable;
328                 standardCallMapTable = callMapTmp;
329                 maxCallMapSz -= MAX_CALLMAP_SIZE;
330                 return HC_ERR_MEMORY_COPY;
331             }
332             delete[] callMapTmp;
333             callMapTmp = nullptr;
334         }
335     }
336 
337     standardCallMapTable[callMapElemNum].method = method;
338     standardCallMapTable[callMapElemNum].methodId = methodId;
339     callMapElemNum++;
340     return HC_SUCCESS;
341 }
342 
SetRemoteObject(sptr<IRemoteObject> & object)343 int32_t ServiceDevAuth::SetRemoteObject(sptr<IRemoteObject> &object)
344 {
345     int32_t idx = -1;
346     int32_t i;
347 
348     std::lock_guard<std::mutex> autoLock(g_cBMutex);
349     for (i = 0; i < MAX_CBSTUB_SIZE; i++) {
350         if (!g_cbStub[i].inUse) {
351             idx = i;
352             break;
353         }
354     }
355     LOGI("remote object cache index %" LOG_PUB "d", idx);
356     if (idx == -1) {
357         return -1;
358     }
359     g_cbStub[idx].cbStub = object;
360     g_cbStub[idx].inUse = true;
361     return idx;
362 }
363 
AddCbDeathRecipient(int32_t cbStubIdx,int32_t cbDataIdx)364 void ServiceDevAuth::AddCbDeathRecipient(int32_t cbStubIdx, int32_t cbDataIdx)
365 {
366     bool bRet = false;
367     if ((cbStubIdx < 0) || (cbStubIdx >= MAX_CBSTUB_SIZE) || (!g_cbStub[cbStubIdx].inUse)) {
368         return;
369     }
370 
371     std::lock_guard<std::mutex> autoLock(g_cBMutex);
372     DevAuthDeathRecipient *deathRecipient = new(std::nothrow) DevAuthDeathRecipient(cbDataIdx);
373     if (deathRecipient == nullptr) {
374         LOGE("Failed to create death recipient");
375         return;
376     }
377     bRet = g_cbStub[cbStubIdx].cbStub->AddDeathRecipient(deathRecipient);
378     LOGI("AddDeathRecipient %" LOG_PUB "s, callback stub idx %" LOG_PUB "d", bRet ? "success" : "failed", cbStubIdx);
379     return;
380 }
381 
ResetRemoteObject(int32_t idx)382 void ServiceDevAuth::ResetRemoteObject(int32_t idx)
383 {
384     if ((idx >= 0) && (idx < MAX_CBSTUB_SIZE)) {
385         LOGI("remote object used done, idx %" LOG_PUB "d", idx);
386         std::lock_guard<std::mutex> autoLock(g_cBMutex);
387         g_cbStub[idx].inUse = false;
388     }
389     return;
390 }
391 
ActCallback(int32_t objIdx,int32_t callbackId,bool sync,uintptr_t cbHook,MessageParcel & dataParcel,MessageParcel & reply)392 void ServiceDevAuth::ActCallback(int32_t objIdx, int32_t callbackId, bool sync,
393     uintptr_t cbHook, MessageParcel &dataParcel, MessageParcel &reply)
394 {
395     if ((objIdx < 0) || (objIdx >= MAX_CBSTUB_SIZE) || (!g_cbStub[objIdx].inUse)) {
396         LOGW("nothing to do, callback id %" LOG_PUB "d, remote object id %" LOG_PUB "d", callbackId, objIdx);
397         return;
398     }
399     MessageOption option(MessageOption::TF_SYNC);
400     if (!sync) {
401         option.SetFlags(MessageOption::TF_ASYNC);
402     }
403     std::lock_guard<std::mutex> autoLock(g_cBMutex);
404     sptr<ICommIpcCallback> proxy = iface_cast<ICommIpcCallback>(g_cbStub[objIdx].cbStub);
405     proxy->DoCallBack(callbackId, cbHook, dataParcel, reply, option);
406     return;
407 }
408 
DevAuthDeathRecipient(int32_t cbIdx)409 DevAuthDeathRecipient::DevAuthDeathRecipient(int32_t cbIdx)
410 {
411     callbackIdx = cbIdx;
412 }
413 }
414