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_pdgetpid_rights = CAP_RIGHTS_INITIALIZER(CAP_PDGETPID);
92 const cap_rights_t cap_pdkill_rights = CAP_RIGHTS_INITIALIZER(CAP_PDKILL);
93 const cap_rights_t cap_pread_rights = CAP_RIGHTS_INITIALIZER(CAP_PREAD);
94 const cap_rights_t cap_pwrite_rights = CAP_RIGHTS_INITIALIZER(CAP_PWRITE);
95 const cap_rights_t cap_read_rights = CAP_RIGHTS_INITIALIZER(CAP_READ);
96 const cap_rights_t cap_recv_rights = CAP_RIGHTS_INITIALIZER(CAP_RECV);
97 const cap_rights_t cap_renameat_source_rights =
98 CAP_RIGHTS_INITIALIZER(CAP_RENAMEAT_SOURCE);
99 const cap_rights_t cap_renameat_target_rights =
100 CAP_RIGHTS_INITIALIZER(CAP_RENAMEAT_TARGET);
101 const cap_rights_t cap_seek_rights = CAP_RIGHTS_INITIALIZER(CAP_SEEK);
102 const cap_rights_t cap_send_rights = CAP_RIGHTS_INITIALIZER(CAP_SEND);
103 const cap_rights_t cap_send_connect_rights =
104 CAP_RIGHTS_INITIALIZER2(CAP_SEND, CAP_CONNECT);
105 const cap_rights_t cap_setsockopt_rights =
106 CAP_RIGHTS_INITIALIZER(CAP_SETSOCKOPT);
107 const cap_rights_t cap_shutdown_rights = CAP_RIGHTS_INITIALIZER(CAP_SHUTDOWN);
108 const cap_rights_t cap_symlinkat_rights = CAP_RIGHTS_INITIALIZER(CAP_SYMLINKAT);
109 const cap_rights_t cap_unlinkat_rights = CAP_RIGHTS_INITIALIZER(CAP_UNLINKAT);
110 const cap_rights_t cap_write_rights = CAP_RIGHTS_INITIALIZER(CAP_WRITE);
111 const cap_rights_t cap_no_rights = CAP_RIGHTS_INITIALIZER(0ULL);
112 #endif
113
114 #define CAPARSIZE_MIN (CAP_RIGHTS_VERSION_00 + 2)
115 #define CAPARSIZE_MAX (CAP_RIGHTS_VERSION + 2)
116
117 static __inline int
right_to_index(uint64_t right)118 right_to_index(uint64_t right)
119 {
120 static const int bit2idx[] = {
121 -1, 0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1,
122 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
123 };
124 int idx;
125
126 idx = CAPIDXBIT(right);
127 assert(idx >= 0 && idx < sizeof(bit2idx) / sizeof(bit2idx[0]));
128 return (bit2idx[idx]);
129 }
130
131 static void
cap_rights_vset(cap_rights_t * rights,va_list ap)132 cap_rights_vset(cap_rights_t *rights, va_list ap)
133 {
134 uint64_t right;
135 int i, n __unused;
136
137 assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00);
138
139 n = CAPARSIZE(rights);
140 assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX);
141
142 for (;;) {
143 right = (uint64_t)va_arg(ap, unsigned long long);
144 if (right == 0)
145 break;
146 assert(CAPRVER(right) == 0);
147 i = right_to_index(right);
148 assert(i >= 0);
149 assert(i < n);
150 assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right));
151 rights->cr_rights[i] |= right;
152 assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right));
153 }
154 }
155
156 static void
cap_rights_vclear(cap_rights_t * rights,va_list ap)157 cap_rights_vclear(cap_rights_t *rights, va_list ap)
158 {
159 uint64_t right;
160 int i, n __unused;
161
162 assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00);
163
164 n = CAPARSIZE(rights);
165 assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX);
166
167 for (;;) {
168 right = (uint64_t)va_arg(ap, unsigned long long);
169 if (right == 0)
170 break;
171 assert(CAPRVER(right) == 0);
172 i = right_to_index(right);
173 assert(i >= 0);
174 assert(i < n);
175 assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right));
176 rights->cr_rights[i] &= ~(right & 0x01FFFFFFFFFFFFFFULL);
177 assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right));
178 }
179 }
180
181 static bool
cap_rights_is_vset(const cap_rights_t * rights,va_list ap)182 cap_rights_is_vset(const cap_rights_t *rights, va_list ap)
183 {
184 uint64_t right;
185 int i, n __unused;
186
187 assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00);
188
189 n = CAPARSIZE(rights);
190 assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX);
191
192 for (;;) {
193 right = (uint64_t)va_arg(ap, unsigned long long);
194 if (right == 0)
195 break;
196 assert(CAPRVER(right) == 0);
197 i = right_to_index(right);
198 assert(i >= 0);
199 assert(i < n);
200 assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right));
201 if ((rights->cr_rights[i] & right) != right)
202 return (false);
203 }
204
205 return (true);
206 }
207
208 cap_rights_t *
__cap_rights_init(int version,cap_rights_t * rights,...)209 __cap_rights_init(int version, cap_rights_t *rights, ...)
210 {
211 unsigned int n __unused;
212 va_list ap;
213
214 assert(version == CAP_RIGHTS_VERSION_00);
215
216 n = version + 2;
217 assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX);
218 CAP_NONE(rights);
219 va_start(ap, rights);
220 cap_rights_vset(rights, ap);
221 va_end(ap);
222
223 return (rights);
224 }
225
226 cap_rights_t *
__cap_rights_set(cap_rights_t * rights,...)227 __cap_rights_set(cap_rights_t *rights, ...)
228 {
229 va_list ap;
230
231 assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00);
232
233 va_start(ap, rights);
234 cap_rights_vset(rights, ap);
235 va_end(ap);
236
237 return (rights);
238 }
239
240 cap_rights_t *
__cap_rights_clear(cap_rights_t * rights,...)241 __cap_rights_clear(cap_rights_t *rights, ...)
242 {
243 va_list ap;
244
245 assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00);
246
247 va_start(ap, rights);
248 cap_rights_vclear(rights, ap);
249 va_end(ap);
250
251 return (rights);
252 }
253
254 bool
__cap_rights_is_set(const cap_rights_t * rights,...)255 __cap_rights_is_set(const cap_rights_t *rights, ...)
256 {
257 va_list ap;
258 bool ret;
259
260 assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00);
261
262 va_start(ap, rights);
263 ret = cap_rights_is_vset(rights, ap);
264 va_end(ap);
265
266 return (ret);
267 }
268
269 bool
cap_rights_is_empty(const cap_rights_t * rights)270 cap_rights_is_empty(const cap_rights_t *rights)
271 {
272 #ifndef _KERNEL
273 cap_rights_t cap_no_rights;
274 cap_rights_init(&cap_no_rights);
275 #endif
276
277 assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00);
278 assert(CAPVER(&cap_no_rights) == CAP_RIGHTS_VERSION_00);
279
280 for (int i = 0; i < CAPARSIZE(rights); i++) {
281 if (rights->cr_rights[i] != cap_no_rights.cr_rights[i])
282 return (false);
283 }
284
285 return (true);
286 }
287
288 bool
cap_rights_is_valid(const cap_rights_t * rights)289 cap_rights_is_valid(const cap_rights_t *rights)
290 {
291 cap_rights_t allrights;
292 int i, j;
293
294 if (CAPVER(rights) != CAP_RIGHTS_VERSION_00)
295 return (false);
296 if (CAPARSIZE(rights) < CAPARSIZE_MIN ||
297 CAPARSIZE(rights) > CAPARSIZE_MAX) {
298 return (false);
299 }
300 CAP_ALL(&allrights);
301 if (!cap_rights_contains(&allrights, rights))
302 return (false);
303 for (i = 0; i < CAPARSIZE(rights); i++) {
304 j = right_to_index(rights->cr_rights[i]);
305 if (i != j)
306 return (false);
307 if (i > 0) {
308 if (CAPRVER(rights->cr_rights[i]) != 0)
309 return (false);
310 }
311 }
312
313 return (true);
314 }
315
316 cap_rights_t *
cap_rights_merge(cap_rights_t * dst,const cap_rights_t * src)317 cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src)
318 {
319 unsigned int i, n;
320
321 assert(CAPVER(dst) == CAP_RIGHTS_VERSION_00);
322 assert(CAPVER(src) == CAP_RIGHTS_VERSION_00);
323 assert(CAPVER(dst) == CAPVER(src));
324 assert(cap_rights_is_valid(src));
325 assert(cap_rights_is_valid(dst));
326
327 n = CAPARSIZE(dst);
328 assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX);
329
330 for (i = 0; i < n; i++)
331 dst->cr_rights[i] |= src->cr_rights[i];
332
333 assert(cap_rights_is_valid(src));
334 assert(cap_rights_is_valid(dst));
335
336 return (dst);
337 }
338
339 cap_rights_t *
cap_rights_remove(cap_rights_t * dst,const cap_rights_t * src)340 cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src)
341 {
342 unsigned int i, n;
343
344 assert(CAPVER(dst) == CAP_RIGHTS_VERSION_00);
345 assert(CAPVER(src) == CAP_RIGHTS_VERSION_00);
346 assert(CAPVER(dst) == CAPVER(src));
347 assert(cap_rights_is_valid(src));
348 assert(cap_rights_is_valid(dst));
349
350 n = CAPARSIZE(dst);
351 assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX);
352
353 for (i = 0; i < n; i++) {
354 dst->cr_rights[i] &=
355 ~(src->cr_rights[i] & 0x01FFFFFFFFFFFFFFULL);
356 }
357
358 assert(cap_rights_is_valid(src));
359 assert(cap_rights_is_valid(dst));
360
361 return (dst);
362 }
363
364 #ifndef _KERNEL
365 bool
cap_rights_contains(const cap_rights_t * big,const cap_rights_t * little)366 cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little)
367 {
368 unsigned int i, n;
369
370 assert(CAPVER(big) == CAP_RIGHTS_VERSION_00);
371 assert(CAPVER(little) == CAP_RIGHTS_VERSION_00);
372 assert(CAPVER(big) == CAPVER(little));
373
374 n = CAPARSIZE(big);
375 assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX);
376
377 for (i = 0; i < n; i++) {
378 if ((big->cr_rights[i] & little->cr_rights[i]) !=
379 little->cr_rights[i]) {
380 return (false);
381 }
382 }
383
384 return (true);
385 }
386 #endif
387