1 /*
2 * Copyright (c) 2024 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
16 #include <errno.h>
17 #include <unistd.h>
18 #include <stdio.h>
19 #include "syscall.h"
20 #include "sys/capability.h"
21
22 static unsigned int __linux_caps_maps[] = {
23 CAP_CHOWN, CAP_DAC_OVERRIDE, CAP_DAC_READ_SEARCH, CAP_FOWNER,
24 CAP_KILL, CAP_SETGID, CAP_SETUID, CAP_SETPCAP, CAP_NET_BIND_SERVICE,
25 CAP_NET_BROADCAST, CAP_NET_ADMIN, CAP_NET_RAW, CAP_SYS_PTRACE, CAP_SYS_ADMIN,
26 CAP_SYS_NICE, CAP_SYS_TIME, CAP_SYS_BOOT};
27
28 static unsigned int __ohos_caps_maps[] = {
29 OHOS_CAP_CHOWN, OHOS_CAP_DAC_EXECUTE, OHOS_CAP_DAC_WRITE, OHOS_CAP_DAC_READ_SEARCH, OHOS_CAP_FOWNER, OHOS_CAP_KILL,
30 OHOS_CAP_SETGID, OHOS_CAP_SETUID, OHOS_CAP_NET_BIND_SERVICE, OHOS_CAP_NET_BROADCAST, OHOS_CAP_NET_ADMIN,
31 OHOS_CAP_NET_RAW, OHOS_CAP_FS_MOUNT, OHOS_CAP_FS_FORMAT, OHOS_CAP_SCHED_SETPRIORITY,
32 OHOS_CAP_SET_TIMEOFDAY, OHOS_CAP_CLOCK_SETTIME, OHOS_CAP_CAPSET, OHOS_CAP_REBOOT, OHOS_CAP_SHELL_EXEC};
33
linux_caps_to_ohos(unsigned int caps)34 static unsigned int linux_caps_to_ohos(unsigned int caps)
35 {
36 int num = sizeof(__linux_caps_maps) / sizeof(int);
37 int loop;
38 unsigned int result = 0;
39 for (loop = 0; loop < num; loop++) {
40 if (!((1 << __linux_caps_maps[loop]) & caps)) {
41 continue;
42 }
43
44 switch (__linux_caps_maps[loop]) {
45 case CAP_CHOWN:
46 result |= 1 << OHOS_CAP_CHOWN;
47 break;
48 case CAP_DAC_OVERRIDE:
49 result |= 1 << OHOS_CAP_DAC_EXECUTE;
50 result |= 1 << OHOS_CAP_DAC_WRITE;
51 result |= 1 << OHOS_CAP_DAC_READ_SEARCH;
52 break;
53 case CAP_DAC_READ_SEARCH:
54 result |= 1 << OHOS_CAP_DAC_READ_SEARCH;
55 break;
56 case CAP_FOWNER:
57 result |= 1 << OHOS_CAP_FOWNER;
58 break;
59 case CAP_KILL:
60 result |= 1 << OHOS_CAP_KILL;
61 break;
62 case CAP_SETGID:
63 result |= 1 << OHOS_CAP_SETGID;
64 break;
65 case CAP_SETUID:
66 result |= 1 << OHOS_CAP_SETUID;
67 break;
68 case CAP_SETPCAP:
69 result |= 1 << OHOS_CAP_CAPSET;
70 break;
71 case CAP_NET_BIND_SERVICE:
72 result |= 1 << OHOS_CAP_NET_BIND_SERVICE;
73 break;
74 case CAP_NET_BROADCAST:
75 result |= 1 << OHOS_CAP_NET_BROADCAST;
76 break;
77 case CAP_NET_ADMIN:
78 result |= 1 << OHOS_CAP_NET_ADMIN;
79 break;
80 case CAP_NET_RAW:
81 result |= 1 << OHOS_CAP_NET_RAW;
82 break;
83 case CAP_SYS_PTRACE:
84 result |= 1 << OHOS_CAP_SHELL_EXEC;
85 break;
86 case CAP_SYS_ADMIN:
87 result |= 1 << OHOS_CAP_FS_MOUNT;
88 result |= 1 << OHOS_CAP_FS_FORMAT;
89 break;
90 case CAP_SYS_NICE:
91 result |= 1 << OHOS_CAP_SCHED_SETPRIORITY;
92 break;
93 case CAP_SYS_TIME:
94 result |= 1 << OHOS_CAP_SET_TIMEOFDAY;
95 result |= 1 << OHOS_CAP_CLOCK_SETTIME;
96 break;
97 case CAP_SYS_BOOT:
98 result |= 1 << OHOS_CAP_REBOOT;
99 break;
100 default:
101 break;
102 }
103 }
104
105 return result;
106 }
107
ohos_caps_to_linux(unsigned int caps)108 static unsigned int ohos_caps_to_linux(unsigned int caps)
109 {
110 int num = sizeof(__ohos_caps_maps) / sizeof(int);
111 int loop;
112 unsigned int result = 0;
113 for (loop = 0; loop < num; loop++) {
114 if (!((1 << __ohos_caps_maps[loop]) & caps)) {
115 continue;
116 }
117
118 switch (__ohos_caps_maps[loop]) {
119 case OHOS_CAP_CHOWN:
120 result |= 1 << CAP_CHOWN;
121 break;
122 case OHOS_CAP_DAC_EXECUTE:
123 case OHOS_CAP_DAC_WRITE:
124 result |= 1 << CAP_DAC_OVERRIDE;
125 break;
126 case OHOS_CAP_DAC_READ_SEARCH:
127 result |= 1 << CAP_DAC_READ_SEARCH;
128 break;
129 case OHOS_CAP_FOWNER:
130 result |= 1 << CAP_FOWNER;
131 break;
132 case OHOS_CAP_KILL:
133 result |= 1 << CAP_KILL;
134 break;
135 case OHOS_CAP_SETGID:
136 result |= 1 << CAP_SETGID;
137 break;
138 case OHOS_CAP_SETUID:
139 result |= 1 << CAP_SETUID;
140 break;
141 case OHOS_CAP_CAPSET:
142 result |= 1 << CAP_SETPCAP;
143 break;
144 case OHOS_CAP_NET_BIND_SERVICE:
145 result |= 1 << CAP_NET_BIND_SERVICE;
146 break;
147 case OHOS_CAP_NET_BROADCAST:
148 result |= 1 << CAP_NET_BROADCAST;
149 break;
150 case OHOS_CAP_NET_ADMIN:
151 result |= 1 << CAP_NET_ADMIN;
152 break;
153 case OHOS_CAP_NET_RAW:
154 result |= 1 << CAP_NET_RAW;
155 break;
156 case OHOS_CAP_SHELL_EXEC:
157 result |= 1 << CAP_SYS_PTRACE;
158 break;
159 case OHOS_CAP_FS_MOUNT:
160 case OHOS_CAP_FS_FORMAT:
161 result |= 1 << CAP_SYS_ADMIN;
162 break;
163 case OHOS_CAP_SCHED_SETPRIORITY:
164 result |= 1 << CAP_SYS_NICE;
165 break;
166 case OHOS_CAP_SET_TIMEOFDAY:
167 case OHOS_CAP_CLOCK_SETTIME:
168 result |= 1 << CAP_SYS_TIME;
169 break;
170 case OHOS_CAP_REBOOT:
171 result |= 1 << CAP_SYS_BOOT;
172 break;
173 default:
174 break;
175 }
176 }
177
178 return result;
179 }
180
linux_capget(cap_user_header_t hdr_ptr,cap_user_data_t data_ptr)181 int linux_capget(cap_user_header_t hdr_ptr, cap_user_data_t data_ptr)
182 {
183 unsigned int capvalue = 0;
184
185 if (hdr_ptr == NULL || data_ptr == NULL) {
186 errno = EINVAL;
187 return -1;
188 }
189
190 switch (hdr_ptr->version) {
191 case _LINUX_CAPABILITY_VERSION_1:
192 case _LINUX_CAPABILITY_VERSION_2:
193 case _LINUX_CAPABILITY_VERSION_3:
194 break;
195 default:
196 errno = EINVAL;
197 return -1;
198 }
199
200 if (syscall(SYS_ohoscapget, hdr_ptr->pid, &capvalue)) {
201 return -1;
202 }
203
204 data_ptr[0].effective = ohos_caps_to_linux(capvalue);
205 data_ptr[0].permitted = ohos_caps_to_linux(capvalue);
206 data_ptr[0].inheritable = ohos_caps_to_linux(capvalue);
207 return 0;
208 }
209
linux_capset(cap_user_header_t hdr_ptr,const cap_user_data_t data_ptr)210 int linux_capset(cap_user_header_t hdr_ptr, const cap_user_data_t data_ptr)
211 {
212 unsigned int capvalue = 0;
213
214 if (hdr_ptr == NULL || data_ptr == NULL) {
215 errno = EINVAL;
216 return -1;
217 }
218
219 if (hdr_ptr->pid) {
220 errno = EPERM;
221 return -1;
222 }
223
224 switch (hdr_ptr->version) {
225 case _LINUX_CAPABILITY_VERSION_1:
226 case _LINUX_CAPABILITY_VERSION_2:
227 case _LINUX_CAPABILITY_VERSION_3:
228 break;
229 default:
230 errno = EINVAL;
231 return -1;
232 }
233
234 capvalue = linux_caps_to_ohos(data_ptr[0].effective);
235 return syscall(SYS_ohoscapset, capvalue);
236 }
237
238 weak_alias(linux_capget, capget);
239 weak_alias(linux_capset, capset);
240
ohos_capget(pid_t pid,unsigned int * caps)241 int ohos_capget(pid_t pid, unsigned int *caps)
242 {
243 return syscall(SYS_ohoscapget, pid, caps);
244 }
245
ohos_capset(unsigned int caps)246 int ohos_capset(unsigned int caps)
247 {
248 return syscall(SYS_ohoscapset, caps);
249 }
250