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