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 }