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