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_pdwait_rights = CAP_RIGHTS_INITIALIZER(CAP_PDWAIT); 94 const cap_rights_t cap_pread_rights = CAP_RIGHTS_INITIALIZER(CAP_PREAD); 95 const cap_rights_t cap_pwrite_rights = CAP_RIGHTS_INITIALIZER(CAP_PWRITE); 96 const cap_rights_t cap_read_rights = CAP_RIGHTS_INITIALIZER(CAP_READ); 97 const cap_rights_t cap_recv_rights = CAP_RIGHTS_INITIALIZER(CAP_RECV); 98 const cap_rights_t cap_renameat_source_rights = 99 CAP_RIGHTS_INITIALIZER(CAP_RENAMEAT_SOURCE); 100 const cap_rights_t cap_renameat_target_rights = 101 CAP_RIGHTS_INITIALIZER(CAP_RENAMEAT_TARGET); 102 const cap_rights_t cap_seek_rights = CAP_RIGHTS_INITIALIZER(CAP_SEEK); 103 const cap_rights_t cap_send_rights = CAP_RIGHTS_INITIALIZER(CAP_SEND); 104 const cap_rights_t cap_send_connect_rights = 105 CAP_RIGHTS_INITIALIZER2(CAP_SEND, CAP_CONNECT); 106 const cap_rights_t cap_setsockopt_rights = 107 CAP_RIGHTS_INITIALIZER(CAP_SETSOCKOPT); 108 const cap_rights_t cap_shutdown_rights = CAP_RIGHTS_INITIALIZER(CAP_SHUTDOWN); 109 const cap_rights_t cap_symlinkat_rights = CAP_RIGHTS_INITIALIZER(CAP_SYMLINKAT); 110 const cap_rights_t cap_unlinkat_rights = CAP_RIGHTS_INITIALIZER(CAP_UNLINKAT); 111 const cap_rights_t cap_write_rights = CAP_RIGHTS_INITIALIZER(CAP_WRITE); 112 const cap_rights_t cap_no_rights = CAP_RIGHTS_INITIALIZER(0ULL); 113 #endif 114 115 #define CAPARSIZE_MIN (CAP_RIGHTS_VERSION_00 + 2) 116 #define CAPARSIZE_MAX (CAP_RIGHTS_VERSION + 2) 117 118 static __inline int 119 right_to_index(uint64_t right) 120 { 121 static const int bit2idx[] = { 122 -1, 0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, 123 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 124 }; 125 int idx; 126 127 idx = CAPIDXBIT(right); 128 assert(idx >= 0 && idx < sizeof(bit2idx) / sizeof(bit2idx[0])); 129 return (bit2idx[idx]); 130 } 131 132 static void 133 cap_rights_vset(cap_rights_t *rights, va_list ap) 134 { 135 uint64_t right; 136 int i, n __unused; 137 138 assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00); 139 140 n = CAPARSIZE(rights); 141 assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX); 142 143 for (;;) { 144 right = (uint64_t)va_arg(ap, unsigned long long); 145 if (right == 0) 146 break; 147 assert(CAPRVER(right) == 0); 148 i = right_to_index(right); 149 assert(i >= 0); 150 assert(i < n); 151 assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right)); 152 rights->cr_rights[i] |= right; 153 assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right)); 154 } 155 } 156 157 static void 158 cap_rights_vclear(cap_rights_t *rights, va_list ap) 159 { 160 uint64_t right; 161 int i, n __unused; 162 163 assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00); 164 165 n = CAPARSIZE(rights); 166 assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX); 167 168 for (;;) { 169 right = (uint64_t)va_arg(ap, unsigned long long); 170 if (right == 0) 171 break; 172 assert(CAPRVER(right) == 0); 173 i = right_to_index(right); 174 assert(i >= 0); 175 assert(i < n); 176 assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right)); 177 rights->cr_rights[i] &= ~(right & 0x01FFFFFFFFFFFFFFULL); 178 assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right)); 179 } 180 } 181 182 static bool 183 cap_rights_is_vset(const cap_rights_t *rights, va_list ap) 184 { 185 uint64_t right; 186 int i, n __unused; 187 188 assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00); 189 190 n = CAPARSIZE(rights); 191 assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX); 192 193 for (;;) { 194 right = (uint64_t)va_arg(ap, unsigned long long); 195 if (right == 0) 196 break; 197 assert(CAPRVER(right) == 0); 198 i = right_to_index(right); 199 assert(i >= 0); 200 assert(i < n); 201 assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right)); 202 if ((rights->cr_rights[i] & right) != right) 203 return (false); 204 } 205 206 return (true); 207 } 208 209 cap_rights_t * 210 __cap_rights_init(int version, cap_rights_t *rights, ...) 211 { 212 unsigned int n __unused; 213 va_list ap; 214 215 assert(version == CAP_RIGHTS_VERSION_00); 216 217 n = version + 2; 218 assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX); 219 CAP_NONE(rights); 220 va_start(ap, rights); 221 cap_rights_vset(rights, ap); 222 va_end(ap); 223 224 return (rights); 225 } 226 227 cap_rights_t * 228 __cap_rights_set(cap_rights_t *rights, ...) 229 { 230 va_list ap; 231 232 assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00); 233 234 va_start(ap, rights); 235 cap_rights_vset(rights, ap); 236 va_end(ap); 237 238 return (rights); 239 } 240 241 cap_rights_t * 242 __cap_rights_clear(cap_rights_t *rights, ...) 243 { 244 va_list ap; 245 246 assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00); 247 248 va_start(ap, rights); 249 cap_rights_vclear(rights, ap); 250 va_end(ap); 251 252 return (rights); 253 } 254 255 bool 256 __cap_rights_is_set(const cap_rights_t *rights, ...) 257 { 258 va_list ap; 259 bool ret; 260 261 assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00); 262 263 va_start(ap, rights); 264 ret = cap_rights_is_vset(rights, ap); 265 va_end(ap); 266 267 return (ret); 268 } 269 270 bool 271 cap_rights_is_empty(const cap_rights_t *rights) 272 { 273 #ifndef _KERNEL 274 cap_rights_t cap_no_rights; 275 cap_rights_init(&cap_no_rights); 276 #endif 277 278 assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00); 279 assert(CAPVER(&cap_no_rights) == CAP_RIGHTS_VERSION_00); 280 281 for (int i = 0; i < CAPARSIZE(rights); i++) { 282 if (rights->cr_rights[i] != cap_no_rights.cr_rights[i]) 283 return (false); 284 } 285 286 return (true); 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 #ifndef _KERNEL 366 bool 367 cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little) 368 { 369 unsigned int i, n; 370 371 assert(CAPVER(big) == CAP_RIGHTS_VERSION_00); 372 assert(CAPVER(little) == CAP_RIGHTS_VERSION_00); 373 assert(CAPVER(big) == CAPVER(little)); 374 375 n = CAPARSIZE(big); 376 assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX); 377 378 for (i = 0; i < n; i++) { 379 if ((big->cr_rights[i] & little->cr_rights[i]) != 380 little->cr_rights[i]) { 381 return (false); 382 } 383 } 384 385 return (true); 386 } 387 #endif 388