1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2013 FreeBSD Foundation
5 *
6 * This software was developed by Pawel Jakub Dawidek under sponsorship from
7 * the FreeBSD Foundation.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31 #include <sys/cdefs.h>
32 /*
33 * Note that this file is compiled into the kernel and into libc.
34 */
35
36 #include <sys/types.h>
37 #include <sys/capsicum.h>
38
39 #ifdef _KERNEL
40 #include <sys/systm.h>
41 #include <sys/kernel.h>
42 #include <sys/stdarg.h>
43 #else /* !_KERNEL */
44 #include <assert.h>
45 #include <stdarg.h>
46 #include <stdbool.h>
47 #include <stdint.h>
48 #include <string.h>
49 #endif
50
51 #ifdef _KERNEL
52 #define assert(exp) KASSERT((exp), ("%s:%u", __func__, __LINE__))
53 const cap_rights_t cap_accept_rights = CAP_RIGHTS_INITIALIZER(CAP_ACCEPT);
54 const cap_rights_t cap_bind_rights = CAP_RIGHTS_INITIALIZER(CAP_BIND);
55 const cap_rights_t cap_connect_rights = CAP_RIGHTS_INITIALIZER(CAP_CONNECT);
56 const cap_rights_t cap_event_rights = CAP_RIGHTS_INITIALIZER(CAP_EVENT);
57 const cap_rights_t cap_fchdir_rights = CAP_RIGHTS_INITIALIZER(CAP_FCHDIR);
58 const cap_rights_t cap_fchflags_rights = CAP_RIGHTS_INITIALIZER(CAP_FCHFLAGS);
59 const cap_rights_t cap_fchmod_rights = CAP_RIGHTS_INITIALIZER(CAP_FCHMOD);
60 const cap_rights_t cap_fchown_rights = CAP_RIGHTS_INITIALIZER(CAP_FCHOWN);
61 const cap_rights_t cap_fchroot_rights = CAP_RIGHTS_INITIALIZER(CAP_FCHROOT);
62 const cap_rights_t cap_fcntl_rights = CAP_RIGHTS_INITIALIZER(CAP_FCNTL);
63 const cap_rights_t cap_fexecve_rights = CAP_RIGHTS_INITIALIZER(CAP_FEXECVE);
64 const cap_rights_t cap_flock_rights = CAP_RIGHTS_INITIALIZER(CAP_FLOCK);
65 const cap_rights_t cap_fpathconf_rights = CAP_RIGHTS_INITIALIZER(CAP_FPATHCONF);
66 const cap_rights_t cap_fstat_rights = CAP_RIGHTS_INITIALIZER(CAP_FSTAT);
67 const cap_rights_t cap_fstatfs_rights = CAP_RIGHTS_INITIALIZER(CAP_FSTATFS);
68 const cap_rights_t cap_fsync_rights = CAP_RIGHTS_INITIALIZER(CAP_FSYNC);
69 const cap_rights_t cap_ftruncate_rights = CAP_RIGHTS_INITIALIZER(CAP_FTRUNCATE);
70 const cap_rights_t cap_futimes_rights = CAP_RIGHTS_INITIALIZER(CAP_FUTIMES);
71 const cap_rights_t cap_getpeername_rights =
72 CAP_RIGHTS_INITIALIZER(CAP_GETPEERNAME);
73 const cap_rights_t cap_getsockopt_rights =
74 CAP_RIGHTS_INITIALIZER(CAP_GETSOCKOPT);
75 const cap_rights_t cap_getsockname_rights =
76 CAP_RIGHTS_INITIALIZER(CAP_GETSOCKNAME);
77 const cap_rights_t cap_inotify_add_rights =
78 CAP_RIGHTS_INITIALIZER(CAP_INOTIFY_ADD);
79 const cap_rights_t cap_inotify_rm_rights =
80 CAP_RIGHTS_INITIALIZER(CAP_INOTIFY_RM);
81 const cap_rights_t cap_ioctl_rights = CAP_RIGHTS_INITIALIZER(CAP_IOCTL);
82 const cap_rights_t cap_listen_rights = CAP_RIGHTS_INITIALIZER(CAP_LISTEN);
83 const cap_rights_t cap_linkat_source_rights =
84 CAP_RIGHTS_INITIALIZER(CAP_LINKAT_SOURCE);
85 const cap_rights_t cap_linkat_target_rights =
86 CAP_RIGHTS_INITIALIZER(CAP_LINKAT_TARGET);
87 const cap_rights_t cap_mmap_rights = CAP_RIGHTS_INITIALIZER(CAP_MMAP);
88 const cap_rights_t cap_mkdirat_rights = CAP_RIGHTS_INITIALIZER(CAP_MKDIRAT);
89 const cap_rights_t cap_mkfifoat_rights = CAP_RIGHTS_INITIALIZER(CAP_MKFIFOAT);
90 const cap_rights_t cap_mknodat_rights = CAP_RIGHTS_INITIALIZER(CAP_MKNODAT);
91 const cap_rights_t cap_pddupfd_rights = CAP_RIGHTS_INITIALIZER(CAP_PDDUPFD);
92 const cap_rights_t cap_pdgetpid_rights = CAP_RIGHTS_INITIALIZER(CAP_PDGETPID);
93 const cap_rights_t cap_pdkill_rights = CAP_RIGHTS_INITIALIZER(CAP_PDKILL);
94 const cap_rights_t cap_pdwait_rights = CAP_RIGHTS_INITIALIZER(CAP_PDWAIT);
95 const cap_rights_t cap_pread_rights = CAP_RIGHTS_INITIALIZER(CAP_PREAD);
96 const cap_rights_t cap_ptrace_rights = CAP_RIGHTS_INITIALIZER(CAP_PTRACE);
97 const cap_rights_t cap_pwrite_rights = CAP_RIGHTS_INITIALIZER(CAP_PWRITE);
98 const cap_rights_t cap_read_rights = CAP_RIGHTS_INITIALIZER(CAP_READ);
99 const cap_rights_t cap_recv_rights = CAP_RIGHTS_INITIALIZER(CAP_RECV);
100 const cap_rights_t cap_renameat_source_rights =
101 CAP_RIGHTS_INITIALIZER(CAP_RENAMEAT_SOURCE);
102 const cap_rights_t cap_renameat_target_rights =
103 CAP_RIGHTS_INITIALIZER(CAP_RENAMEAT_TARGET);
104 const cap_rights_t cap_seek_rights = CAP_RIGHTS_INITIALIZER(CAP_SEEK);
105 const cap_rights_t cap_send_rights = CAP_RIGHTS_INITIALIZER(CAP_SEND);
106 const cap_rights_t cap_send_connect_rights =
107 CAP_RIGHTS_INITIALIZER2(CAP_SEND, CAP_CONNECT);
108 const cap_rights_t cap_setsockopt_rights =
109 CAP_RIGHTS_INITIALIZER(CAP_SETSOCKOPT);
110 const cap_rights_t cap_shutdown_rights = CAP_RIGHTS_INITIALIZER(CAP_SHUTDOWN);
111 const cap_rights_t cap_symlinkat_rights = CAP_RIGHTS_INITIALIZER(CAP_SYMLINKAT);
112 const cap_rights_t cap_unlinkat_rights = CAP_RIGHTS_INITIALIZER(CAP_UNLINKAT);
113 const cap_rights_t cap_write_rights = CAP_RIGHTS_INITIALIZER(CAP_WRITE);
114 const cap_rights_t cap_no_rights = CAP_RIGHTS_INITIALIZER(0ULL);
115 #endif
116
117 #define CAPARSIZE_MIN (CAP_RIGHTS_VERSION_00 + 2)
118 #define CAPARSIZE_MAX (CAP_RIGHTS_VERSION + 2)
119
120 static __inline int
right_to_index(uint64_t right)121 right_to_index(uint64_t right)
122 {
123 static const int bit2idx[] = {
124 -1, 0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1,
125 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
126 };
127 int idx;
128
129 idx = CAPIDXBIT(right);
130 assert(idx >= 0 && idx < sizeof(bit2idx) / sizeof(bit2idx[0]));
131 return (bit2idx[idx]);
132 }
133
134 static void
cap_rights_vset(cap_rights_t * rights,va_list ap)135 cap_rights_vset(cap_rights_t *rights, va_list ap)
136 {
137 uint64_t right;
138 int i, n __unused;
139
140 assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00);
141
142 n = CAPARSIZE(rights);
143 assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX);
144
145 for (;;) {
146 right = (uint64_t)va_arg(ap, unsigned long long);
147 if (right == 0)
148 break;
149 assert(CAPRVER(right) == 0);
150 i = right_to_index(right);
151 assert(i >= 0);
152 assert(i < n);
153 assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right));
154 rights->cr_rights[i] |= right;
155 assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right));
156 }
157 }
158
159 static void
cap_rights_vclear(cap_rights_t * rights,va_list ap)160 cap_rights_vclear(cap_rights_t *rights, va_list ap)
161 {
162 uint64_t right;
163 int i, n __unused;
164
165 assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00);
166
167 n = CAPARSIZE(rights);
168 assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX);
169
170 for (;;) {
171 right = (uint64_t)va_arg(ap, unsigned long long);
172 if (right == 0)
173 break;
174 assert(CAPRVER(right) == 0);
175 i = right_to_index(right);
176 assert(i >= 0);
177 assert(i < n);
178 assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right));
179 rights->cr_rights[i] &= ~(right & 0x01FFFFFFFFFFFFFFULL);
180 assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right));
181 }
182 }
183
184 static bool
cap_rights_is_vset(const cap_rights_t * rights,va_list ap)185 cap_rights_is_vset(const cap_rights_t *rights, va_list ap)
186 {
187 uint64_t right;
188 int i, n __unused;
189
190 assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00);
191
192 n = CAPARSIZE(rights);
193 assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX);
194
195 for (;;) {
196 right = (uint64_t)va_arg(ap, unsigned long long);
197 if (right == 0)
198 break;
199 assert(CAPRVER(right) == 0);
200 i = right_to_index(right);
201 assert(i >= 0);
202 assert(i < n);
203 assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right));
204 if ((rights->cr_rights[i] & right) != right)
205 return (false);
206 }
207
208 return (true);
209 }
210
211 cap_rights_t *
__cap_rights_init(int version,cap_rights_t * rights,...)212 __cap_rights_init(int version, cap_rights_t *rights, ...)
213 {
214 unsigned int n __unused;
215 va_list ap;
216
217 assert(version == CAP_RIGHTS_VERSION_00);
218
219 n = version + 2;
220 assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX);
221 CAP_NONE(rights);
222 va_start(ap, rights);
223 cap_rights_vset(rights, ap);
224 va_end(ap);
225
226 return (rights);
227 }
228
229 cap_rights_t *
__cap_rights_set(cap_rights_t * rights,...)230 __cap_rights_set(cap_rights_t *rights, ...)
231 {
232 va_list ap;
233
234 assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00);
235
236 va_start(ap, rights);
237 cap_rights_vset(rights, ap);
238 va_end(ap);
239
240 return (rights);
241 }
242
243 cap_rights_t *
__cap_rights_clear(cap_rights_t * rights,...)244 __cap_rights_clear(cap_rights_t *rights, ...)
245 {
246 va_list ap;
247
248 assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00);
249
250 va_start(ap, rights);
251 cap_rights_vclear(rights, ap);
252 va_end(ap);
253
254 return (rights);
255 }
256
257 bool
__cap_rights_is_set(const cap_rights_t * rights,...)258 __cap_rights_is_set(const cap_rights_t *rights, ...)
259 {
260 va_list ap;
261 bool ret;
262
263 assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00);
264
265 va_start(ap, rights);
266 ret = cap_rights_is_vset(rights, ap);
267 va_end(ap);
268
269 return (ret);
270 }
271
272 bool
cap_rights_is_empty(const cap_rights_t * rights)273 cap_rights_is_empty(const cap_rights_t *rights)
274 {
275 #ifndef _KERNEL
276 cap_rights_t cap_no_rights;
277 cap_rights_init(&cap_no_rights);
278 #endif
279
280 assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00);
281 assert(CAPVER(&cap_no_rights) == CAP_RIGHTS_VERSION_00);
282
283 for (int i = 0; i < CAPARSIZE(rights); i++) {
284 if (rights->cr_rights[i] != cap_no_rights.cr_rights[i])
285 return (false);
286 }
287
288 return (true);
289 }
290
291 bool
cap_rights_is_valid(const cap_rights_t * rights)292 cap_rights_is_valid(const cap_rights_t *rights)
293 {
294 cap_rights_t allrights;
295 int i, j;
296
297 if (CAPVER(rights) != CAP_RIGHTS_VERSION_00)
298 return (false);
299 if (CAPARSIZE(rights) < CAPARSIZE_MIN ||
300 CAPARSIZE(rights) > CAPARSIZE_MAX) {
301 return (false);
302 }
303 CAP_ALL(&allrights);
304 if (!cap_rights_contains(&allrights, rights))
305 return (false);
306 for (i = 0; i < CAPARSIZE(rights); i++) {
307 j = right_to_index(rights->cr_rights[i]);
308 if (i != j)
309 return (false);
310 if (i > 0) {
311 if (CAPRVER(rights->cr_rights[i]) != 0)
312 return (false);
313 }
314 }
315
316 return (true);
317 }
318
319 cap_rights_t *
cap_rights_merge(cap_rights_t * dst,const cap_rights_t * src)320 cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src)
321 {
322 unsigned int i, n;
323
324 assert(CAPVER(dst) == CAP_RIGHTS_VERSION_00);
325 assert(CAPVER(src) == CAP_RIGHTS_VERSION_00);
326 assert(CAPVER(dst) == CAPVER(src));
327 assert(cap_rights_is_valid(src));
328 assert(cap_rights_is_valid(dst));
329
330 n = CAPARSIZE(dst);
331 assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX);
332
333 for (i = 0; i < n; i++)
334 dst->cr_rights[i] |= src->cr_rights[i];
335
336 assert(cap_rights_is_valid(src));
337 assert(cap_rights_is_valid(dst));
338
339 return (dst);
340 }
341
342 cap_rights_t *
cap_rights_remove(cap_rights_t * dst,const cap_rights_t * src)343 cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src)
344 {
345 unsigned int i, n;
346
347 assert(CAPVER(dst) == CAP_RIGHTS_VERSION_00);
348 assert(CAPVER(src) == CAP_RIGHTS_VERSION_00);
349 assert(CAPVER(dst) == CAPVER(src));
350 assert(cap_rights_is_valid(src));
351 assert(cap_rights_is_valid(dst));
352
353 n = CAPARSIZE(dst);
354 assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX);
355
356 for (i = 0; i < n; i++) {
357 dst->cr_rights[i] &=
358 ~(src->cr_rights[i] & 0x01FFFFFFFFFFFFFFULL);
359 }
360
361 assert(cap_rights_is_valid(src));
362 assert(cap_rights_is_valid(dst));
363
364 return (dst);
365 }
366
367 #ifndef _KERNEL
368 bool
cap_rights_contains(const cap_rights_t * big,const cap_rights_t * little)369 cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little)
370 {
371 unsigned int i, n;
372
373 assert(CAPVER(big) == CAP_RIGHTS_VERSION_00);
374 assert(CAPVER(little) == CAP_RIGHTS_VERSION_00);
375 assert(CAPVER(big) == CAPVER(little));
376
377 n = CAPARSIZE(big);
378 assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX);
379
380 for (i = 0; i < n; i++) {
381 if ((big->cr_rights[i] & little->cr_rights[i]) !=
382 little->cr_rights[i]) {
383 return (false);
384 }
385 }
386
387 return (true);
388 }
389 #endif
390