1 /*- 2 * Copyright (c) 2013 FreeBSD Foundation 3 * All rights reserved. 4 * 5 * This software was developed by Pawel Jakub Dawidek under sponsorship from 6 * the FreeBSD Foundation. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 /* 34 * Note that this file is compiled into the kernel and into libc. 35 */ 36 37 #ifdef _KERNEL 38 #include <sys/types.h> 39 #include <sys/capability.h> 40 #include <sys/systm.h> 41 42 #include <machine/stdarg.h> 43 #else /* !_KERNEL */ 44 #include <sys/types.h> 45 #include <sys/capability.h> 46 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 #endif 57 58 #define CAPARSIZE_MIN (CAP_RIGHTS_VERSION_00 + 2) 59 #define CAPARSIZE_MAX (CAP_RIGHTS_VERSION + 2) 60 61 static __inline int 62 right_to_index(uint64_t right) 63 { 64 static const int bit2idx[] = { 65 -1, 0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, 66 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 67 }; 68 int idx; 69 70 idx = CAPIDXBIT(right); 71 assert(idx >= 0 && idx < sizeof(bit2idx) / sizeof(bit2idx[0])); 72 return (bit2idx[idx]); 73 } 74 75 static void 76 cap_rights_vset(cap_rights_t *rights, va_list ap) 77 { 78 uint64_t right; 79 int i, n; 80 81 assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00); 82 83 n = CAPARSIZE(rights); 84 assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX); 85 86 for (;;) { 87 right = (uint64_t)va_arg(ap, unsigned long long); 88 if (right == 0) 89 break; 90 assert(CAPRVER(right) == 0); 91 i = right_to_index(right); 92 assert(i >= 0); 93 assert(i < n); 94 assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right)); 95 rights->cr_rights[i] |= right; 96 assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right)); 97 } 98 } 99 100 static void 101 cap_rights_vclear(cap_rights_t *rights, va_list ap) 102 { 103 uint64_t right; 104 int i, n; 105 106 assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00); 107 108 n = CAPARSIZE(rights); 109 assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX); 110 111 for (;;) { 112 right = (uint64_t)va_arg(ap, unsigned long long); 113 if (right == 0) 114 break; 115 assert(CAPRVER(right) == 0); 116 i = right_to_index(right); 117 assert(i >= 0); 118 assert(i < n); 119 assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right)); 120 rights->cr_rights[i] &= ~(right & 0x01FFFFFFFFFFFFFFULL); 121 assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right)); 122 } 123 } 124 125 static bool 126 cap_rights_is_vset(const cap_rights_t *rights, va_list ap) 127 { 128 uint64_t right; 129 int i, n; 130 131 assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00); 132 133 n = CAPARSIZE(rights); 134 assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX); 135 136 for (;;) { 137 right = (uint64_t)va_arg(ap, unsigned long long); 138 if (right == 0) 139 break; 140 assert(CAPRVER(right) == 0); 141 i = right_to_index(right); 142 assert(i >= 0); 143 assert(i < n); 144 assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right)); 145 if ((rights->cr_rights[i] & right) != right) 146 return (false); 147 } 148 149 return (true); 150 } 151 152 cap_rights_t * 153 __cap_rights_init(int version, cap_rights_t *rights, ...) 154 { 155 unsigned int n; 156 va_list ap; 157 158 assert(version == CAP_RIGHTS_VERSION_00); 159 160 n = version + 2; 161 assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX); 162 memset(rights->cr_rights, 0, sizeof(rights->cr_rights[0]) * n); 163 CAP_NONE(rights); 164 va_start(ap, rights); 165 cap_rights_vset(rights, ap); 166 va_end(ap); 167 168 return (rights); 169 } 170 171 cap_rights_t * 172 __cap_rights_set(cap_rights_t *rights, ...) 173 { 174 va_list ap; 175 176 assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00); 177 178 va_start(ap, rights); 179 cap_rights_vset(rights, ap); 180 va_end(ap); 181 182 return (rights); 183 } 184 185 cap_rights_t * 186 __cap_rights_clear(cap_rights_t *rights, ...) 187 { 188 va_list ap; 189 190 assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00); 191 192 va_start(ap, rights); 193 cap_rights_vclear(rights, ap); 194 va_end(ap); 195 196 return (rights); 197 } 198 199 bool 200 __cap_rights_is_set(const cap_rights_t *rights, ...) 201 { 202 va_list ap; 203 bool ret; 204 205 assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00); 206 207 va_start(ap, rights); 208 ret = cap_rights_is_vset(rights, ap); 209 va_end(ap); 210 211 return (ret); 212 } 213 214 bool 215 cap_rights_is_valid(const cap_rights_t *rights) 216 { 217 cap_rights_t allrights; 218 int i, j; 219 220 if (CAPVER(rights) != CAP_RIGHTS_VERSION_00) 221 return (false); 222 if (CAPARSIZE(rights) < CAPARSIZE_MIN || 223 CAPARSIZE(rights) > CAPARSIZE_MAX) { 224 return (false); 225 } 226 CAP_ALL(&allrights); 227 if (!cap_rights_contains(&allrights, rights)) 228 return (false); 229 for (i = 0; i < CAPARSIZE(rights); i++) { 230 j = right_to_index(rights->cr_rights[i]); 231 if (i != j) 232 return (false); 233 if (i > 0) { 234 if (CAPRVER(rights->cr_rights[i]) != 0) 235 return (false); 236 } 237 } 238 239 return (true); 240 } 241 242 cap_rights_t * 243 cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src) 244 { 245 unsigned int i, n; 246 247 assert(CAPVER(dst) == CAP_RIGHTS_VERSION_00); 248 assert(CAPVER(src) == CAP_RIGHTS_VERSION_00); 249 assert(CAPVER(dst) == CAPVER(src)); 250 assert(cap_rights_is_valid(src)); 251 assert(cap_rights_is_valid(dst)); 252 253 n = CAPARSIZE(dst); 254 assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX); 255 256 for (i = 0; i < n; i++) 257 dst->cr_rights[i] |= src->cr_rights[i]; 258 259 assert(cap_rights_is_valid(src)); 260 assert(cap_rights_is_valid(dst)); 261 262 return (dst); 263 } 264 265 cap_rights_t * 266 cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src) 267 { 268 unsigned int i, n; 269 270 assert(CAPVER(dst) == CAP_RIGHTS_VERSION_00); 271 assert(CAPVER(src) == CAP_RIGHTS_VERSION_00); 272 assert(CAPVER(dst) == CAPVER(src)); 273 assert(cap_rights_is_valid(src)); 274 assert(cap_rights_is_valid(dst)); 275 276 n = CAPARSIZE(dst); 277 assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX); 278 279 for (i = 0; i < n; i++) { 280 dst->cr_rights[i] &= 281 ~(src->cr_rights[i] & 0x01FFFFFFFFFFFFFFULL); 282 } 283 284 assert(cap_rights_is_valid(src)); 285 assert(cap_rights_is_valid(dst)); 286 287 return (dst); 288 } 289 290 bool 291 cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little) 292 { 293 unsigned int i, n; 294 295 assert(CAPVER(big) == CAP_RIGHTS_VERSION_00); 296 assert(CAPVER(little) == CAP_RIGHTS_VERSION_00); 297 assert(CAPVER(big) == CAPVER(little)); 298 299 n = CAPARSIZE(big); 300 assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX); 301 302 for (i = 0; i < n; i++) { 303 if ((big->cr_rights[i] & little->cr_rights[i]) != 304 little->cr_rights[i]) { 305 return (false); 306 } 307 } 308 309 return (true); 310 } 311