1 /*
2 * Copyright (c) 2020 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 #include "endpoint.h"
16
17 #include <stdlib.h>
18 #include <securec.h>
19 #include <unistd.h>
20
21 #include <ohos_errno.h>
22 #include <service.h>
23 #include <log.h>
24
25 #include "policy_define.h"
26 #include "iproxy_server.h"
27 #include "memory_adapter.h"
28 #include "thread_adapter.h"
29 #include "default_client.h"
30
31 #undef LOG_TAG
32 #undef LOG_DOMAIN
33 #define LOG_TAG "Samgr"
34 #define LOG_DOMAIN 0xD001800
35
36 #ifdef LITE_LINUX_BINDER_IPC
37 #define MAX_STACK_SIZE 0x100000
38 #else
39 #define MAX_STACK_SIZE 0x1000
40 #endif
41 #define MAX_OBJECT_NUM 5
42 #define MAX_RETRY_TIMES 300
43 #define RETRY_INTERVAL (50 * 1000)
44 #define MAX_REGISTER_RETRY_TIMES 10
45 #define REGISTER_RETRY_INTERVAL 2
46 #define MAX_POLICY_NUM 8
47
48 #ifndef MAX_BUCKET_RATE
49 #define MAX_BUCKET_RATE 1000
50 #endif
51
52 #ifndef MAX_BURST_RATE
53 #define MAX_BURST_RATE (MAX_BUCKET_RATE + (MAX_BUCKET_RATE >> 1))
54 #endif
55
56 #define SAMGR_SERVICE "samgr"
57
58 typedef struct Router {
59 SaName saName;
60 Identity identity;
61 IServerProxy *proxy;
62 PolicyTrans *policy;
63 uint32 policyNum;
64 } Router;
65
66 static int CompareIServerProxy(const IServerProxy *proxy1, const IServerProxy *proxy2);
67 static IServerProxy *GetIServerProxy(const Router *router);
68 static void *Receive(void *argv);
69 static int Dispatch(const IpcContext *context, void *ipcMsg, IpcIo *data, void *argv);
70 static void HandleIpc(const Request *request, const Response *response);
71 static int OnSamgrServerExit(const IpcContext *context, void *ipcMsg, IpcIo *data, void *argv);
72 static int RegisterRemoteFeatures(Endpoint *endpoint);
73 static void Listen(Endpoint *endpoint);
74 static boolean JudgePolicy(uid_t callingUid, const PolicyTrans *policy, uint32 policyNum);
75 static boolean SearchFixedPolicy(uid_t callingUid, PolicyTrans policy);
76 static int AddPolicyToRouter(const Endpoint *endpoint, const SvcIdentity *saInfo,
77 const PolicyTrans *policy, uint32 policyNum);
78 static int RegisterRemoteEndpoint(const IpcContext *context, SvcIdentity *identity);
79 static int RegisterIdentity(const IpcContext *context, const SaName *saName, SvcIdentity *saInfo,
80 PolicyTrans **policy, uint32 *policyNum);
81 static void GetRemotePolicy(IpcIo *reply, PolicyTrans **policy, uint32 *policyNum);
82
SAMGR_CreateEndpoint(const char * name,RegisterEndpoint registry)83 Endpoint *SAMGR_CreateEndpoint(const char *name, RegisterEndpoint registry)
84 {
85 Endpoint *endpoint = SAMGR_Malloc(sizeof(Endpoint));
86 if (endpoint == NULL) {
87 return NULL;
88 }
89 endpoint->deadId = INVALID_INDEX;
90 endpoint->context = OpenLiteIpc(LITEIPC_DEFAULT_MAP_SIZE);
91 endpoint->boss = NULL;
92 endpoint->routers = VECTOR_Make((VECTOR_Key)GetIServerProxy, (VECTOR_Compare)CompareIServerProxy);
93 endpoint->name = name;
94 endpoint->running = FALSE;
95 endpoint->identity.handle = (uint32_t)INVALID_INDEX;
96 endpoint->identity.token = (uint32_t)INVALID_INDEX;
97 endpoint->identity.cookie = (uint32_t)INVALID_INDEX;
98 endpoint->registerEP = (registry == NULL) ? RegisterRemoteEndpoint : registry;
99 TB_InitBucket(&endpoint->bucket, MAX_BUCKET_RATE, MAX_BURST_RATE);
100 return endpoint;
101 }
102
SAMGR_AddRouter(Endpoint * endpoint,const SaName * saName,const Identity * id,IUnknown * proxy)103 int SAMGR_AddRouter(Endpoint *endpoint, const SaName *saName, const Identity *id, IUnknown *proxy)
104 {
105 if (endpoint == NULL || id == NULL || proxy == NULL || saName == NULL) {
106 return EC_INVALID;
107 }
108
109 IServerProxy *serverProxy = NULL;
110 proxy->QueryInterface(proxy, SERVER_PROXY_VER, (void *)&serverProxy);
111 if (serverProxy == NULL) {
112 return EC_INVALID;
113 }
114 // Lock the multi-write
115 int index = VECTOR_FindByKey(&endpoint->routers, proxy);
116 if (index != INVALID_INDEX) {
117 serverProxy->Release((IUnknown *)serverProxy);
118 return index;
119 }
120
121 Router *router = SAMGR_Malloc(sizeof(Router));
122 if (router == NULL) {
123 HILOG_ERROR(HILOG_MODULE_SAMGR, "Memory is not enough! Identity<%d, %d>",
124 id->serviceId, id->featureId);
125 return EC_NOMEMORY;
126 }
127 router->saName = *saName;
128 router->identity = *id;
129 router->proxy = serverProxy;
130 router->policy = NULL;
131 router->policyNum = 0;
132 index = VECTOR_Add(&endpoint->routers, router);
133 if (index == INVALID_INDEX) {
134 SAMGR_Free(router);
135 return EC_FAILURE;
136 }
137 Listen(endpoint);
138 return index;
139 }
140
SAMGR_AddSysCap(const Endpoint * endpoint,const char * sysCap,BOOL isReg)141 int32 SAMGR_AddSysCap(const Endpoint *endpoint, const char *sysCap, BOOL isReg)
142 {
143 if (endpoint == NULL) {
144 return EC_INVALID;
145 }
146 HILOG_DEBUG(HILOG_MODULE_SAMGR, "SAMGR_AddSysCap begin");
147 IpcIo req;
148 uint8 data[MAX_DATA_LEN];
149 IpcIoInit(&req, data, MAX_DATA_LEN, 0);
150 IpcIoPushUint32(&req, RES_SYSCAP);
151 IpcIoPushUint32(&req, OP_PUT);
152 IpcIoPushString(&req, sysCap);
153 IpcIoPushBool(&req, isReg);
154
155 IpcIo reply;
156 void *replyBuf = NULL;
157 SvcIdentity samgr = {SAMGR_HANDLE, SAMGR_TOKEN, SAMGR_COOKIE};
158 int ret = Transact(endpoint->context, samgr, INVALID_INDEX, &req, &reply,
159 LITEIPC_FLAG_DEFAULT, (uintptr_t *)&replyBuf);
160 ret = -ret;
161 if (ret == LITEIPC_OK) {
162 ret = IpcIoPopInt32(&reply);
163 }
164
165 if (replyBuf != NULL) {
166 FreeBuffer(endpoint->context, replyBuf);
167 }
168 HILOG_DEBUG(HILOG_MODULE_SAMGR, "SAMGR_AddSysCap ret = %d", ret);
169
170 return ret;
171 }
172
SAMGR_GetSysCap(const Endpoint * endpoint,const char * sysCap,BOOL * isReg)173 int32 SAMGR_GetSysCap(const Endpoint *endpoint, const char *sysCap, BOOL *isReg)
174 {
175 if (endpoint == NULL) {
176 return EC_INVALID;
177 }
178 HILOG_DEBUG(HILOG_MODULE_SAMGR, "SAMGR_GetSysCap begin");
179 IpcIo req;
180 uint8 data[MAX_DATA_LEN];
181 IpcIoInit(&req, data, MAX_DATA_LEN, 0);
182 IpcIoPushUint32(&req, RES_SYSCAP);
183 IpcIoPushUint32(&req, OP_GET);
184 IpcIoPushString(&req, sysCap);
185
186 IpcIo reply;
187 void *replyBuf = NULL;
188 SvcIdentity samgr = {SAMGR_HANDLE, SAMGR_TOKEN, SAMGR_COOKIE};
189 int ret = Transact(endpoint->context, samgr, INVALID_INDEX, &req, &reply,
190 LITEIPC_FLAG_DEFAULT, (uintptr_t *)&replyBuf);
191 ret = -ret;
192 *isReg = FALSE;
193 if (ret == LITEIPC_OK) {
194 ret = IpcIoPopInt32(&reply);
195 }
196 if (ret == EC_SUCCESS) {
197 *isReg = IpcIoPopBool(&reply);
198 }
199 if (replyBuf != NULL) {
200 FreeBuffer(endpoint->context, replyBuf);
201 }
202 HILOG_DEBUG(HILOG_MODULE_SAMGR, "SAMGR_GetSysCap ret = %d", ret);
203 return ret;
204 }
205
SendGetAllSysCapsRequest(const Endpoint * endpoint,uint32 startIdx,IpcIo * reply,void ** replyBuf)206 static int SendGetAllSysCapsRequest(const Endpoint *endpoint, uint32 startIdx, IpcIo *reply, void **replyBuf)
207 {
208 IpcIo req;
209 uint8 data[MAX_DATA_LEN];
210 IpcIoInit(&req, data, MAX_DATA_LEN, 0);
211 IpcIoPushUint32(&req, RES_SYSCAP);
212 IpcIoPushUint32(&req, OP_ALL);
213 IpcIoPushUint32(&req, startIdx);
214 SvcIdentity samgr = {SAMGR_HANDLE, SAMGR_TOKEN, SAMGR_COOKIE};
215 int ret = Transact(endpoint->context, samgr, INVALID_INDEX, &req, reply,
216 LITEIPC_FLAG_DEFAULT, (uintptr_t *)replyBuf);
217 HILOG_DEBUG(HILOG_MODULE_SAMGR, "SendGetAllSysCapsRequest startIdx:%d, ret:%d!", startIdx, ret);
218 return -ret;
219 }
220
ParseGetAllSysCapsReply(IpcIo * reply,char sysCaps[MAX_SYSCAP_NUM][MAX_SYSCAP_NAME_LEN],int32 * sysCapNum,BOOL * isEnd,uint32 * nextRequestIdx)221 static int32 ParseGetAllSysCapsReply(IpcIo *reply, char sysCaps[MAX_SYSCAP_NUM][MAX_SYSCAP_NAME_LEN],
222 int32 *sysCapNum, BOOL *isEnd, uint32 *nextRequestIdx)
223 {
224 int32 ret = IpcIoPopInt32(reply);
225 if (ret != EC_SUCCESS) {
226 *isEnd = TRUE;
227 return ret;
228 }
229 *isEnd = IpcIoPopBool(reply);
230 *nextRequestIdx = IpcIoPopUint32(reply);
231 uint32 size = IpcIoPopUint32(reply);
232 size = ((size > MAX_SYSCAP_NUM) ? MAX_SYSCAP_NUM : size);
233 int cnt = *sysCapNum;
234 for (uint32 i = 0; i < size; i++) {
235 uint32 len = 0;
236 char *sysCap = (char *)IpcIoPopString(reply, &len);
237 if (sysCap == NULL || len == 0) {
238 continue;
239 }
240 if (strcpy_s(sysCaps[cnt], sizeof(sysCaps[cnt]), sysCap) != EC_SUCCESS) {
241 continue;
242 }
243 cnt++;
244 }
245 *sysCapNum = cnt;
246
247 return ret;
248 }
249
SAMGR_GetSystemCapabilities(const Endpoint * endpoint,char sysCaps[MAX_SYSCAP_NUM][MAX_SYSCAP_NAME_LEN],int32 * sysCapNum)250 int32 SAMGR_GetSystemCapabilities(const Endpoint *endpoint,
251 char sysCaps[MAX_SYSCAP_NUM][MAX_SYSCAP_NAME_LEN], int32 *sysCapNum)
252 {
253 if (sysCapNum == NULL) {
254 return EC_INVALID;
255 }
256 *sysCapNum = 0;
257 if (endpoint == NULL) {
258 return EC_INVALID;
259 }
260 HILOG_DEBUG(HILOG_MODULE_SAMGR, "SAMGR_GetSystemCapabilities begin");
261 IpcIo reply;
262 void *replyBuf = NULL;
263 uint32 startIdx = 0;
264 BOOL isEnd = TRUE;
265 int ret;
266 do {
267 ret = SendGetAllSysCapsRequest(endpoint, startIdx, &reply, &replyBuf);
268 if (ret == EC_SUCCESS) {
269 ret = ParseGetAllSysCapsReply(&reply, sysCaps, sysCapNum, &isEnd, &startIdx);
270 }
271 if (replyBuf != NULL) {
272 FreeBuffer(endpoint->context, replyBuf);
273 }
274 } while (isEnd == FALSE && ret == EC_SUCCESS);
275 HILOG_DEBUG(HILOG_MODULE_SAMGR, "SAMGR_GetSystemCapabilities ret = %d", ret);
276 return ret;
277 }
278
SAMGR_ProcPolicy(const Endpoint * endpoint,const SaName * saName,int token)279 int SAMGR_ProcPolicy(const Endpoint *endpoint, const SaName *saName, int token)
280 {
281 if (endpoint == NULL || saName == NULL || token == INVALID_INDEX) {
282 return EC_INVALID;
283 }
284 // retry until success or 20 seconds.
285 int ret = EC_INVALID;
286 uint8 retry = 0;
287 SvcIdentity saInfo = {INVALID_INDEX, token, INVALID_INDEX};
288 while (retry < MAX_REGISTER_RETRY_TIMES) {
289 ++retry;
290 PolicyTrans *policy = NULL;
291 uint32 policyNum = 0;
292 ret = RegisterIdentity(endpoint->context, saName, &saInfo, &policy, &policyNum);
293 if (ret != EC_SUCCESS || policy == NULL) {
294 SAMGR_Free(policy);
295 continue;
296 }
297 HILOG_INFO(HILOG_MODULE_SAMGR, "Register server sa<%s, %s> id<%u, %u> retry:%d ret:%d!",
298 saName->service, saName->feature, saInfo.handle, saInfo.token, retry, ret);
299 ret = AddPolicyToRouter(endpoint, &saInfo, policy, policyNum);
300 SAMGR_Free(policy);
301 if (ret == EC_SUCCESS) {
302 break;
303 }
304 sleep(REGISTER_RETRY_INTERVAL);
305 }
306 return ret;
307 }
308
Listen(Endpoint * endpoint)309 static void Listen(Endpoint *endpoint)
310 {
311 if (endpoint->boss != NULL) {
312 return;
313 }
314 ThreadAttr attr = {endpoint->name, MAX_STACK_SIZE, PRI_ABOVE_NORMAL, 0, 0};
315 endpoint->boss = (ThreadId)THREAD_Create(Receive, endpoint, &attr);
316 }
317
AddPolicyToRouter(const Endpoint * endpoint,const SvcIdentity * saInfo,const PolicyTrans * policy,uint32 policyNum)318 static int AddPolicyToRouter(const Endpoint *endpoint, const SvcIdentity *saInfo,
319 const PolicyTrans *policy, uint32 policyNum)
320 {
321 if (endpoint == NULL || saInfo == NULL || policy == NULL) {
322 return EC_INVALID;
323 }
324
325 Router *router = VECTOR_At((Vector *)&endpoint->routers, saInfo->token);
326 if (router == NULL) {
327 HILOG_ERROR(HILOG_MODULE_SAMGR, "Router <%s, %u> is NULL", endpoint->name, saInfo->token);
328 return EC_INVALID;
329 }
330
331 if (router->policy != NULL) {
332 return EC_SUCCESS;
333 }
334 router->policyNum = policyNum;
335 if (policyNum == 0) {
336 return EC_INVALID;
337 }
338 router->policy = (PolicyTrans *)SAMGR_Malloc(sizeof(PolicyTrans) * policyNum);
339 if (router->policy == NULL) {
340 return EC_NOMEMORY;
341 }
342 if (memcpy_s(router->policy, sizeof(PolicyTrans) * policyNum, policy, sizeof(PolicyTrans) * policyNum) != EOK) {
343 SAMGR_Free(router->policy);
344 router->policy = NULL;
345 HILOG_ERROR(HILOG_MODULE_SAMGR, "Add Policy <%s, %s, %s> Failed!",
346 endpoint->name, router->saName.service, router->saName.feature);
347 return EC_FAILURE;
348 }
349 HILOG_DEBUG(HILOG_MODULE_SAMGR, "Add Policy <%s, %s, %s> Success",
350 endpoint->name, router->saName.service, router->saName.feature);
351 return EC_SUCCESS;
352 }
353
Receive(void * argv)354 static void *Receive(void *argv)
355 {
356 Endpoint *endpoint = (Endpoint *)argv;
357 if (endpoint == NULL || endpoint->registerEP == NULL) {
358 return NULL;
359 }
360
361 int ret = EC_INVALID;
362 uint32 retry = 0;
363 while (retry < MAX_RETRY_TIMES) {
364 ret = endpoint->registerEP(endpoint->context, &endpoint->identity);
365 if (ret == EC_SUCCESS) {
366 SvcIdentity samgr = {SAMGR_HANDLE, SAMGR_TOKEN, SAMGR_COOKIE};
367 (void)UnregisterDeathCallback(samgr, endpoint->deadId);
368 (void)RegisterDeathCallback(endpoint->context, samgr, OnSamgrServerExit, endpoint, &endpoint->deadId);
369 break;
370 }
371 ++retry;
372 usleep(RETRY_INTERVAL);
373 }
374
375 if (ret != EC_SUCCESS) {
376 HILOG_FATAL(HILOG_MODULE_SAMGR, "Register endpoint<%s>, handle<%u> failed! will exit to recover!",
377 endpoint->name, endpoint->identity.handle);
378 exit(-ret);
379 }
380
381 endpoint->running = TRUE;
382 if (endpoint->identity.handle != SAMGR_HANDLE) {
383 int remain = RegisterRemoteFeatures(endpoint);
384 HILOG_INFO(HILOG_MODULE_SAMGR, "Register endpoint<%s> and iunknown finished! remain<%d> iunknown!",
385 endpoint->name, remain);
386 }
387 StartLoop(endpoint->context, Dispatch, endpoint);
388 return NULL;
389 }
390
Dispatch(const IpcContext * context,void * ipcMsg,IpcIo * data,void * argv)391 static int Dispatch(const IpcContext *context, void *ipcMsg, IpcIo *data, void *argv)
392 {
393 if (argv == NULL || ipcMsg == NULL) {
394 return EC_INVALID;
395 }
396
397 Endpoint *endpoint = (Endpoint *)argv;
398 uint32_t token = (uint32_t)INVALID_INDEX;
399 GetToken(ipcMsg, &token);
400 if (TB_CheckMessage(&endpoint->bucket) == BUCKET_BUSY) {
401 HILOG_WARN(HILOG_MODULE_SAMGR, "Flow Control <%u> is NULL", token);
402 goto ERROR;
403 }
404
405 Router *router = VECTOR_At(&endpoint->routers, token);
406 if (router == NULL) {
407 HILOG_ERROR(HILOG_MODULE_SAMGR, "Router <%s, %u> is NULL", endpoint->name, token);
408 goto ERROR;
409 }
410 Response resp = {0};
411 resp.data = endpoint;
412 Request request = {0};
413 request.msgId = token;
414 request.data = ipcMsg;
415 request.msgValue = INVALID_INDEX;
416 GetCode(ipcMsg, &request.msgValue);
417 #ifdef LITE_LINUX_BINDER_IPC
418 HandleIpc(&request, &resp);
419 #else
420 uint32 *ref = NULL;
421 int ret = SAMGR_SendSharedDirectRequest(&router->identity, &request, &resp, &ref, HandleIpc);
422 if (ret != EC_SUCCESS) {
423 HILOG_ERROR(HILOG_MODULE_SAMGR, "Router[%u] Service<%d, %d> is busy",
424 token, router->identity.serviceId, router->identity.featureId);
425 goto ERROR;
426 }
427 #endif
428 return EC_SUCCESS;
429 ERROR:
430 if (ipcMsg != NULL) {
431 FreeBuffer(endpoint->context, ipcMsg);
432 }
433 return EC_INVALID;
434 }
435
HandleIpc(const Request * request,const Response * response)436 static void HandleIpc(const Request *request, const Response *response)
437 {
438 void *ipcMsg = (void *)request->data;
439 Endpoint *endpoint = (Endpoint *)response->data;
440 Router *router = VECTOR_At(&endpoint->routers, request->msgId);
441 if (ipcMsg == NULL) {
442 return;
443 }
444
445 if (router == NULL || router->proxy == NULL || router->proxy->Invoke == NULL) {
446 FreeBuffer(endpoint->context, ipcMsg);
447 HILOG_ERROR(HILOG_MODULE_SAMGR, "Invalid IPC router!");
448 return;
449 }
450
451 uid_t uid = GetCallingUid(ipcMsg);
452 if ((strcmp(router->saName.service, SAMGR_SERVICE) != 0) &&
453 !JudgePolicy(uid, (const PolicyTrans *)(router->policy), router->policyNum)) {
454 FreeBuffer(endpoint->context, ipcMsg);
455 HILOG_ERROR(HILOG_MODULE_SAMGR, "Consumer uid<%d> has no permission to access<%s, %d, %d>!",
456 uid, router->saName.service, router->identity.serviceId, router->identity.featureId);
457 return;
458 }
459
460 IpcIo req;
461 IpcIoInitFromMsg(&req, ipcMsg);
462 IpcIo reply;
463 uint8 data[IPC_IO_DATA_MAX];
464 IpcIoInit(&reply, data, IPC_IO_DATA_MAX, MAX_OBJECT_NUM);
465 router->proxy->Invoke(router->proxy, request->msgValue, ipcMsg, &req, &reply);
466 uint32_t flag = 0;
467 GetFlag(ipcMsg, &flag);
468 if (flag == LITEIPC_FLAG_DEFAULT) {
469 SendReply(endpoint->context, ipcMsg, &reply);
470 } else {
471 FreeBuffer(endpoint->context, ipcMsg);
472 }
473 }
CompareIServerProxy(const IServerProxy * proxy1,const IServerProxy * proxy2)474 static int CompareIServerProxy(const IServerProxy *proxy1, const IServerProxy *proxy2)
475 {
476 if (proxy1 == proxy2) {
477 return 0;
478 }
479 return (proxy1 > proxy2) ? 1 : -1;
480 }
481
GetIServerProxy(const Router * router)482 static IServerProxy *GetIServerProxy(const Router *router)
483 {
484 if (router == NULL) {
485 return NULL;
486 }
487 return router->proxy;
488 }
489
RegisterIdentity(const IpcContext * context,const SaName * saName,SvcIdentity * saInfo,PolicyTrans ** policy,uint32 * policyNum)490 static int RegisterIdentity(const IpcContext *context, const SaName *saName, SvcIdentity *saInfo,
491 PolicyTrans **policy, uint32 *policyNum)
492 {
493 IpcIo req;
494 uint8 data[MAX_DATA_LEN];
495 IpcIoInit(&req, data, MAX_DATA_LEN, 0);
496 IpcIoPushUint32(&req, RES_FEATURE);
497 IpcIoPushUint32(&req, OP_PUT);
498 IpcIoPushString(&req, saName->service);
499 IpcIoPushBool(&req, saName->feature == NULL);
500 if (saName->feature != NULL) {
501 IpcIoPushString(&req, saName->feature);
502 }
503 IpcIoPushUint32(&req, saInfo->token);
504 IpcIo reply;
505 void *replyBuf = NULL;
506 SvcIdentity samgr = {SAMGR_HANDLE, SAMGR_TOKEN, SAMGR_COOKIE};
507 int ret = Transact(context, samgr, INVALID_INDEX, &req, &reply, LITEIPC_FLAG_DEFAULT, (uintptr_t *)&replyBuf);
508 ret = -ret;
509 if (ret == LITEIPC_OK) {
510 ret = IpcIoPopInt32(&reply);
511 }
512 if (ret == EC_SUCCESS) {
513 IpcIoPopSvc(&reply);
514 GetRemotePolicy(&reply, policy, policyNum);
515 }
516 if (replyBuf != NULL) {
517 FreeBuffer(context, replyBuf);
518 }
519 return ret;
520 }
521
RegisterRemoteFeatures(Endpoint * endpoint)522 static int RegisterRemoteFeatures(Endpoint *endpoint)
523 {
524 int nums = 0;
525 int size = VECTOR_Size(&endpoint->routers);
526 int i;
527 SvcIdentity identity;
528 for (i = 0; i < size; ++i) {
529 Router *router = VECTOR_At(&endpoint->routers, i);
530 if (router == NULL) {
531 continue;
532 }
533
534 identity.handle = endpoint->identity.handle;
535 identity.token = i;
536 int ret = RegisterIdentity(endpoint->context, &(router->saName), &identity, &(router->policy),
537 &(router->policyNum));
538 if (ret == EC_SUCCESS) {
539 ++nums;
540 }
541 HILOG_DEBUG(HILOG_MODULE_SAMGR, "RegisterRemoteFeatures<%s, %s> ret:%d",
542 router->saName.service, router->saName.feature, ret);
543 }
544 return VECTOR_Num(&endpoint->routers) - nums;
545 }
546
RegisterRemoteEndpoint(const IpcContext * context,SvcIdentity * identity)547 static int RegisterRemoteEndpoint(const IpcContext *context, SvcIdentity *identity)
548 {
549 IpcIo req;
550 uint8 data[MAX_DATA_LEN];
551 IpcIoInit(&req, data, MAX_DATA_LEN, 0);
552 IpcIoPushUint32(&req, RES_ENDPOINT);
553 IpcIoPushUint32(&req, OP_POST);
554 uint32 retry = 0;
555 while (retry < MAX_RETRY_TIMES) {
556 ++retry;
557 IpcIo reply;
558 void *replyBuf = NULL;
559 SvcIdentity samgr = {SAMGR_HANDLE, SAMGR_TOKEN, SAMGR_COOKIE};
560 int err = Transact(context, samgr, INVALID_INDEX, &req, &reply, LITEIPC_FLAG_DEFAULT, (uintptr_t *)&replyBuf);
561 if (err == LITEIPC_OK) {
562 identity->handle = IpcIoPopUint32(&reply);
563 if (replyBuf != NULL) {
564 FreeBuffer(context, replyBuf);
565 }
566 if (identity->handle == (uint32)INVALID_INDEX) {
567 continue;
568 }
569 return EC_SUCCESS;
570 }
571 usleep(RETRY_INTERVAL);
572 }
573 return EC_FAILURE;
574 }
575
OnSamgrServerExit(const IpcContext * context,void * ipcMsg,IpcIo * data,void * argv)576 static int OnSamgrServerExit(const IpcContext *context, void *ipcMsg, IpcIo *data, void *argv)
577 {
578 (void)data;
579 HILOG_ERROR(HILOG_MODULE_SAMGR, "Disconnect to samgr server!");
580 Endpoint *endpoint = (Endpoint *)argv;
581 if (endpoint == NULL || endpoint->registerEP == NULL) {
582 return EC_FAILURE;
583 }
584 if (ipcMsg != NULL) {
585 FreeBuffer(endpoint->context, ipcMsg);
586 }
587 int size = VECTOR_Size(&endpoint->routers);
588 int i;
589 for (i = 0; i < size; i++) {
590 Router *router = VECTOR_At(&endpoint->routers, i);
591 if (router == NULL) {
592 continue;
593 }
594 SAMGR_Free(router->policy);
595 router->policy = NULL;
596 router->policyNum = 0;
597 }
598
599 SvcIdentity old = endpoint->identity;
600 while (endpoint->registerEP(endpoint->context, &endpoint->identity) != EC_SUCCESS) {
601 HILOG_ERROR(HILOG_MODULE_SAMGR, "Reconnect to samgr server failed!");
602 usleep(RETRY_INTERVAL);
603 }
604 SvcIdentity new = endpoint->identity;
605 if (old.handle != new.handle || old.cookie != new.cookie || old.token != new.token) {
606 HILOG_ERROR(HILOG_MODULE_SAMGR, "Samgr server identity error!");
607 exit(-1);
608 }
609
610 SvcIdentity identity = {SAMGR_HANDLE, SAMGR_TOKEN, SAMGR_COOKIE};
611 (void)UnregisterDeathCallback(identity, endpoint->deadId);
612 (void)RegisterDeathCallback(endpoint->context, identity, OnSamgrServerExit, endpoint, &endpoint->deadId);
613 int remain = RegisterRemoteFeatures(endpoint);
614 HILOG_INFO(HILOG_MODULE_SAMGR, "Reconnect and register finished! remain<%d> iunknown!", remain);
615 return EC_SUCCESS;
616 }
617
GetRemotePolicy(IpcIo * reply,PolicyTrans ** policy,uint32 * policyNum)618 static void GetRemotePolicy(IpcIo *reply, PolicyTrans **policy, uint32 *policyNum)
619 {
620 if (reply == NULL) {
621 return;
622 }
623 uint32 i;
624 uint32 j;
625 *policyNum = IpcIoPopUint32(reply);
626 if (*policyNum > MAX_POLICY_NUM) {
627 *policyNum = MAX_POLICY_NUM;
628 }
629 SAMGR_Free(*policy);
630 if (*policyNum == 0) {
631 *policy = NULL;
632 return;
633 }
634 *policy = (PolicyTrans *)SAMGR_Malloc(sizeof(PolicyTrans) * (*policyNum));
635 if (*policy == NULL) {
636 return;
637 }
638 for (i = 0; i < *policyNum; i++) {
639 (*policy)[i].type = IpcIoPopInt32(reply);
640 switch ((*policy)[i].type) {
641 case RANGE:
642 (*policy)[i].uidMin = IpcIoPopInt32(reply);
643 (*policy)[i].uidMax = IpcIoPopInt32(reply);
644 break;
645 case FIXED:
646 for (j = 0; j < UID_SIZE; j++) {
647 (*policy)[i].fixedUid[j] = IpcIoPopInt32(reply);
648 }
649 break;
650 case BUNDLENAME:
651 (*policy)[i].fixedUid[0] = IpcIoPopInt32(reply);
652 break;
653 default:
654 break;
655 }
656 }
657 }
658
JudgePolicy(uid_t callingUid,const PolicyTrans * policy,uint32 policyNum)659 static boolean JudgePolicy(uid_t callingUid, const PolicyTrans *policy, uint32 policyNum)
660 {
661 if (policy == NULL) {
662 HILOG_ERROR(HILOG_MODULE_SAMGR, "Policy is NULL! Num is %u", policyNum);
663 return FALSE;
664 }
665
666 uint32 i;
667 for (i = 0; i < policyNum; i++) {
668 if (policy[i].type == RANGE && callingUid >= policy[i].uidMin && callingUid <= policy[i].uidMax) {
669 return TRUE;
670 }
671 if (policy[i].type == FIXED && SearchFixedPolicy(callingUid, policy[i])) {
672 return TRUE;
673 }
674 }
675 return FALSE;
676 }
677
SearchFixedPolicy(uid_t callingUid,PolicyTrans policy)678 static boolean SearchFixedPolicy(uid_t callingUid, PolicyTrans policy)
679 {
680 int i;
681 for (i = 0; i < UID_SIZE; i++) {
682 if (callingUid == policy.fixedUid[i]) {
683 return TRUE;
684 }
685 }
686 return FALSE;
687 }