1 /*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <errno.h>
33 #include <unistd.h>
34 #include <stdio.h>
35 #include "syscall.h"
36 #include "sys/capability.h"
37
38 static unsigned int __linux_caps_maps[] = {
39 CAP_CHOWN, CAP_DAC_OVERRIDE, CAP_DAC_READ_SEARCH, CAP_FOWNER,
40 CAP_KILL, CAP_SETGID, CAP_SETUID, CAP_SETPCAP, CAP_NET_BIND_SERVICE,
41 CAP_NET_BROADCAST, CAP_NET_ADMIN, CAP_NET_RAW, CAP_SYS_PTRACE, CAP_SYS_ADMIN,
42 CAP_SYS_NICE, CAP_SYS_TIME, CAP_SYS_BOOT};
43
44 static unsigned int __ohos_caps_maps[] = {
45 OHOS_CAP_CHOWN, OHOS_CAP_DAC_EXECUTE, OHOS_CAP_DAC_WRITE, OHOS_CAP_DAC_READ_SEARCH, OHOS_CAP_FOWNER, OHOS_CAP_KILL,
46 OHOS_CAP_SETGID, OHOS_CAP_SETUID, OHOS_CAP_NET_BIND_SERVICE, OHOS_CAP_NET_BROADCAST, OHOS_CAP_NET_ADMIN,
47 OHOS_CAP_NET_RAW, OHOS_CAP_FS_MOUNT, OHOS_CAP_FS_FORMAT, OHOS_CAP_SCHED_SETPRIORITY,
48 OHOS_CAP_SET_TIMEOFDAY, OHOS_CAP_CLOCK_SETTIME, OHOS_CAP_CAPSET, OHOS_CAP_REBOOT, OHOS_CAP_SHELL_EXEC};
49
linux_caps_to_ohos(unsigned int caps)50 static unsigned int linux_caps_to_ohos(unsigned int caps)
51 {
52 int num = sizeof(__linux_caps_maps) / sizeof(int);
53 int loop;
54 unsigned int result = 0;
55 for (loop = 0; loop < num; loop++) {
56 if (!((1 << __linux_caps_maps[loop]) & caps)) {
57 continue;
58 }
59
60 switch (__linux_caps_maps[loop]) {
61 case CAP_CHOWN:
62 result |= 1 << OHOS_CAP_CHOWN;
63 break;
64 case CAP_DAC_OVERRIDE:
65 result |= 1 << OHOS_CAP_DAC_EXECUTE;
66 result |= 1 << OHOS_CAP_DAC_WRITE;
67 result |= 1 << OHOS_CAP_DAC_READ_SEARCH;
68 break;
69 case CAP_DAC_READ_SEARCH:
70 result |= 1 << OHOS_CAP_DAC_READ_SEARCH;
71 break;
72 case CAP_FOWNER:
73 result |= 1 << OHOS_CAP_FOWNER;
74 break;
75 case CAP_KILL:
76 result |= 1 << OHOS_CAP_KILL;
77 break;
78 case CAP_SETGID:
79 result |= 1 << OHOS_CAP_SETGID;
80 break;
81 case CAP_SETUID:
82 result |= 1 << OHOS_CAP_SETUID;
83 break;
84 case CAP_SETPCAP:
85 result |= 1 << OHOS_CAP_CAPSET;
86 break;
87 case CAP_NET_BIND_SERVICE:
88 result |= 1 << OHOS_CAP_NET_BIND_SERVICE;
89 break;
90 case CAP_NET_BROADCAST:
91 result |= 1 << OHOS_CAP_NET_BROADCAST;
92 break;
93 case CAP_NET_ADMIN:
94 result |= 1 << OHOS_CAP_NET_ADMIN;
95 break;
96 case CAP_NET_RAW:
97 result |= 1 << OHOS_CAP_NET_RAW;
98 break;
99 case CAP_SYS_PTRACE:
100 result |= 1 << OHOS_CAP_SHELL_EXEC;
101 break;
102 case CAP_SYS_ADMIN:
103 result |= 1 << OHOS_CAP_FS_MOUNT;
104 result |= 1 << OHOS_CAP_FS_FORMAT;
105 break;
106 case CAP_SYS_NICE:
107 result |= 1 << OHOS_CAP_SCHED_SETPRIORITY;
108 break;
109 case CAP_SYS_TIME:
110 result |= 1 << OHOS_CAP_SET_TIMEOFDAY;
111 result |= 1 << OHOS_CAP_CLOCK_SETTIME;
112 break;
113 case CAP_SYS_BOOT:
114 result |= 1 << OHOS_CAP_REBOOT;
115 break;
116 default:
117 break;
118 }
119 }
120
121 return result;
122 }
123
ohos_caps_to_linux(unsigned int caps)124 static unsigned int ohos_caps_to_linux(unsigned int caps)
125 {
126 int num = sizeof(__ohos_caps_maps) / sizeof(int);
127 int loop;
128 unsigned int result = 0;
129 for (loop = 0; loop < num; loop++) {
130 if (!((1 << __ohos_caps_maps[loop]) & caps)) {
131 continue;
132 }
133
134 switch (__ohos_caps_maps[loop]) {
135 case OHOS_CAP_CHOWN:
136 result |= 1 << CAP_CHOWN;
137 break;
138 case OHOS_CAP_DAC_EXECUTE:
139 case OHOS_CAP_DAC_WRITE:
140 result |= 1 << CAP_DAC_OVERRIDE;
141 break;
142 case OHOS_CAP_DAC_READ_SEARCH:
143 result |= 1 << CAP_DAC_READ_SEARCH;
144 break;
145 case OHOS_CAP_FOWNER:
146 result |= 1 << CAP_FOWNER;
147 break;
148 case OHOS_CAP_KILL:
149 result |= 1 << CAP_KILL;
150 break;
151 case OHOS_CAP_SETGID:
152 result |= 1 << CAP_SETGID;
153 break;
154 case OHOS_CAP_SETUID:
155 result |= 1 << CAP_SETUID;
156 break;
157 case OHOS_CAP_CAPSET:
158 result |= 1 << CAP_SETPCAP;
159 break;
160 case OHOS_CAP_NET_BIND_SERVICE:
161 result |= 1 << CAP_NET_BIND_SERVICE;
162 break;
163 case OHOS_CAP_NET_BROADCAST:
164 result |= 1 << CAP_NET_BROADCAST;
165 break;
166 case OHOS_CAP_NET_ADMIN:
167 result |= 1 << CAP_NET_ADMIN;
168 break;
169 case OHOS_CAP_NET_RAW:
170 result |= 1 << CAP_NET_RAW;
171 break;
172 case OHOS_CAP_SHELL_EXEC:
173 result |= 1 << CAP_SYS_PTRACE;
174 break;
175 case OHOS_CAP_FS_MOUNT:
176 case OHOS_CAP_FS_FORMAT:
177 result |= 1 << CAP_SYS_ADMIN;
178 break;
179 case OHOS_CAP_SCHED_SETPRIORITY:
180 result |= 1 << CAP_SYS_NICE;
181 break;
182 case OHOS_CAP_SET_TIMEOFDAY:
183 case OHOS_CAP_CLOCK_SETTIME:
184 result |= 1 << CAP_SYS_TIME;
185 break;
186 case OHOS_CAP_REBOOT:
187 result |= 1 << CAP_SYS_BOOT;
188 break;
189 default:
190 break;
191 }
192 }
193
194 return result;
195 }
196
linux_capget(cap_user_header_t hdr_ptr,cap_user_data_t data_ptr)197 int linux_capget(cap_user_header_t hdr_ptr, cap_user_data_t data_ptr)
198 {
199 unsigned int capvalue = 0;
200
201 if (hdr_ptr == NULL || data_ptr == NULL) {
202 errno = EINVAL;
203 return -1;
204 }
205
206 switch (hdr_ptr->version) {
207 case _LINUX_CAPABILITY_VERSION_1:
208 case _LINUX_CAPABILITY_VERSION_2:
209 case _LINUX_CAPABILITY_VERSION_3:
210 break;
211 default:
212 errno = EINVAL;
213 return -1;
214 }
215
216 if (syscall(SYS_ohoscapget, hdr_ptr->pid, &capvalue)) {
217 return -1;
218 }
219
220 data_ptr[0].effective = ohos_caps_to_linux(capvalue);
221 data_ptr[0].permitted = ohos_caps_to_linux(capvalue);
222 data_ptr[0].inheritable = ohos_caps_to_linux(capvalue);
223 return 0;
224 }
225
linux_capset(cap_user_header_t hdr_ptr,const cap_user_data_t data_ptr)226 int linux_capset(cap_user_header_t hdr_ptr, const cap_user_data_t data_ptr)
227 {
228 unsigned int capvalue = 0;
229
230 if (hdr_ptr == NULL || data_ptr == NULL) {
231 errno = EINVAL;
232 return -1;
233 }
234
235 if (hdr_ptr->pid) {
236 errno = EPERM;
237 return -1;
238 }
239
240 switch (hdr_ptr->version) {
241 case _LINUX_CAPABILITY_VERSION_1:
242 case _LINUX_CAPABILITY_VERSION_2:
243 case _LINUX_CAPABILITY_VERSION_3:
244 break;
245 default:
246 errno = EINVAL;
247 return -1;
248 }
249
250 capvalue = linux_caps_to_ohos(data_ptr[0].effective);
251 return syscall(SYS_ohoscapset, capvalue);
252 }
253
254 weak_alias(linux_capget, capget);
255 weak_alias(linux_capset, capset);
256
ohos_capget(pid_t pid,unsigned int * caps)257 int ohos_capget(pid_t pid, unsigned int *caps)
258 {
259 return syscall(SYS_ohoscapget, pid, caps);
260 }
261
ohos_capset(unsigned int caps)262 int ohos_capset(unsigned int caps)
263 {
264 return syscall(SYS_ohoscapset, caps);
265 }
266