1 /*
2 * Copyright (c) 2020-2021 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 <limits.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #if defined OHOS_LITE && !defined __LINUX__
19 #include <sys/capability.h>
20 #else
21 #include <linux/capability.h>
22 #endif
23 #include <sys/types.h>
24 #include <unistd.h>
25
26 #include "init_log.h"
27 #include "init_service.h"
28 #include "init_service_manager.h"
29 #include "init_utils.h"
30
31 #define MAX_CAPS_CNT_FOR_ONE_SERVICE 100
32
GetCapByString(const char * capStr)33 static unsigned int GetCapByString(const char *capStr)
34 {
35 static const CapStrCapNum capStrCapNum[] = {
36 { "CHOWN", CAP_CHOWN },
37 { "DAC_OVERRIDE", CAP_DAC_OVERRIDE },
38 { "DAC_READ_SEARCH", CAP_DAC_READ_SEARCH },
39 { "FOWNER", CAP_FOWNER },
40 { "FSETID", CAP_FSETID },
41 { "KILL", CAP_KILL },
42 { "SETGID", CAP_SETGID },
43 { "SETUID", CAP_SETUID },
44 { "SETPCAP", CAP_SETPCAP },
45 { "LINUX_IMMUTABLE", CAP_LINUX_IMMUTABLE },
46 { "NET_BIND_SERVICE", CAP_NET_BIND_SERVICE },
47 { "NET_BROADCAST", CAP_NET_BROADCAST },
48 { "NET_ADMIN", CAP_NET_ADMIN },
49 { "NET_RAW", CAP_NET_RAW },
50 { "IPC_LOCK", CAP_IPC_LOCK },
51 { "IPC_OWNER", CAP_IPC_OWNER },
52 { "SYS_MODULE", CAP_SYS_MODULE },
53 { "SYS_RAWIO", CAP_SYS_RAWIO },
54 { "SYS_CHROOT", CAP_SYS_CHROOT },
55 { "SYS_PTRACE", CAP_SYS_PTRACE },
56 { "SYS_PACCT", CAP_SYS_PACCT },
57 { "SYS_ADMIN", CAP_SYS_ADMIN },
58 { "SYS_BOOT", CAP_SYS_BOOT },
59 { "SYS_NICE", CAP_SYS_NICE },
60 { "SYS_RESOURCE", CAP_SYS_RESOURCE },
61 { "SYS_TIME", CAP_SYS_TIME },
62 { "SYS_TTY_CONFIG", CAP_SYS_TTY_CONFIG },
63 { "MKNOD", CAP_MKNOD },
64 { "LEASE", CAP_LEASE },
65 { "AUDIT_WRITE", CAP_AUDIT_WRITE },
66 { "AUDIT_CONTROL", CAP_AUDIT_CONTROL },
67 { "SETFCAP", CAP_SETFCAP },
68 { "MAC_OVERRIDE", CAP_MAC_OVERRIDE },
69 { "MAC_ADMIN", CAP_MAC_ADMIN },
70 { "SYSLOG", CAP_SYSLOG },
71 { "WAKE_ALARM", CAP_WAKE_ALARM },
72 { "BLOCK_SUSPEND", CAP_BLOCK_SUSPEND },
73 { "AUDIT_READ", CAP_AUDIT_READ },
74 #if defined CAP_PERFMON
75 { "PERFMON", CAP_PERFMON },
76 #endif
77 };
78 int mapSize = (int)ARRAY_LENGTH(capStrCapNum);
79 int capLen = strlen("CAP_");
80 for (int j = 0; j < mapSize; j++) {
81 if ((strcmp(capStr, capStrCapNum[j].capStr) == 0) ||
82 ((strncmp(capStr, "CAP_", capLen) == 0) &&
83 (strcmp(capStr + capLen, capStrCapNum[j].capStr) == 0))) {
84 return capStrCapNum[j].CapNum;
85 }
86 }
87 return CAP_LAST_CAP + 1;
88 }
89
InitServiceCaps(const cJSON * curArrItem,Service * service)90 int InitServiceCaps(const cJSON *curArrItem, Service *service)
91 {
92 INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "service is null ptr.");
93 INIT_ERROR_CHECK(curArrItem != NULL, return SERVICE_FAILURE, "json is null ptr.");
94 int capsCnt = 0;
95 cJSON *filedJ = GetArrayItem(curArrItem, &capsCnt, "caps");
96 if (filedJ == NULL) {
97 return SERVICE_SUCCESS;
98 }
99 INIT_ERROR_CHECK(capsCnt <= MAX_CAPS_CNT_FOR_ONE_SERVICE, return SERVICE_FAILURE,
100 "service=%s, too many caps[cnt %d] for one service", service->name, capsCnt);
101 service->servPerm.capsCnt = 0;
102 if (service->servPerm.caps != NULL) {
103 free(service->servPerm.caps);
104 service->servPerm.caps = NULL;
105 }
106 service->servPerm.caps = (unsigned int *)calloc(1, sizeof(unsigned int) * capsCnt);
107 INIT_ERROR_CHECK(service->servPerm.caps != NULL, return SERVICE_FAILURE,
108 "Failed to malloc for service %s", service->name);
109 unsigned int caps = FULL_CAP;
110 for (int i = 0; i < capsCnt; ++i) { // number form
111 char *capStr = NULL;
112 cJSON *capJson = cJSON_GetArrayItem(filedJ, i);
113 if (cJSON_IsNumber(capJson)) { // for number
114 caps = (unsigned int)cJSON_GetNumberValue(capJson);
115 } else if (cJSON_IsString(capJson)) {
116 capStr = cJSON_GetStringValue(capJson);
117 if (capStr == NULL || strlen(capStr) == 0) { // check all errors
118 INIT_LOGE("service=%s, parse item[%d] as string, error.", service->name, i);
119 break;
120 }
121 caps = GetCapByString(capStr);
122 } else {
123 caps = CAP_LAST_CAP + 1;
124 }
125 if ((caps > CAP_LAST_CAP) && (caps != (unsigned int)FULL_CAP)) {
126 INIT_LOGE("service=%s not support caps = %s caps %d", service->name, capStr, caps);
127 continue;
128 }
129 service->servPerm.caps[service->servPerm.capsCnt] = (unsigned int)caps;
130 service->servPerm.capsCnt++;
131 }
132 return 0;
133 }
134