xref: /third_party/musl/src/linux/liteos_a/cap.c (revision 570af302)
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
22static 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
28static 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
34static 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
108static 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
181int 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
210int 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
238weak_alias(linux_capget, capget);
239weak_alias(linux_capset, capset);
240
241int ohos_capget(pid_t pid, unsigned int *caps)
242{
243	return syscall(SYS_ohoscapget, pid, caps);
244}
245
246int ohos_capset(unsigned int caps)
247{
248	return syscall(SYS_ohoscapset, caps);
249}
250