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