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