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