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 "samgr_server.h"
16 
17 #include <fcntl.h>
18 #include <log.h>
19 #include <ohos_errno.h>
20 #include <ohos_init.h>
21 #include <ohos_types.h>
22 #include <pthread.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/stat.h>
26 
27 #include "cJSON.h"
28 #ifdef MINI_SAMGR_LITE_RPC
29 #include "dbinder_service.h"
30 #endif
31 #include "default_client.h"
32 #include "ipc_skeleton.h"
33 #include "memory_adapter.h"
34 #include "policy_define.h"
35 #include "samgr_lite.h"
36 #include "securec.h"
37 #include "stdio.h"
38 #include "thread_adapter.h"
39 #include "utils_list.h"
40 
41 #undef LOG_TAG
42 #undef LOG_DOMAIN
43 #define LOG_TAG "Samgr"
44 #define LOG_DOMAIN 0xD001800
45 
46 typedef int(*ProcFunc)(SamgrServer *server, int32 option, void *origin, IpcIo *req, IpcIo *reply);
47 #define MAX_SA_SIZE 0x100
48 #define RETRY_TIMES 3
49 #define RETRY_INTERVAL 1
50 #define MINI_SA_RPC_ID 16
51 #define UID_HAP 10000
52 #define MAX_SYSCAP_NUM_PER_REPLY 118
53 
54 static const char *GetName(Service *service);
55 static BOOL Initialize(Service *service, Identity identity);
56 static TaskConfig GetTaskConfig(Service *service);
57 static BOOL MessageHandle(Service *service, Request *request);
58 static int32 Invoke(IServerProxy *iProxy, int funcId, void *origin, IpcIo *req, IpcIo *reply);
59 static void OnEndpointExit(void* argv);
60 static int ProcEndpoint(SamgrServer *server, int32 option, void *origin, IpcIo *req, IpcIo *reply);
61 static int32 ProcPutFeature(SamgrServer *server, const void *origin, IpcIo *req, IpcIo *reply, SvcIdentity *identity);
62 static int32 ProcGetFeature(SamgrServer *server, const void *origin, IpcIo *req, IpcIo *reply, SvcIdentity *identity);
63 static int ProcFeature(SamgrServer *server, int32 option, void *origin, IpcIo *req, IpcIo *reply);
64 static int RegisterSamgrEndpoint(SvcIdentity* identity, int token, const char *service, const char *feature);
65 static void TransmitPolicy(int ret, const SvcIdentity* identity, IpcIo *reply,
66                            const PolicyTrans *policy, uint32 policyNum);
67 static void TransmitFixedPolicy(IpcIo *reply, PolicyTrans policy);
68 static IpcAuthInterface *GetIpcAuthInterface(void);
69 static int ProcSysCap(SamgrServer *server, int32 option, void *origin, IpcIo *req, IpcIo *reply);
70 static void ParseSysCap(void);
71 
72 static SamgrServer g_server = {
73         .GetName = GetName,
74         .Initialize = Initialize,
75         .GetTaskConfig = GetTaskConfig,
76         .MessageHandle = MessageHandle,
77         SERVER_IPROXY_IMPL_BEGIN,
78         .Invoke = Invoke,
79         IPROXY_END,
80 };
81 
82 static ProcFunc g_functions[] = {
83         [RES_ENDPOINT] = ProcEndpoint,
84         [RES_FEATURE] = ProcFeature,
85         [RES_SYSCAP] = ProcSysCap,
86 };
87 
88 static struct UTILS_DL_LIST g_saList;
89 pthread_mutex_t g_saMutex = PTHREAD_MUTEX_INITIALIZER;
90 
GetSaNodeBySaName(const char * service,const char * feature)91 SaNode *GetSaNodeBySaName(const char *service, const char *feature)
92 {
93     SaNode *node = NULL;
94     SaNode *retNode = NULL;
95     pthread_mutex_lock(&g_saMutex);
96     UTILS_DL_LIST_FOR_EACH_ENTRY(node, &g_saList, SaNode, list)
97     {
98         if (strncmp(node->saName.service, service, MAX_NAME_LEN) == 0) {
99             if (feature != NULL) {
100                 if ((node->saName.feature != NULL) && (strncmp(node->saName.feature, feature, MAX_NAME_LEN) == 0)) {
101                     retNode = node;
102                 }
103             } else {
104                 if (node->saName.feature == NULL) {
105                     retNode = node;
106                 }
107             }
108             break;
109         }
110     }
111     pthread_mutex_unlock(&g_saMutex);
112     return retNode;
113 }
114 
GetSaNodeBySaId(uintptr_t saId)115 SaNode *GetSaNodeBySaId(uintptr_t saId)
116 {
117     SaNode *node = NULL;
118     SaNode *retNode = NULL;
119 
120     pthread_mutex_lock(&g_saMutex);
121     UTILS_DL_LIST_FOR_EACH_ENTRY(node, &g_saList, SaNode, list)
122     {
123         if (node->saId == saId) {
124             retNode = node;
125             break;
126         }
127     }
128     pthread_mutex_unlock(&g_saMutex);
129     return retNode;
130 }
131 #ifdef MINI_SAMGR_LITE_RPC
RpcStartSamgr(void)132 void RpcStartSamgr(void)
133 {
134     pthread_setname_np(pthread_self(), "rpc_server");
135     SvcIdentity target = {
136             .cookie = 0
137     };
138     (void)SetContextObject(target);
139     StartDBinderService();
140 }
141 #endif
GetSystemAbilityById(int32_t saId,IpcIo * reply)142 int32_t GetSystemAbilityById(int32_t saId, IpcIo *reply)
143 {
144     SaNode *saNode = GetSaNodeBySaId(saId);
145     if (saNode == NULL) {
146         return EC_FAILURE;
147     }
148     SvcIdentity sid = SASTORA_Find(&g_server.store, saNode->saName.service, saNode->saName.feature);
149     WriteRemoteObject(reply, &sid);
150     reply->bufferCur = reply->bufferBase;
151     return EC_SUCCESS;
152 }
153 
GetSysCapName(const SysCapImpl * serviceImpl)154 static const char *GetSysCapName(const SysCapImpl *serviceImpl)
155 {
156     if (serviceImpl == NULL) {
157         return NULL;
158     }
159     return serviceImpl->name;
160 }
161 
162 #ifdef MINI_SAMGR_LITE_RPC
InitializeGSaList(void)163 static void InitializeGSaList(void)
164 {
165     SaNode *saNode = (SaNode *)malloc(sizeof(SaNode));
166     if (saNode == NULL) {
167         HILOG_ERROR(HILOG_MODULE_SAMGR, "malloc samap failed");
168         return;
169     }
170     saNode->saName.service = "mini_sa_rpc";
171     saNode->saName.feature = NULL;
172     saNode->saId = MINI_SA_RPC_ID;
173     UtilsListInit(&g_saList);
174     UtilsListAdd(&g_saList, &saNode->list);
175 }
176 #endif
177 
InitializeRegistry(void)178 static void InitializeRegistry(void)
179 {
180 #ifdef MINI_SAMGR_LITE_RPC
181     InitializeGSaList();
182 #endif
183     g_server.mtx = MUTEX_InitValue();
184     SASTORA_Init(&g_server.store);
185     g_server.samgr = SAMGR_CreateEndpoint("samgr", RegisterSamgrEndpoint);
186     SAMGR_GetInstance()->RegisterService((Service *)&g_server);
187     g_server.sysCapMtx = MUTEX_InitValue();
188     g_server.sysCapabilitys = VECTOR_Make((VECTOR_Key)GetSysCapName, (VECTOR_Compare)strcmp);
189 #ifndef MINI_SAMGR_LITE_RPC
190     ParseSysCap();
191 #endif
192 }
193 SYS_SERVICE_INIT(InitializeRegistry);
194 
CanRequest(const void * origin)195 static BOOL CanRequest(const void *origin)
196 {
197 #ifndef MINI_SAMGR_LITE_RPC
198     pid_t uid = GetCallingUid();
199     return uid < UID_HAP;
200 #else
201     return TRUE;
202 #endif
203 }
204 
GetName(Service * service)205 static const char *GetName(Service *service)
206 {
207     (void)service;
208     return SAMGR_SERVICE;
209 }
210 
Initialize(Service * service,Identity identity)211 static BOOL Initialize(Service *service, Identity identity)
212 {
213     SamgrServer *server = (SamgrServer *)service;
214     server->identity = identity;
215     SaName saName = {SAMGR_SERVICE, NULL};
216     SAMGR_AddRouter(server->samgr, &saName, &server->identity, GET_IUNKNOWN(*server));
217     return TRUE;
218 }
219 
MessageHandle(Service * service,Request * request)220 static BOOL MessageHandle(Service *service, Request *request)
221 {
222     SamgrServer *server = (SamgrServer *)service;
223     switch (request->msgId) {
224         case MSG_CLEAN:
225             MUTEX_Lock(server->mtx);
226             SASTORA_ClearByPid(&server->store, request->msgValue);
227             MUTEX_Unlock(server->mtx);
228             break;
229         default:
230             break;
231     }
232     return TRUE;
233 }
234 
GetTaskConfig(Service * service)235 static TaskConfig GetTaskConfig(Service *service)
236 {
237     (void)service;
238     TaskConfig config = {LEVEL_HIGH, PRI_BUTT - 1, 0x4000, 20, SINGLE_TASK}; // Cannot use PRI_BUTT directly, so minus 1
239     return config;
240 }
241 
Invoke(IServerProxy * iProxy,int funcId,void * origin,IpcIo * req,IpcIo * reply)242 static int32 Invoke(IServerProxy *iProxy, int funcId, void *origin, IpcIo *req, IpcIo *reply)
243 {
244     SamgrServer *server = GET_OBJECT(iProxy, SamgrServer, iUnknown);
245     uint32_t resource;
246     ReadUint32(req, &resource);
247     int32_t option;
248     ReadInt32(req, &option);
249     if (server == NULL || resource >= RES_BUTT || g_functions[resource] == NULL) {
250         HILOG_ERROR(HILOG_MODULE_SAMGR, "Invalid Msg<%d, %u, %d>", resource, option, funcId);
251         return EC_INVALID;
252     }
253     return g_functions[resource](server, option, origin, req, reply);
254 }
255 
AddEndpoint(SvcIdentity identity,const char * service,const char * feature)256 int AddEndpoint(SvcIdentity identity, const char *service, const char *feature)
257 {
258     return SASTORA_Save(&g_server.store, service, feature, &identity);
259 }
260 
ProcEndpoint(SamgrServer * server,int32 option,void * origin,IpcIo * req,IpcIo * reply)261 static int ProcEndpoint(SamgrServer *server, int32 option, void *origin, IpcIo *req, IpcIo *reply)
262 {
263     if (option != OP_POST) {
264         WriteInt32(reply, INVALID_INDEX);
265         return EC_FAILURE;
266     }
267     pid_t pid = GetCallingPid();
268     PidHandle handle;
269     MUTEX_Lock(server->mtx);
270     int index = SASTORA_FindHandleByPid(&g_server.store, pid, &handle);
271     if (index == INVALID_INDEX) {
272         SvcIdentity identity = {(int32)INVALID_INDEX, (uint32)INVALID_INDEX, (uint32)INVALID_INDEX};
273 #ifndef MINI_SAMGR_LITE_RPC
274         bool ret = ReadRemoteObject(req, &identity);
275         if (ret) {
276             // identity.handle <= 0 In-process communication,identity.handle > 0 Cross-process communication
277             if ((identity.handle <= 0) && (identity.cookie != 0)) {
278                 identity.handle = 0;
279             }
280         } else {
281             WriteInt32(reply, INVALID_INDEX);
282             return EC_FAILURE;
283         }
284 #endif
285         handle.uid = GetCallingUid();
286         handle.pid = pid;
287         handle.handle = identity.handle;
288         handle.cookie = identity.cookie;
289         handle.deadId = INVALID_INDEX;
290         (void)SASTORA_SaveHandleByPid(&server->store, handle);
291         (void)RemoveDeathRecipient(identity, handle.deadId);
292         (void)AddDeathRecipient(identity, OnEndpointExit, (void*)((uintptr_t)pid), &handle.deadId);
293     }
294     MUTEX_Unlock(server->mtx);
295     WriteInt32(reply, handle.handle);
296     HILOG_INFO(HILOG_MODULE_SAMGR, "Register Endpoint<%d, %d, %d>", handle.pid, handle.handle, handle.deadId);
297     return EC_SUCCESS;
298 }
299 
ProcPutFeature(SamgrServer * server,const void * origin,IpcIo * req,IpcIo * reply,SvcIdentity * identity)300 static int32 ProcPutFeature(SamgrServer *server, const void *origin, IpcIo *req, IpcIo *reply, SvcIdentity *identity)
301 {
302     size_t len = 0;
303     char *service = (char *)ReadString(req, &len);
304     if (service == NULL || len == 0) {
305         WriteInt32(reply, EC_INVALID);
306         return EC_INVALID;
307     }
308     pid_t pid = GetCallingPid();
309     uid_t uid = GetCallingUid();
310     bool isFeature;
311     ReadBool(req, &isFeature);
312     char *feature = NULL;
313     if (!isFeature) {
314         feature = (char *)ReadString(req, &len);
315     }
316     MUTEX_Lock(server->mtx);
317     PidHandle handle;
318     int index = SASTORA_FindHandleByUidPid(&server->store, uid, pid, &handle);
319     if (index == INVALID_INDEX) {
320         MUTEX_Unlock(server->mtx);
321         HILOG_ERROR(HILOG_MODULE_SAMGR, "Endpoint[%d] is not register", pid);
322         WriteInt32(reply, EC_NOSERVICE);
323         return EC_NOSERVICE;
324     }
325     *identity = SASTORA_Find(&server->store, service, feature);
326     if (identity->handle != INVALID_INDEX && identity->handle != handle.handle) {
327         MUTEX_Unlock(server->mtx);
328         WriteInt32(reply, EC_INVALID);
329         return EC_INVALID;
330     }
331 #ifndef MINI_SAMGR_LITE_RPC
332     ReadUint32(req, &identity->token);
333 #else
334     identity->token = ReadPointer(req);
335 #endif
336     identity->handle = (int32_t)handle.handle;
337     identity->cookie = handle.cookie;
338     PolicyTrans *policy = NULL;
339     RegParams regParams = {service, feature, handle.uid, handle.pid};
340     uint32 policyNum = 0;
341     int ret = g_server.ipcAuth->GetCommunicationStrategy(regParams, &policy, &policyNum);
342     if (ret != EC_SUCCESS || policy == NULL) {
343         MUTEX_Unlock(server->mtx);
344         SAMGR_Free(policy);
345         HILOG_DEBUG(HILOG_MODULE_SAMGR, "Remote Get Communication Strategy<%s, %s> No Permission<%d>!",
346                     service, feature, ret);
347         WriteInt32(reply, EC_PERMISSION);
348         return EC_PERMISSION;
349     }
350     ret = SASTORA_Save(&server->store, service, feature, identity);
351     MUTEX_Unlock(server->mtx);
352     HILOG_DEBUG(HILOG_MODULE_SAMGR, "Register Feature<%s, %s> pid<%d>, id<%d, %d> ret:%d",
353                 service, feature, pid, identity->handle, identity->token, ret);
354     TransmitPolicy(ret, identity, reply, policy, policyNum);
355     SAMGR_Free(policy);
356     return ret;
357 }
358 
TransmitPolicy(int ret,const SvcIdentity * identity,IpcIo * reply,const PolicyTrans * policy,uint32 policyNum)359 static void TransmitPolicy(int ret, const SvcIdentity* identity, IpcIo *reply,
360                            const PolicyTrans *policy, uint32 policyNum)
361 {
362     if (identity == NULL || reply == NULL || policy == NULL) {
363         WriteInt32(reply, EC_INVALID);
364         return;
365     }
366     if (ret != EC_SUCCESS) {
367         WriteInt32(reply, ret);
368         return;
369     }
370     WriteInt32(reply, ret);
371     WriteRemoteObject(reply, identity);
372     WriteUint32(reply, policyNum);
373     uint32 i;
374     for (i = 0; i < policyNum; i++) {
375         WriteInt32(reply, policy[i].type);
376         switch (policy[i].type) {
377             case RANGE:
378                 WriteInt32(reply, policy[i].uidMin);
379                 WriteInt32(reply, policy[i].uidMax);
380                 break;
381             case FIXED:
382                 TransmitFixedPolicy(reply, policy[i]);
383                 break;
384             case BUNDLENAME:
385                 WriteInt32(reply, policy[i].fixedUid[0]);
386                 break;
387             default:
388                 break;
389         }
390     }
391 }
392 
TransmitFixedPolicy(IpcIo * reply,PolicyTrans policy)393 static void TransmitFixedPolicy(IpcIo *reply, PolicyTrans policy)
394 {
395     if (reply == NULL) {
396         return;
397     }
398     uint32 i;
399     for (i = 0; i < UID_SIZE; i++) {
400         WriteInt32(reply, policy.fixedUid[i]);
401     }
402 }
403 
ProcGetFeature(SamgrServer * server,const void * origin,IpcIo * req,IpcIo * reply,SvcIdentity * identity)404 static int32 ProcGetFeature(SamgrServer *server, const void *origin, IpcIo *req, IpcIo *reply, SvcIdentity *identity)
405 {
406     size_t len = 0;
407     char *service = (char *)ReadString(req, &len);
408     if (service == NULL || len == 0) {
409         WriteInt32(reply, EC_INVALID);
410         return EC_INVALID;
411     }
412     bool isFeature;
413     ReadBool(req, &isFeature);
414     char *feature = NULL;
415     if (!isFeature) {
416         feature = (char *)ReadString(req, &len);
417     }
418     MUTEX_Lock(server->mtx);
419     *identity = SASTORA_Find(&server->store, service, feature);
420     if (identity->handle == INVALID_INDEX) {
421         MUTEX_Unlock(server->mtx);
422         HILOG_DEBUG(HILOG_MODULE_SAMGR, "Cannot Find Feature<%s, %s> id<%d, %d> ret:%d",
423                     service, feature, identity->handle, identity->token, EC_NOSERVICE);
424         return EC_NOSERVICE;
425     }
426     PidHandle providerPid = SASTORA_FindPidHandleByIpcHandle(&server->store, identity->handle);
427     MUTEX_Unlock(server->mtx);
428     if (providerPid.pid == INVALID_INDEX || providerPid.uid == INVALID_INDEX) {
429         HILOG_DEBUG(HILOG_MODULE_SAMGR, "Cannot Find PidHandle<%s, %s> id<%d, %d> ret:%d",
430                     service, feature, identity->handle, identity->token, EC_FAILURE);
431         return EC_FAILURE;
432     }
433     AuthParams authParams = {
434             .providerService = service,
435             .providerfeature = feature,
436             .consumerPid = GetCallingPid(),
437             .consumerUid = GetCallingUid(),
438             .providerPid = providerPid.pid,
439             .providerUid = providerPid.uid
440     };
441     int isAuth = g_server.ipcAuth->IsCommunicationAllowed(authParams);
442     HILOG_DEBUG(HILOG_MODULE_SAMGR, "Judge Auth<%s, %s> ret:%d", service, feature, isAuth);
443     return isAuth;
444 }
445 
ProcFeature(SamgrServer * server,int32 option,void * origin,IpcIo * req,IpcIo * reply)446 static int ProcFeature(SamgrServer *server, int32 option, void *origin, IpcIo *req, IpcIo *reply)
447 {
448     if (option != OP_PUT && option != OP_GET) {
449         WriteInt32(reply, EC_INVALID);
450         return EC_INVALID;
451     }
452 
453     if (g_server.ipcAuth == NULL) {
454         g_server.ipcAuth = GetIpcAuthInterface();
455     }
456     if (g_server.ipcAuth == NULL) {
457         WriteInt32(reply, EC_NOINIT);
458         return EC_NOINIT;
459     }
460 
461     int ret = EC_SUCCESS;
462     SvcIdentity identity = {INVALID_INDEX, INVALID_INDEX, INVALID_INDEX};
463     if (option == OP_PUT) {
464         ret = ProcPutFeature(server, origin, req, reply, &identity);
465     }
466     if (ret != EC_SUCCESS) {
467         return ret;
468     }
469 
470     if (option == OP_GET) {
471         ret = ProcGetFeature(server, origin, req, reply, &identity);
472         WriteInt32(reply, ret);
473         if (ret == EC_SUCCESS) {
474             // The WriteRemoteObject identity.token parameter is invalid
475             WriteRemoteObject(reply, &identity);
476             WriteUint32(reply, (uint32_t)identity.token);
477         }
478     }
479     return ret;
480 }
481 
ProcAddSysCap(SamgrServer * server,IpcIo * req)482 static int32 ProcAddSysCap(SamgrServer *server, IpcIo *req)
483 {
484     size_t len = 0;
485     char *sysCap = (char *)ReadString(req, &len);
486     if (sysCap == NULL || len == 0 || len > MAX_SYSCAP_NAME_LEN) {
487         HILOG_ERROR(HILOG_MODULE_SAMGR, "ProcAddSysCap sysCap invalid");
488         return EC_INVALID;
489     }
490     MUTEX_Lock(server->sysCapMtx);
491     Vector *sysCapablitys = &(server->sysCapabilitys);
492     int16 pos = VECTOR_FindByKey(sysCapablitys, (void *)sysCap);
493     if (pos < 0) {
494         MUTEX_Unlock(server->sysCapMtx);
495         return EC_FAILURE;
496     }
497     SysCapImpl *serviceImpl = (SysCapImpl *)VECTOR_At(sysCapablitys, pos);
498     if (serviceImpl == NULL) {
499         MUTEX_Unlock(server->sysCapMtx);
500         return EC_FAILURE;
501     }
502     serviceImpl->isRegister = TRUE;
503     MUTEX_Unlock(server->sysCapMtx);
504     return EC_SUCCESS;
505 }
506 
ProcGetSysCap(SamgrServer * server,IpcIo * req)507 static BOOL ProcGetSysCap(SamgrServer *server, IpcIo *req)
508 {
509     size_t len = 0;
510     char *sysCap = (char *)ReadString(req, &len);
511     if (sysCap == NULL || len == 0 || len > MAX_SYSCAP_NAME_LEN) {
512         HILOG_ERROR(HILOG_MODULE_SAMGR, "ProcGetSysCap sysCap invalid");
513         return FALSE;
514     }
515     MUTEX_Lock(server->sysCapMtx);
516     Vector *sysCapablitys = &(server->sysCapabilitys);
517     int16 pos = VECTOR_FindByKey(sysCapablitys, (void *)sysCap);
518     if (pos < 0) {
519         MUTEX_Unlock(server->sysCapMtx);
520         return FALSE;
521     }
522     SysCapImpl *serviceImpl = (SysCapImpl *)VECTOR_At(sysCapablitys, pos);
523     if (serviceImpl == NULL) {
524         MUTEX_Unlock(server->sysCapMtx);
525         return FALSE;
526     }
527 
528     BOOL res = (serviceImpl->isRegister == TRUE);
529     MUTEX_Unlock(server->sysCapMtx);
530     return res;
531 }
532 
GetReplyNumAndNextReqIdx(Vector * sysCapablitys,int32 startIdx,int32 * nextRequestIdx)533 static int32 GetReplyNumAndNextReqIdx(Vector *sysCapablitys, int32 startIdx, int32 *nextRequestIdx)
534 {
535     int32 registerNum = 0;
536     int32 size = VECTOR_Num(sysCapablitys);
537     int32 i = startIdx;
538     for (; i < size && registerNum < MAX_SYSCAP_NUM_PER_REPLY; i++) {
539         SysCapImpl *serviceImpl = (SysCapImpl *)VECTOR_At(sysCapablitys, i);
540         if (serviceImpl->isRegister == FALSE) {
541             continue;
542         }
543         registerNum++;
544     }
545     *nextRequestIdx = i;
546     return registerNum;
547 }
548 
ProcGetAllSysCap(SamgrServer * server,IpcIo * req,IpcIo * reply)549 void ProcGetAllSysCap(SamgrServer *server, IpcIo *req, IpcIo *reply)
550 {
551     uint32_t startIdx;
552     ReadUint32(req, &startIdx);
553     MUTEX_Lock(server->sysCapMtx);
554     Vector *sysCapablitys = &(server->sysCapabilitys);
555     int32 size = VECTOR_Num(sysCapablitys);
556     if (size == INVALID_INDEX) {
557         WriteInt32(reply, EC_FAILURE);
558         WriteBool(reply, TRUE);
559         WriteUint32(reply, startIdx);
560         WriteUint32(reply, 0);
561         MUTEX_Unlock(server->sysCapMtx);
562         return;
563     }
564     int32 nextRequestIdx = startIdx;
565     int32 replyNum = GetReplyNumAndNextReqIdx(sysCapablitys, startIdx, &nextRequestIdx);
566     HILOG_DEBUG(HILOG_MODULE_SAMGR, "ProcGetAllSysCap replyNum: %d, size: %d, startIdx: %u, nextRequestIdx: %d",
567                 replyNum, size, startIdx, nextRequestIdx);
568     WriteInt32(reply, EC_SUCCESS);
569     // indicate is the last reply
570     WriteBool(reply, nextRequestIdx == size);
571     // indicate is the next start idx
572     WriteUint32(reply, nextRequestIdx);
573     WriteUint32(reply, replyNum);
574     int32 cnt = 0;
575     int32 i = startIdx;
576     for (; i < size && cnt < replyNum; i++) {
577         SysCapImpl *serviceImpl = (SysCapImpl *)VECTOR_At(sysCapablitys, i);
578         if (serviceImpl->isRegister == FALSE) {
579             continue;
580         }
581         WriteString(reply, serviceImpl->name);
582         cnt++;
583     }
584     MUTEX_Unlock(server->sysCapMtx);
585 }
586 
ProcSysCap(SamgrServer * server,int32 option,void * origin,IpcIo * req,IpcIo * reply)587 static int ProcSysCap(SamgrServer *server, int32 option, void *origin, IpcIo *req, IpcIo *reply)
588 {
589     if (CanRequest(origin) == FALSE) {
590         HILOG_ERROR(HILOG_MODULE_SAMGR, "ProcSysCap no permission");
591         WriteInt32(reply, EC_PERMISSION);
592         return EC_PERMISSION;
593     }
594     if (option != OP_PUT && option != OP_GET && option != OP_ALL) {
595         WriteInt32(reply, EC_INVALID);
596         return EC_INVALID;
597     }
598     HILOG_DEBUG(HILOG_MODULE_SAMGR, "ProcSysCap option: %d begin", option);
599     if (option == OP_PUT) {
600         int32 ret = ProcAddSysCap(server, req);
601         WriteInt32(reply, ret);
602     } else if (option == OP_GET) {
603         BOOL ret = ProcGetSysCap(server, req);
604         WriteInt32(reply, EC_SUCCESS);
605         WriteBool(reply, ret);
606     } else if (option == OP_ALL) {
607         ProcGetAllSysCap(server, req, reply);
608     } else {
609         HILOG_WARN(HILOG_MODULE_SAMGR, "ProcSysCap error option: %d", option);
610         WriteInt32(reply, EC_INVALID);
611         return EC_INVALID;
612     }
613     HILOG_DEBUG(HILOG_MODULE_SAMGR, "ProcSysCap end");
614     return EC_SUCCESS;
615 }
616 
RegisterSamgrEndpoint(SvcIdentity * identity,int token,const char * service,const char * feature)617 static int RegisterSamgrEndpoint(SvcIdentity* identity, int token, const char *service, const char *feature)
618 {
619 #ifndef MINI_SAMGR_LITE_RPC
620     int ret = SetContextObject(*identity);
621     if (ret != EC_SUCCESS) {
622         HILOG_FATAL(HILOG_MODULE_SAMGR, "Set sa manager<%d> failed!", ret);
623         return EC_INVALID;
624     }
625 #endif
626     identity->handle = SAMGR_HANDLE;
627     identity->token = SAMGR_TOKEN;
628     identity->cookie = SAMGR_COOKIE;
629     return EC_SUCCESS;
630 }
631 
OnEndpointExit(void * argv)632 static void OnEndpointExit(void* argv)
633 {
634     pid_t pid = (pid_t)((uintptr_t)argv);
635     Request request = {0};
636     request.msgId = MSG_CLEAN;
637     request.msgValue = pid;
638     int retry = RETRY_TIMES;
639     int ret = EC_INVALID;
640     while (retry > 0) {
641         ret = SAMGR_SendRequest(&g_server.identity, &request, NULL);
642         if (ret == EC_SUCCESS) {
643             break;
644         }
645         sleep(RETRY_INTERVAL);
646         --retry;
647     }
648 
649     PidHandle handle;
650     int err = SASTORA_FindHandleByPid(&g_server.store, pid, &handle);
651     if (err != INVALID_INDEX) {
652         SvcIdentity target = {INVALID_INDEX, INVALID_INDEX, INVALID_INDEX};
653         target.handle = handle.handle;
654         ReleaseSvc(target);
655     }
656     HILOG_ERROR(HILOG_MODULE_SAMGR, "IPC pid<%d> exit! send clean request retry(%d), ret(%d)!", pid, retry, ret);
657 }
658 
GetIpcAuthInterface(void)659 static IpcAuthInterface *GetIpcAuthInterface(void)
660 {
661     IpcAuthInterface *ipcAuth = NULL;
662     IUnknown *iUnknown = SAMGR_GetInstance()->GetFeatureApi(PERMISSION_SERVICE, IPCAUTH);
663     if (iUnknown == NULL) {
664         HILOG_ERROR(HILOG_MODULE_SAMGR, "Get IpcAuthInterface: IUnknown NULL");
665         return NULL;
666     }
667     (void)iUnknown->QueryInterface(iUnknown, DEFAULT_VERSION, (void **)&ipcAuth);
668     return ipcAuth;
669 }
670 
GetJsonStream()671 static cJSON *GetJsonStream()
672 {
673     const char *path = "/etc/system_capability.json";
674     struct stat fileInfo;
675     int32_t size = 0;
676 
677     if (stat(path, &fileInfo) != 0 || (size = fileInfo.st_size) == 0) {
678         return NULL;
679     }
680 
681     int32_t fp = open(path, O_RDONLY, S_IRUSR);
682     if (fp < 0) {
683         return NULL;
684     }
685 
686     char *json = (char *)SAMGR_Malloc(size * sizeof(char));
687     if (json == NULL) {
688         close(fp);
689         return NULL;
690     }
691     if (read(fp, json, size * sizeof(char)) != size * sizeof(char)) {
692         SAMGR_Free(json);
693         close(fp);
694         return NULL;
695     }
696     close(fp);
697 
698     cJSON *root = cJSON_Parse(json);
699     SAMGR_Free(json);
700     json = NULL;
701     return root;
702 }
703 
ParseSysCap(void)704 static void ParseSysCap(void)
705 {
706     cJSON *root = GetJsonStream();
707     if (root == NULL) {
708         HILOG_ERROR(HILOG_MODULE_SAMGR, "ParseSysCap GetJsonStream failed!");
709         return;
710     }
711     cJSON *sysCaps = cJSON_GetObjectItem(root, "systemCapability");
712     if (!cJSON_IsArray(sysCaps)) {
713         cJSON_Delete(root);
714         HILOG_ERROR(HILOG_MODULE_SAMGR, "ParseSysCap format failed!");
715         return;
716     }
717     int32_t size = cJSON_GetArraySize(sysCaps);
718     int32_t sysCapNum = 0;
719     for (int32_t i = 0; i < size; i++) {
720         if (sysCapNum >= MAX_SYSCAP_NUM) {
721             HILOG_ERROR(HILOG_MODULE_SAMGR, "ParseSycCapMap system capability exceed");
722             break;
723         }
724         cJSON *item = cJSON_GetArrayItem(sysCaps, i);
725         if (!cJSON_IsObject(item)) {
726             continue;
727         }
728         cJSON *name = cJSON_GetObjectItem(item, "name");
729         cJSON *isRegister = cJSON_GetObjectItem(item, "register-on-startup");
730         if (!cJSON_IsString(name) || !cJSON_IsBool(isRegister)) {
731             continue;
732         }
733         char *nameStr = cJSON_GetStringValue(name);
734         if (VECTOR_FindByKey(&(g_server.sysCapabilitys), nameStr) != INVALID_INDEX) {
735             HILOG_WARN(HILOG_MODULE_SAMGR, "Duplicate system capability %s register!", nameStr);
736             continue;
737         }
738         SysCapImpl *impl = (SysCapImpl *)SAMGR_Malloc(sizeof(SysCapImpl));
739         if (impl == NULL) {
740             continue;
741         }
742         if (strcpy_s(impl->name, sizeof(impl->name), cJSON_GetStringValue(name)) != EC_SUCCESS) {
743             SAMGR_Free(impl);
744             continue;
745         }
746         impl->isRegister = cJSON_IsTrue(isRegister);
747         if (VECTOR_Add(&(g_server.sysCapabilitys), impl) == INVALID_INDEX) {
748             SAMGR_Free(impl);
749             HILOG_ERROR(HILOG_MODULE_SAMGR, "system capability %s register failed!", impl->name);
750             continue;
751         }
752         sysCapNum++;
753     }
754     cJSON_Delete(root);
755 }
756