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