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