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 57 CAP_RIGHTS_DEFINE1(cap_accept_rights, CAP_ACCEPT); 58 CAP_RIGHTS_DEFINE1(cap_bind_rights, CAP_BIND); 59 CAP_RIGHTS_DEFINE1(cap_connect_rights, CAP_CONNECT); 60 CAP_RIGHTS_DEFINE1(cap_event_rights, CAP_EVENT); 61 CAP_RIGHTS_DEFINE1(cap_fchdir_rights, CAP_FCHDIR); 62 CAP_RIGHTS_DEFINE1(cap_fcntl_rights, CAP_FCNTL); 63 CAP_RIGHTS_DEFINE1(cap_fexecve_rights, CAP_FEXECVE); 64 CAP_RIGHTS_DEFINE1(cap_flock_rights, CAP_FLOCK); 65 CAP_RIGHTS_DEFINE1(cap_fpathconf_rights, CAP_FPATHCONF); 66 CAP_RIGHTS_DEFINE1(cap_fstat_rights, CAP_FSTAT); 67 CAP_RIGHTS_DEFINE1(cap_fsync_rights, CAP_FSYNC); 68 CAP_RIGHTS_DEFINE1(cap_ftruncate_rights, CAP_FTRUNCATE); 69 CAP_RIGHTS_DEFINE1(cap_getpeername_rights, CAP_GETPEERNAME); 70 CAP_RIGHTS_DEFINE1(cap_getsockname_rights, CAP_GETSOCKNAME); 71 CAP_RIGHTS_DEFINE1(cap_getsockopt_rights, CAP_GETSOCKOPT); 72 CAP_RIGHTS_DEFINE1(cap_ioctl_rights, CAP_IOCTL); 73 CAP_RIGHTS_DEFINE1(cap_listen_rights, CAP_LISTEN); 74 CAP_RIGHTS_DEFINE1(cap_mmap_rights, CAP_MMAP); 75 CAP_RIGHTS_DEFINE1(cap_pdgetpid_rights, CAP_PDGETPID); 76 CAP_RIGHTS_DEFINE1(cap_pdkill_rights, CAP_PDKILL); 77 CAP_RIGHTS_DEFINE1(cap_pread_rights, CAP_PREAD); 78 CAP_RIGHTS_DEFINE1(cap_pwrite_rights, CAP_PWRITE); 79 CAP_RIGHTS_DEFINE1(cap_read_rights, CAP_READ); 80 CAP_RIGHTS_DEFINE1(cap_recv_rights, CAP_RECV); 81 CAP_RIGHTS_DEFINE1(cap_send_rights, CAP_SEND); 82 CAP_RIGHTS_DEFINE1(cap_setsockopt_rights, CAP_SETSOCKOPT); 83 CAP_RIGHTS_DEFINE1(cap_shutdown_rights, CAP_SHUTDOWN); 84 CAP_RIGHTS_DEFINE1(cap_write_rights, CAP_WRITE); 85 86 __read_mostly cap_rights_t cap_no_rights; 87 CAP_RIGHTS_SYSINIT0(cap_no_rights, cap_no_rights); 88 #endif 89 90 #define CAPARSIZE_MIN (CAP_RIGHTS_VERSION_00 + 2) 91 #define CAPARSIZE_MAX (CAP_RIGHTS_VERSION + 2) 92 93 static __inline int 94 right_to_index(uint64_t right) 95 { 96 static const int bit2idx[] = { 97 -1, 0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, 98 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 99 }; 100 int idx; 101 102 idx = CAPIDXBIT(right); 103 assert(idx >= 0 && idx < sizeof(bit2idx) / sizeof(bit2idx[0])); 104 return (bit2idx[idx]); 105 } 106 107 static void 108 cap_rights_vset(cap_rights_t *rights, va_list ap) 109 { 110 uint64_t right; 111 int i, n; 112 113 assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00); 114 115 n = CAPARSIZE(rights); 116 assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX); 117 118 for (;;) { 119 right = (uint64_t)va_arg(ap, unsigned long long); 120 if (right == 0) 121 break; 122 assert(CAPRVER(right) == 0); 123 i = right_to_index(right); 124 assert(i >= 0); 125 assert(i < n); 126 assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right)); 127 rights->cr_rights[i] |= right; 128 assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right)); 129 } 130 } 131 132 static void 133 cap_rights_vclear(cap_rights_t *rights, va_list ap) 134 { 135 uint64_t right; 136 int i, n; 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 & 0x01FFFFFFFFFFFFFFULL); 153 assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right)); 154 } 155 } 156 157 static bool 158 cap_rights_is_vset(const cap_rights_t *rights, va_list ap) 159 { 160 uint64_t right; 161 int i, n; 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 if ((rights->cr_rights[i] & right) != right) 178 return (false); 179 } 180 181 return (true); 182 } 183 184 void 185 __cap_rights_sysinit(void *arg) 186 { 187 struct cap_rights_init_args *cria = arg; 188 cap_rights_t *rights = cria->cria_rights; 189 190 __cap_rights_init(CAP_RIGHTS_VERSION, rights, cria->cria_value1, 191 cria->cria_value2, cria->cria_value3, cria->cria_value4, 0ULL); 192 } 193 194 cap_rights_t * 195 __cap_rights_init(int version, cap_rights_t *rights, ...) 196 { 197 unsigned int n; 198 va_list ap; 199 200 assert(version == CAP_RIGHTS_VERSION_00); 201 202 n = version + 2; 203 assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX); 204 CAP_NONE(rights); 205 va_start(ap, rights); 206 cap_rights_vset(rights, ap); 207 va_end(ap); 208 209 return (rights); 210 } 211 212 cap_rights_t * 213 __cap_rights_set(cap_rights_t *rights, ...) 214 { 215 va_list ap; 216 217 assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00); 218 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 * 227 __cap_rights_clear(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_vclear(rights, ap); 235 va_end(ap); 236 237 return (rights); 238 } 239 240 bool 241 __cap_rights_is_set(const cap_rights_t *rights, ...) 242 { 243 va_list ap; 244 bool ret; 245 246 assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00); 247 248 va_start(ap, rights); 249 ret = cap_rights_is_vset(rights, ap); 250 va_end(ap); 251 252 return (ret); 253 } 254 255 bool 256 cap_rights_is_valid(const cap_rights_t *rights) 257 { 258 cap_rights_t allrights; 259 int i, j; 260 261 if (CAPVER(rights) != CAP_RIGHTS_VERSION_00) 262 return (false); 263 if (CAPARSIZE(rights) < CAPARSIZE_MIN || 264 CAPARSIZE(rights) > CAPARSIZE_MAX) { 265 return (false); 266 } 267 CAP_ALL(&allrights); 268 if (!cap_rights_contains(&allrights, rights)) 269 return (false); 270 for (i = 0; i < CAPARSIZE(rights); i++) { 271 j = right_to_index(rights->cr_rights[i]); 272 if (i != j) 273 return (false); 274 if (i > 0) { 275 if (CAPRVER(rights->cr_rights[i]) != 0) 276 return (false); 277 } 278 } 279 280 return (true); 281 } 282 283 cap_rights_t * 284 cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src) 285 { 286 unsigned int i, n; 287 288 assert(CAPVER(dst) == CAP_RIGHTS_VERSION_00); 289 assert(CAPVER(src) == CAP_RIGHTS_VERSION_00); 290 assert(CAPVER(dst) == CAPVER(src)); 291 assert(cap_rights_is_valid(src)); 292 assert(cap_rights_is_valid(dst)); 293 294 n = CAPARSIZE(dst); 295 assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX); 296 297 for (i = 0; i < n; i++) 298 dst->cr_rights[i] |= src->cr_rights[i]; 299 300 assert(cap_rights_is_valid(src)); 301 assert(cap_rights_is_valid(dst)); 302 303 return (dst); 304 } 305 306 cap_rights_t * 307 cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src) 308 { 309 unsigned int i, n; 310 311 assert(CAPVER(dst) == CAP_RIGHTS_VERSION_00); 312 assert(CAPVER(src) == CAP_RIGHTS_VERSION_00); 313 assert(CAPVER(dst) == CAPVER(src)); 314 assert(cap_rights_is_valid(src)); 315 assert(cap_rights_is_valid(dst)); 316 317 n = CAPARSIZE(dst); 318 assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX); 319 320 for (i = 0; i < n; i++) { 321 dst->cr_rights[i] &= 322 ~(src->cr_rights[i] & 0x01FFFFFFFFFFFFFFULL); 323 } 324 325 assert(cap_rights_is_valid(src)); 326 assert(cap_rights_is_valid(dst)); 327 328 return (dst); 329 } 330 331 bool 332 cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little) 333 { 334 unsigned int i, n; 335 336 assert(CAPVER(big) == CAP_RIGHTS_VERSION_00); 337 assert(CAPVER(little) == CAP_RIGHTS_VERSION_00); 338 assert(CAPVER(big) == CAPVER(little)); 339 340 n = CAPARSIZE(big); 341 assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX); 342 343 for (i = 0; i < n; i++) { 344 if ((big->cr_rights[i] & little->cr_rights[i]) != 345 little->cr_rights[i]) { 346 return (false); 347 } 348 } 349 350 return (true); 351 } 352