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