• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }