1 1.84 ad /* $NetBSD: kern_auth.c,v 1.84 2023/10/04 22:17:09 ad Exp $ */ 2 1.2 elad 3 1.2 elad /*- 4 1.2 elad * Copyright (c) 2005, 2006 Elad Efrat <elad (at) NetBSD.org> 5 1.2 elad * All rights reserved. 6 1.2 elad * 7 1.2 elad * Redistribution and use in source and binary forms, with or without 8 1.2 elad * modification, are permitted provided that the following conditions 9 1.2 elad * are met: 10 1.2 elad * 1. Redistributions of source code must retain the above copyright 11 1.2 elad * notice, this list of conditions and the following disclaimer. 12 1.2 elad * 2. Redistributions in binary form must reproduce the above copyright 13 1.2 elad * notice, this list of conditions and the following disclaimer in the 14 1.2 elad * documentation and/or other materials provided with the distribution. 15 1.37 elad * 3. The name of the author may not be used to endorse or promote products 16 1.2 elad * derived from this software without specific prior written permission. 17 1.2 elad * 18 1.2 elad * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 1.2 elad * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 1.2 elad * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 1.2 elad * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 1.2 elad * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 1.2 elad * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 1.2 elad * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 1.2 elad * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 1.2 elad * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 1.2 elad * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 1.2 elad */ 29 1.2 elad 30 1.20 elad #include <sys/cdefs.h> 31 1.84 ad __KERNEL_RCSID(0, "$NetBSD: kern_auth.c,v 1.84 2023/10/04 22:17:09 ad Exp $"); 32 1.20 elad 33 1.46 christos #include <sys/types.h> 34 1.2 elad #include <sys/param.h> 35 1.2 elad #include <sys/queue.h> 36 1.2 elad #include <sys/proc.h> 37 1.2 elad #include <sys/ucred.h> 38 1.2 elad #include <sys/pool.h> 39 1.75 christos #define __KAUTH_PRIVATE 40 1.2 elad #include <sys/kauth.h> 41 1.34 ad #include <sys/kmem.h> 42 1.44 ad #include <sys/rwlock.h> 43 1.65 elad #include <sys/sysctl.h> 44 1.55 ad #include <sys/atomic.h> 45 1.46 christos #include <sys/specificdata.h> 46 1.64 elad #include <sys/vnode.h> 47 1.41 elad 48 1.66 jym #include <secmodel/secmodel.h> 49 1.66 jym 50 1.41 elad /* 51 1.41 elad * Secmodel-specific credentials. 52 1.41 elad */ 53 1.41 elad struct kauth_key { 54 1.66 jym secmodel_t ks_secmodel; /* secmodel */ 55 1.41 elad specificdata_key_t ks_key; /* key */ 56 1.41 elad }; 57 1.2 elad 58 1.46 christos 59 1.2 elad /* 60 1.2 elad * Listener. 61 1.2 elad */ 62 1.2 elad struct kauth_listener { 63 1.2 elad kauth_scope_callback_t func; /* callback */ 64 1.2 elad kauth_scope_t scope; /* scope backpointer */ 65 1.11 ad u_int refcnt; /* reference count */ 66 1.2 elad SIMPLEQ_ENTRY(kauth_listener) listener_next; /* listener list */ 67 1.2 elad }; 68 1.2 elad 69 1.2 elad /* 70 1.2 elad * Scope. 71 1.2 elad */ 72 1.2 elad struct kauth_scope { 73 1.2 elad const char *id; /* scope name */ 74 1.2 elad void *cookie; /* user cookie */ 75 1.11 ad u_int nlisteners; /* # of listeners */ 76 1.2 elad SIMPLEQ_HEAD(, kauth_listener) listenq; /* listener list */ 77 1.2 elad SIMPLEQ_ENTRY(kauth_scope) next_scope; /* scope list */ 78 1.2 elad }; 79 1.2 elad 80 1.41 elad static int kauth_cred_hook(kauth_cred_t, kauth_action_t, void *, void *); 81 1.2 elad 82 1.2 elad /* List of scopes and its lock. */ 83 1.54 matt static SIMPLEQ_HEAD(, kauth_scope) scope_list = 84 1.54 matt SIMPLEQ_HEAD_INITIALIZER(scope_list); 85 1.2 elad 86 1.2 elad /* Built-in scopes: generic, process. */ 87 1.2 elad static kauth_scope_t kauth_builtin_scope_generic; 88 1.19 elad static kauth_scope_t kauth_builtin_scope_system; 89 1.2 elad static kauth_scope_t kauth_builtin_scope_process; 90 1.19 elad static kauth_scope_t kauth_builtin_scope_network; 91 1.19 elad static kauth_scope_t kauth_builtin_scope_machdep; 92 1.25 elad static kauth_scope_t kauth_builtin_scope_device; 93 1.41 elad static kauth_scope_t kauth_builtin_scope_cred; 94 1.64 elad static kauth_scope_t kauth_builtin_scope_vnode; 95 1.2 elad 96 1.41 elad static specificdata_domain_t kauth_domain; 97 1.53 ad static pool_cache_t kauth_cred_cache; 98 1.65 elad 99 1.44 ad krwlock_t kauth_lock; 100 1.41 elad 101 1.2 elad /* Allocate new, empty kauth credentials. */ 102 1.2 elad kauth_cred_t 103 1.3 yamt kauth_cred_alloc(void) 104 1.3 yamt { 105 1.2 elad kauth_cred_t cred; 106 1.2 elad 107 1.53 ad cred = pool_cache_get(kauth_cred_cache, PR_WAITOK); 108 1.53 ad 109 1.2 elad cred->cr_refcnt = 1; 110 1.53 ad cred->cr_uid = 0; 111 1.53 ad cred->cr_euid = 0; 112 1.53 ad cred->cr_svuid = 0; 113 1.53 ad cred->cr_gid = 0; 114 1.53 ad cred->cr_egid = 0; 115 1.53 ad cred->cr_svgid = 0; 116 1.53 ad cred->cr_ngroups = 0; 117 1.53 ad 118 1.41 elad specificdata_init(kauth_domain, &cred->cr_sd); 119 1.41 elad kauth_cred_hook(cred, KAUTH_CRED_INIT, NULL, NULL); 120 1.2 elad 121 1.2 elad return (cred); 122 1.2 elad } 123 1.2 elad 124 1.2 elad /* Increment reference count to cred. */ 125 1.84 ad kauth_cred_t 126 1.2 elad kauth_cred_hold(kauth_cred_t cred) 127 1.2 elad { 128 1.2 elad KASSERT(cred != NULL); 129 1.74 mlelstv KASSERT(cred != NOCRED); 130 1.74 mlelstv KASSERT(cred != FSCRED); 131 1.11 ad KASSERT(cred->cr_refcnt > 0); 132 1.2 elad 133 1.70 cheusov atomic_inc_uint(&cred->cr_refcnt); 134 1.84 ad return cred; 135 1.2 elad } 136 1.2 elad 137 1.2 elad /* Decrease reference count to cred. If reached zero, free it. */ 138 1.2 elad void 139 1.3 yamt kauth_cred_free(kauth_cred_t cred) 140 1.3 yamt { 141 1.11 ad 142 1.2 elad KASSERT(cred != NULL); 143 1.74 mlelstv KASSERT(cred != NOCRED); 144 1.74 mlelstv KASSERT(cred != FSCRED); 145 1.11 ad KASSERT(cred->cr_refcnt > 0); 146 1.63 yamt ASSERT_SLEEPABLE(); 147 1.2 elad 148 1.81 riastrad membar_release(); 149 1.56 ad if (atomic_dec_uint_nv(&cred->cr_refcnt) > 0) 150 1.55 ad return; 151 1.81 riastrad membar_acquire(); 152 1.55 ad 153 1.55 ad kauth_cred_hook(cred, KAUTH_CRED_FREE, NULL, NULL); 154 1.55 ad specificdata_fini(kauth_domain, &cred->cr_sd); 155 1.55 ad pool_cache_put(kauth_cred_cache, cred); 156 1.2 elad } 157 1.2 elad 158 1.49 dsl static void 159 1.48 dsl kauth_cred_clone1(kauth_cred_t from, kauth_cred_t to, bool copy_groups) 160 1.48 dsl { 161 1.2 elad KASSERT(from != NULL); 162 1.74 mlelstv KASSERT(from != NOCRED); 163 1.74 mlelstv KASSERT(from != FSCRED); 164 1.2 elad KASSERT(to != NULL); 165 1.74 mlelstv KASSERT(to != NOCRED); 166 1.74 mlelstv KASSERT(to != FSCRED); 167 1.11 ad KASSERT(from->cr_refcnt > 0); 168 1.2 elad 169 1.2 elad to->cr_uid = from->cr_uid; 170 1.2 elad to->cr_euid = from->cr_euid; 171 1.2 elad to->cr_svuid = from->cr_svuid; 172 1.2 elad to->cr_gid = from->cr_gid; 173 1.2 elad to->cr_egid = from->cr_egid; 174 1.2 elad to->cr_svgid = from->cr_svgid; 175 1.48 dsl if (copy_groups) { 176 1.48 dsl to->cr_ngroups = from->cr_ngroups; 177 1.48 dsl memcpy(to->cr_groups, from->cr_groups, sizeof(to->cr_groups)); 178 1.48 dsl } 179 1.41 elad 180 1.41 elad kauth_cred_hook(from, KAUTH_CRED_COPY, to, NULL); 181 1.2 elad } 182 1.2 elad 183 1.49 dsl void 184 1.49 dsl kauth_cred_clone(kauth_cred_t from, kauth_cred_t to) 185 1.49 dsl { 186 1.49 dsl kauth_cred_clone1(from, to, true); 187 1.49 dsl } 188 1.49 dsl 189 1.2 elad /* 190 1.2 elad * Duplicate cred and return a new kauth_cred_t. 191 1.2 elad */ 192 1.2 elad kauth_cred_t 193 1.2 elad kauth_cred_dup(kauth_cred_t cred) 194 1.2 elad { 195 1.2 elad kauth_cred_t new_cred; 196 1.2 elad 197 1.2 elad KASSERT(cred != NULL); 198 1.74 mlelstv KASSERT(cred != NOCRED); 199 1.74 mlelstv KASSERT(cred != FSCRED); 200 1.11 ad KASSERT(cred->cr_refcnt > 0); 201 1.2 elad 202 1.2 elad new_cred = kauth_cred_alloc(); 203 1.2 elad 204 1.2 elad kauth_cred_clone(cred, new_cred); 205 1.2 elad 206 1.2 elad return (new_cred); 207 1.2 elad } 208 1.2 elad 209 1.2 elad /* 210 1.2 elad * Similar to crcopy(), only on a kauth_cred_t. 211 1.2 elad * XXX: Is this even needed? [kauth_cred_copy] 212 1.2 elad */ 213 1.2 elad kauth_cred_t 214 1.2 elad kauth_cred_copy(kauth_cred_t cred) 215 1.2 elad { 216 1.2 elad kauth_cred_t new_cred; 217 1.2 elad 218 1.2 elad KASSERT(cred != NULL); 219 1.74 mlelstv KASSERT(cred != NOCRED); 220 1.74 mlelstv KASSERT(cred != FSCRED); 221 1.11 ad KASSERT(cred->cr_refcnt > 0); 222 1.2 elad 223 1.2 elad /* If the provided credentials already have one reference, use them. */ 224 1.2 elad if (cred->cr_refcnt == 1) 225 1.2 elad return (cred); 226 1.2 elad 227 1.2 elad new_cred = kauth_cred_alloc(); 228 1.2 elad 229 1.2 elad kauth_cred_clone(cred, new_cred); 230 1.2 elad 231 1.2 elad kauth_cred_free(cred); 232 1.2 elad 233 1.2 elad return (new_cred); 234 1.2 elad } 235 1.2 elad 236 1.38 elad void 237 1.38 elad kauth_proc_fork(struct proc *parent, struct proc *child) 238 1.38 elad { 239 1.44 ad 240 1.59 ad mutex_enter(parent->p_lock); 241 1.84 ad child->p_cred = kauth_cred_hold(parent->p_cred); 242 1.59 ad mutex_exit(parent->p_lock); 243 1.41 elad 244 1.44 ad /* XXX: relies on parent process stalling during fork() */ 245 1.41 elad kauth_cred_hook(parent->p_cred, KAUTH_CRED_FORK, parent, 246 1.41 elad child); 247 1.38 elad } 248 1.38 elad 249 1.71 cheusov void 250 1.71 cheusov kauth_proc_chroot(kauth_cred_t cred, struct cwdinfo *cwdi) 251 1.71 cheusov { 252 1.71 cheusov kauth_cred_hook(cred, KAUTH_CRED_CHROOT, cwdi, NULL); 253 1.71 cheusov } 254 1.71 cheusov 255 1.2 elad uid_t 256 1.2 elad kauth_cred_getuid(kauth_cred_t cred) 257 1.2 elad { 258 1.2 elad KASSERT(cred != NULL); 259 1.74 mlelstv KASSERT(cred != NOCRED); 260 1.74 mlelstv KASSERT(cred != FSCRED); 261 1.2 elad 262 1.2 elad return (cred->cr_uid); 263 1.2 elad } 264 1.2 elad 265 1.2 elad uid_t 266 1.2 elad kauth_cred_geteuid(kauth_cred_t cred) 267 1.2 elad { 268 1.2 elad KASSERT(cred != NULL); 269 1.74 mlelstv KASSERT(cred != NOCRED); 270 1.74 mlelstv KASSERT(cred != FSCRED); 271 1.2 elad 272 1.2 elad return (cred->cr_euid); 273 1.2 elad } 274 1.2 elad 275 1.2 elad uid_t 276 1.2 elad kauth_cred_getsvuid(kauth_cred_t cred) 277 1.2 elad { 278 1.2 elad KASSERT(cred != NULL); 279 1.74 mlelstv KASSERT(cred != NOCRED); 280 1.74 mlelstv KASSERT(cred != FSCRED); 281 1.2 elad 282 1.2 elad return (cred->cr_svuid); 283 1.2 elad } 284 1.2 elad 285 1.2 elad gid_t 286 1.2 elad kauth_cred_getgid(kauth_cred_t cred) 287 1.2 elad { 288 1.2 elad KASSERT(cred != NULL); 289 1.74 mlelstv KASSERT(cred != NOCRED); 290 1.74 mlelstv KASSERT(cred != FSCRED); 291 1.2 elad 292 1.2 elad return (cred->cr_gid); 293 1.2 elad } 294 1.2 elad 295 1.2 elad gid_t 296 1.2 elad kauth_cred_getegid(kauth_cred_t cred) 297 1.2 elad { 298 1.2 elad KASSERT(cred != NULL); 299 1.74 mlelstv KASSERT(cred != NOCRED); 300 1.74 mlelstv KASSERT(cred != FSCRED); 301 1.2 elad 302 1.2 elad return (cred->cr_egid); 303 1.2 elad } 304 1.2 elad 305 1.2 elad gid_t 306 1.2 elad kauth_cred_getsvgid(kauth_cred_t cred) 307 1.2 elad { 308 1.2 elad KASSERT(cred != NULL); 309 1.74 mlelstv KASSERT(cred != NOCRED); 310 1.74 mlelstv KASSERT(cred != FSCRED); 311 1.2 elad 312 1.2 elad return (cred->cr_svgid); 313 1.2 elad } 314 1.2 elad 315 1.2 elad void 316 1.2 elad kauth_cred_setuid(kauth_cred_t cred, uid_t uid) 317 1.2 elad { 318 1.2 elad KASSERT(cred != NULL); 319 1.74 mlelstv KASSERT(cred != NOCRED); 320 1.74 mlelstv KASSERT(cred != FSCRED); 321 1.11 ad KASSERT(cred->cr_refcnt == 1); 322 1.2 elad 323 1.2 elad cred->cr_uid = uid; 324 1.2 elad } 325 1.2 elad 326 1.2 elad void 327 1.2 elad kauth_cred_seteuid(kauth_cred_t cred, uid_t uid) 328 1.2 elad { 329 1.2 elad KASSERT(cred != NULL); 330 1.74 mlelstv KASSERT(cred != NOCRED); 331 1.74 mlelstv KASSERT(cred != FSCRED); 332 1.11 ad KASSERT(cred->cr_refcnt == 1); 333 1.2 elad 334 1.2 elad cred->cr_euid = uid; 335 1.2 elad } 336 1.2 elad 337 1.2 elad void 338 1.2 elad kauth_cred_setsvuid(kauth_cred_t cred, uid_t uid) 339 1.2 elad { 340 1.2 elad KASSERT(cred != NULL); 341 1.74 mlelstv KASSERT(cred != NOCRED); 342 1.74 mlelstv KASSERT(cred != FSCRED); 343 1.11 ad KASSERT(cred->cr_refcnt == 1); 344 1.2 elad 345 1.2 elad cred->cr_svuid = uid; 346 1.2 elad } 347 1.2 elad 348 1.2 elad void 349 1.2 elad kauth_cred_setgid(kauth_cred_t cred, gid_t gid) 350 1.2 elad { 351 1.2 elad KASSERT(cred != NULL); 352 1.74 mlelstv KASSERT(cred != NOCRED); 353 1.74 mlelstv KASSERT(cred != FSCRED); 354 1.11 ad KASSERT(cred->cr_refcnt == 1); 355 1.2 elad 356 1.2 elad cred->cr_gid = gid; 357 1.2 elad } 358 1.2 elad 359 1.2 elad void 360 1.2 elad kauth_cred_setegid(kauth_cred_t cred, gid_t gid) 361 1.2 elad { 362 1.2 elad KASSERT(cred != NULL); 363 1.74 mlelstv KASSERT(cred != NOCRED); 364 1.74 mlelstv KASSERT(cred != FSCRED); 365 1.11 ad KASSERT(cred->cr_refcnt == 1); 366 1.2 elad 367 1.2 elad cred->cr_egid = gid; 368 1.2 elad } 369 1.2 elad 370 1.2 elad void 371 1.2 elad kauth_cred_setsvgid(kauth_cred_t cred, gid_t gid) 372 1.2 elad { 373 1.2 elad KASSERT(cred != NULL); 374 1.74 mlelstv KASSERT(cred != NOCRED); 375 1.74 mlelstv KASSERT(cred != FSCRED); 376 1.11 ad KASSERT(cred->cr_refcnt == 1); 377 1.2 elad 378 1.2 elad cred->cr_svgid = gid; 379 1.2 elad } 380 1.2 elad 381 1.2 elad /* Checks if gid is a member of the groups in cred. */ 382 1.2 elad int 383 1.2 elad kauth_cred_ismember_gid(kauth_cred_t cred, gid_t gid, int *resultp) 384 1.2 elad { 385 1.62 lukem uint32_t i; 386 1.2 elad 387 1.2 elad KASSERT(cred != NULL); 388 1.74 mlelstv KASSERT(cred != NOCRED); 389 1.74 mlelstv KASSERT(cred != FSCRED); 390 1.2 elad KASSERT(resultp != NULL); 391 1.2 elad 392 1.2 elad *resultp = 0; 393 1.2 elad 394 1.2 elad for (i = 0; i < cred->cr_ngroups; i++) 395 1.2 elad if (cred->cr_groups[i] == gid) { 396 1.2 elad *resultp = 1; 397 1.2 elad break; 398 1.2 elad } 399 1.2 elad 400 1.2 elad return (0); 401 1.2 elad } 402 1.2 elad 403 1.80 christos int 404 1.80 christos kauth_cred_groupmember(kauth_cred_t cred, gid_t gid) 405 1.80 christos { 406 1.80 christos int ismember, error; 407 1.80 christos 408 1.80 christos KASSERT(cred != NULL); 409 1.80 christos KASSERT(cred != NOCRED); 410 1.80 christos KASSERT(cred != FSCRED); 411 1.80 christos 412 1.83 ad if (kauth_cred_getegid(cred) == gid) 413 1.83 ad return 0; 414 1.83 ad 415 1.80 christos error = kauth_cred_ismember_gid(cred, gid, &ismember); 416 1.80 christos if (error) 417 1.80 christos return error; 418 1.80 christos 419 1.83 ad return ismember ? 0 : -1; 420 1.80 christos } 421 1.80 christos 422 1.11 ad u_int 423 1.2 elad kauth_cred_ngroups(kauth_cred_t cred) 424 1.2 elad { 425 1.2 elad KASSERT(cred != NULL); 426 1.74 mlelstv KASSERT(cred != NOCRED); 427 1.74 mlelstv KASSERT(cred != FSCRED); 428 1.2 elad 429 1.2 elad return (cred->cr_ngroups); 430 1.2 elad } 431 1.2 elad 432 1.2 elad /* 433 1.2 elad * Return the group at index idx from the groups in cred. 434 1.2 elad */ 435 1.2 elad gid_t 436 1.11 ad kauth_cred_group(kauth_cred_t cred, u_int idx) 437 1.2 elad { 438 1.2 elad KASSERT(cred != NULL); 439 1.74 mlelstv KASSERT(cred != NOCRED); 440 1.74 mlelstv KASSERT(cred != FSCRED); 441 1.2 elad KASSERT(idx < cred->cr_ngroups); 442 1.2 elad 443 1.2 elad return (cred->cr_groups[idx]); 444 1.2 elad } 445 1.2 elad 446 1.2 elad /* XXX elad: gmuid is unused for now. */ 447 1.2 elad int 448 1.49 dsl kauth_cred_setgroups(kauth_cred_t cred, const gid_t *grbuf, size_t len, 449 1.52 yamt uid_t gmuid, enum uio_seg seg) 450 1.2 elad { 451 1.49 dsl int error = 0; 452 1.49 dsl 453 1.2 elad KASSERT(cred != NULL); 454 1.74 mlelstv KASSERT(cred != NOCRED); 455 1.74 mlelstv KASSERT(cred != FSCRED); 456 1.11 ad KASSERT(cred->cr_refcnt == 1); 457 1.2 elad 458 1.61 matt if (len > __arraycount(cred->cr_groups)) 459 1.49 dsl return EINVAL; 460 1.49 dsl 461 1.49 dsl if (len) { 462 1.52 yamt if (seg == UIO_SYSSPACE) { 463 1.49 dsl memcpy(cred->cr_groups, grbuf, 464 1.49 dsl len * sizeof(cred->cr_groups[0])); 465 1.52 yamt } else { 466 1.49 dsl error = copyin(grbuf, cred->cr_groups, 467 1.49 dsl len * sizeof(cred->cr_groups[0])); 468 1.49 dsl if (error != 0) 469 1.49 dsl len = 0; 470 1.49 dsl } 471 1.49 dsl } 472 1.2 elad memset(cred->cr_groups + len, 0xff, 473 1.2 elad sizeof(cred->cr_groups) - (len * sizeof(cred->cr_groups[0]))); 474 1.2 elad 475 1.2 elad cred->cr_ngroups = len; 476 1.2 elad 477 1.49 dsl return error; 478 1.48 dsl } 479 1.48 dsl 480 1.49 dsl /* This supports sys_setgroups() */ 481 1.48 dsl int 482 1.48 dsl kauth_proc_setgroups(struct lwp *l, kauth_cred_t ncred) 483 1.48 dsl { 484 1.48 dsl kauth_cred_t cred; 485 1.48 dsl int error; 486 1.48 dsl 487 1.48 dsl /* 488 1.48 dsl * At this point we could delete duplicate groups from ncred, 489 1.48 dsl * and plausibly sort the list - but in general the later is 490 1.48 dsl * a bad idea. 491 1.48 dsl */ 492 1.48 dsl proc_crmod_enter(); 493 1.48 dsl /* Maybe we should use curproc here ? */ 494 1.48 dsl cred = l->l_proc->p_cred; 495 1.48 dsl 496 1.48 dsl kauth_cred_clone1(cred, ncred, false); 497 1.48 dsl 498 1.48 dsl error = kauth_authorize_process(cred, KAUTH_PROCESS_SETID, 499 1.48 dsl l->l_proc, NULL, NULL, NULL); 500 1.48 dsl if (error != 0) { 501 1.48 dsl proc_crmod_leave(cred, ncred, false); 502 1.48 dsl return error; 503 1.48 dsl } 504 1.48 dsl 505 1.48 dsl /* Broadcast our credentials to the process and other LWPs. */ 506 1.48 dsl proc_crmod_leave(ncred, cred, true); 507 1.48 dsl return 0; 508 1.48 dsl } 509 1.48 dsl 510 1.2 elad int 511 1.49 dsl kauth_cred_getgroups(kauth_cred_t cred, gid_t *grbuf, size_t len, 512 1.52 yamt enum uio_seg seg) 513 1.2 elad { 514 1.2 elad KASSERT(cred != NULL); 515 1.2 elad 516 1.49 dsl if (len > cred->cr_ngroups) 517 1.49 dsl return EINVAL; 518 1.49 dsl 519 1.52 yamt if (seg == UIO_USERSPACE) 520 1.49 dsl return copyout(cred->cr_groups, grbuf, sizeof(*grbuf) * len); 521 1.2 elad memcpy(grbuf, cred->cr_groups, sizeof(*grbuf) * len); 522 1.2 elad 523 1.49 dsl return 0; 524 1.48 dsl } 525 1.48 dsl 526 1.41 elad int 527 1.66 jym kauth_register_key(secmodel_t secmodel, kauth_key_t *result) 528 1.41 elad { 529 1.41 elad kauth_key_t k; 530 1.41 elad specificdata_key_t key; 531 1.41 elad int error; 532 1.41 elad 533 1.41 elad KASSERT(result != NULL); 534 1.41 elad 535 1.41 elad error = specificdata_key_create(kauth_domain, &key, NULL); 536 1.41 elad if (error) 537 1.41 elad return (error); 538 1.41 elad 539 1.41 elad k = kmem_alloc(sizeof(*k), KM_SLEEP); 540 1.41 elad k->ks_secmodel = secmodel; 541 1.41 elad k->ks_key = key; 542 1.41 elad 543 1.41 elad *result = k; 544 1.41 elad 545 1.41 elad return (0); 546 1.41 elad } 547 1.41 elad 548 1.41 elad int 549 1.41 elad kauth_deregister_key(kauth_key_t key) 550 1.41 elad { 551 1.41 elad KASSERT(key != NULL); 552 1.41 elad 553 1.41 elad specificdata_key_delete(kauth_domain, key->ks_key); 554 1.41 elad kmem_free(key, sizeof(*key)); 555 1.41 elad 556 1.41 elad return (0); 557 1.41 elad } 558 1.41 elad 559 1.41 elad void * 560 1.41 elad kauth_cred_getdata(kauth_cred_t cred, kauth_key_t key) 561 1.41 elad { 562 1.41 elad KASSERT(cred != NULL); 563 1.74 mlelstv KASSERT(cred != NOCRED); 564 1.74 mlelstv KASSERT(cred != FSCRED); 565 1.41 elad KASSERT(key != NULL); 566 1.41 elad 567 1.41 elad return (specificdata_getspecific(kauth_domain, &cred->cr_sd, 568 1.41 elad key->ks_key)); 569 1.41 elad } 570 1.41 elad 571 1.41 elad void 572 1.41 elad kauth_cred_setdata(kauth_cred_t cred, kauth_key_t key, void *data) 573 1.41 elad { 574 1.41 elad KASSERT(cred != NULL); 575 1.74 mlelstv KASSERT(cred != NOCRED); 576 1.74 mlelstv KASSERT(cred != FSCRED); 577 1.41 elad KASSERT(key != NULL); 578 1.41 elad 579 1.41 elad specificdata_setspecific(kauth_domain, &cred->cr_sd, key->ks_key, data); 580 1.41 elad } 581 1.41 elad 582 1.2 elad /* 583 1.19 elad * Match uids in two credentials. 584 1.2 elad */ 585 1.19 elad int 586 1.2 elad kauth_cred_uidmatch(kauth_cred_t cred1, kauth_cred_t cred2) 587 1.2 elad { 588 1.2 elad KASSERT(cred1 != NULL); 589 1.74 mlelstv KASSERT(cred1 != NOCRED); 590 1.74 mlelstv KASSERT(cred1 != FSCRED); 591 1.2 elad KASSERT(cred2 != NULL); 592 1.74 mlelstv KASSERT(cred2 != NOCRED); 593 1.74 mlelstv KASSERT(cred2 != FSCRED); 594 1.2 elad 595 1.2 elad if (cred1->cr_uid == cred2->cr_uid || 596 1.2 elad cred1->cr_euid == cred2->cr_uid || 597 1.2 elad cred1->cr_uid == cred2->cr_euid || 598 1.2 elad cred1->cr_euid == cred2->cr_euid) 599 1.2 elad return (1); 600 1.2 elad 601 1.2 elad return (0); 602 1.2 elad } 603 1.2 elad 604 1.11 ad u_int 605 1.2 elad kauth_cred_getrefcnt(kauth_cred_t cred) 606 1.2 elad { 607 1.2 elad KASSERT(cred != NULL); 608 1.74 mlelstv KASSERT(cred != NOCRED); 609 1.74 mlelstv KASSERT(cred != FSCRED); 610 1.2 elad 611 1.2 elad return (cred->cr_refcnt); 612 1.2 elad } 613 1.2 elad 614 1.2 elad /* 615 1.2 elad * Convert userland credentials (struct uucred) to kauth_cred_t. 616 1.29 pooka * XXX: For NFS & puffs 617 1.2 elad */ 618 1.29 pooka void 619 1.29 pooka kauth_uucred_to_cred(kauth_cred_t cred, const struct uucred *uuc) 620 1.29 pooka { 621 1.2 elad KASSERT(cred != NULL); 622 1.74 mlelstv KASSERT(cred != NOCRED); 623 1.74 mlelstv KASSERT(cred != FSCRED); 624 1.2 elad KASSERT(uuc != NULL); 625 1.29 pooka 626 1.2 elad cred->cr_refcnt = 1; 627 1.2 elad cred->cr_uid = uuc->cr_uid; 628 1.2 elad cred->cr_euid = uuc->cr_uid; 629 1.2 elad cred->cr_svuid = uuc->cr_uid; 630 1.2 elad cred->cr_gid = uuc->cr_gid; 631 1.2 elad cred->cr_egid = uuc->cr_gid; 632 1.2 elad cred->cr_svgid = uuc->cr_gid; 633 1.77 riastrad cred->cr_ngroups = uimin(uuc->cr_ngroups, NGROUPS); 634 1.2 elad kauth_cred_setgroups(cred, __UNCONST(uuc->cr_groups), 635 1.49 dsl cred->cr_ngroups, -1, UIO_SYSSPACE); 636 1.2 elad } 637 1.2 elad 638 1.2 elad /* 639 1.29 pooka * Convert kauth_cred_t to userland credentials (struct uucred). 640 1.29 pooka * XXX: For NFS & puffs 641 1.29 pooka */ 642 1.29 pooka void 643 1.29 pooka kauth_cred_to_uucred(struct uucred *uuc, const kauth_cred_t cred) 644 1.29 pooka { 645 1.29 pooka KASSERT(cred != NULL); 646 1.74 mlelstv KASSERT(cred != NOCRED); 647 1.74 mlelstv KASSERT(cred != FSCRED); 648 1.29 pooka KASSERT(uuc != NULL); 649 1.29 pooka int ng; 650 1.29 pooka 651 1.77 riastrad ng = uimin(cred->cr_ngroups, NGROUPS); 652 1.29 pooka uuc->cr_uid = cred->cr_euid; 653 1.29 pooka uuc->cr_gid = cred->cr_egid; 654 1.29 pooka uuc->cr_ngroups = ng; 655 1.49 dsl kauth_cred_getgroups(cred, uuc->cr_groups, ng, UIO_SYSSPACE); 656 1.29 pooka } 657 1.29 pooka 658 1.29 pooka /* 659 1.2 elad * Compare kauth_cred_t and uucred credentials. 660 1.2 elad * XXX: Modelled after crcmp() for NFS. 661 1.2 elad */ 662 1.2 elad int 663 1.2 elad kauth_cred_uucmp(kauth_cred_t cred, const struct uucred *uuc) 664 1.2 elad { 665 1.2 elad KASSERT(cred != NULL); 666 1.74 mlelstv KASSERT(cred != NOCRED); 667 1.74 mlelstv KASSERT(cred != FSCRED); 668 1.2 elad KASSERT(uuc != NULL); 669 1.2 elad 670 1.2 elad if (cred->cr_euid == uuc->cr_uid && 671 1.2 elad cred->cr_egid == uuc->cr_gid && 672 1.62 lukem cred->cr_ngroups == (uint32_t)uuc->cr_ngroups) { 673 1.2 elad int i; 674 1.2 elad 675 1.2 elad /* Check if all groups from uuc appear in cred. */ 676 1.2 elad for (i = 0; i < uuc->cr_ngroups; i++) { 677 1.2 elad int ismember; 678 1.2 elad 679 1.2 elad ismember = 0; 680 1.2 elad if (kauth_cred_ismember_gid(cred, uuc->cr_groups[i], 681 1.2 elad &ismember) != 0 || !ismember) 682 1.4 yamt return (1); 683 1.2 elad } 684 1.2 elad 685 1.4 yamt return (0); 686 1.2 elad } 687 1.2 elad 688 1.4 yamt return (1); 689 1.2 elad } 690 1.2 elad 691 1.2 elad /* 692 1.12 ad * Make a struct ucred out of a kauth_cred_t. For compatibility. 693 1.2 elad */ 694 1.2 elad void 695 1.45 dsl kauth_cred_toucred(kauth_cred_t cred, struct ki_ucred *uc) 696 1.2 elad { 697 1.2 elad KASSERT(cred != NULL); 698 1.74 mlelstv KASSERT(cred != NOCRED); 699 1.74 mlelstv KASSERT(cred != FSCRED); 700 1.2 elad KASSERT(uc != NULL); 701 1.2 elad 702 1.12 ad uc->cr_ref = cred->cr_refcnt; 703 1.2 elad uc->cr_uid = cred->cr_euid; 704 1.2 elad uc->cr_gid = cred->cr_egid; 705 1.77 riastrad uc->cr_ngroups = uimin(cred->cr_ngroups, __arraycount(uc->cr_groups)); 706 1.2 elad memcpy(uc->cr_groups, cred->cr_groups, 707 1.2 elad uc->cr_ngroups * sizeof(uc->cr_groups[0])); 708 1.2 elad } 709 1.2 elad 710 1.2 elad /* 711 1.12 ad * Make a struct pcred out of a kauth_cred_t. For compatibility. 712 1.2 elad */ 713 1.2 elad void 714 1.45 dsl kauth_cred_topcred(kauth_cred_t cred, struct ki_pcred *pc) 715 1.2 elad { 716 1.2 elad KASSERT(cred != NULL); 717 1.74 mlelstv KASSERT(cred != NOCRED); 718 1.74 mlelstv KASSERT(cred != FSCRED); 719 1.2 elad KASSERT(pc != NULL); 720 1.2 elad 721 1.45 dsl pc->p_pad = NULL; 722 1.2 elad pc->p_ruid = cred->cr_uid; 723 1.2 elad pc->p_svuid = cred->cr_svuid; 724 1.2 elad pc->p_rgid = cred->cr_gid; 725 1.2 elad pc->p_svgid = cred->cr_svgid; 726 1.2 elad pc->p_refcnt = cred->cr_refcnt; 727 1.2 elad } 728 1.2 elad 729 1.2 elad /* 730 1.14 ad * Return kauth_cred_t for the current LWP. 731 1.2 elad */ 732 1.2 elad kauth_cred_t 733 1.2 elad kauth_cred_get(void) 734 1.2 elad { 735 1.14 ad return (curlwp->l_cred); 736 1.2 elad } 737 1.2 elad 738 1.2 elad /* 739 1.2 elad * Returns a scope matching the provided id. 740 1.2 elad * Requires the scope list lock to be held by the caller. 741 1.2 elad */ 742 1.2 elad static kauth_scope_t 743 1.3 yamt kauth_ifindscope(const char *id) 744 1.3 yamt { 745 1.2 elad kauth_scope_t scope; 746 1.2 elad 747 1.44 ad KASSERT(rw_lock_held(&kauth_lock)); 748 1.2 elad 749 1.2 elad scope = NULL; 750 1.2 elad SIMPLEQ_FOREACH(scope, &scope_list, next_scope) { 751 1.2 elad if (strcmp(scope->id, id) == 0) 752 1.2 elad break; 753 1.2 elad } 754 1.2 elad 755 1.2 elad return (scope); 756 1.2 elad } 757 1.2 elad 758 1.2 elad /* 759 1.2 elad * Register a new scope. 760 1.2 elad * 761 1.2 elad * id - identifier for the scope 762 1.2 elad * callback - the scope's default listener 763 1.2 elad * cookie - cookie to be passed to the listener(s) 764 1.2 elad */ 765 1.2 elad kauth_scope_t 766 1.2 elad kauth_register_scope(const char *id, kauth_scope_callback_t callback, 767 1.16 christos void *cookie) 768 1.2 elad { 769 1.2 elad kauth_scope_t scope; 770 1.21 yamt kauth_listener_t listener = NULL; /* XXX gcc */ 771 1.2 elad 772 1.2 elad /* Sanitize input */ 773 1.16 christos if (id == NULL) 774 1.2 elad return (NULL); 775 1.2 elad 776 1.2 elad /* Allocate space for a new scope and listener. */ 777 1.34 ad scope = kmem_alloc(sizeof(*scope), KM_SLEEP); 778 1.76 chs if (callback != NULL) 779 1.34 ad listener = kmem_alloc(sizeof(*listener), KM_SLEEP); 780 1.2 elad 781 1.34 ad /* 782 1.34 ad * Acquire scope list lock. 783 1.34 ad */ 784 1.44 ad rw_enter(&kauth_lock, RW_WRITER); 785 1.2 elad 786 1.2 elad /* Check we don't already have a scope with the same id */ 787 1.2 elad if (kauth_ifindscope(id) != NULL) { 788 1.44 ad rw_exit(&kauth_lock); 789 1.2 elad 790 1.34 ad kmem_free(scope, sizeof(*scope)); 791 1.34 ad if (callback != NULL) 792 1.34 ad kmem_free(listener, sizeof(*listener)); 793 1.2 elad 794 1.2 elad return (NULL); 795 1.2 elad } 796 1.2 elad 797 1.2 elad /* Initialize new scope with parameters */ 798 1.2 elad scope->id = id; 799 1.2 elad scope->cookie = cookie; 800 1.2 elad scope->nlisteners = 1; 801 1.2 elad 802 1.16 christos SIMPLEQ_INIT(&scope->listenq); 803 1.16 christos 804 1.2 elad /* Add default listener */ 805 1.16 christos if (callback != NULL) { 806 1.16 christos listener->func = callback; 807 1.16 christos listener->scope = scope; 808 1.16 christos listener->refcnt = 0; 809 1.16 christos SIMPLEQ_INSERT_HEAD(&scope->listenq, listener, listener_next); 810 1.16 christos } 811 1.2 elad 812 1.2 elad /* Insert scope to scopes list */ 813 1.16 christos SIMPLEQ_INSERT_TAIL(&scope_list, scope, next_scope); 814 1.2 elad 815 1.44 ad rw_exit(&kauth_lock); 816 1.2 elad 817 1.2 elad return (scope); 818 1.2 elad } 819 1.2 elad 820 1.2 elad /* 821 1.2 elad * Initialize the kernel authorization subsystem. 822 1.2 elad * 823 1.2 elad * Initialize the scopes list lock. 824 1.41 elad * Create specificdata domain. 825 1.41 elad * Register the credentials scope, used in kauth(9) internally. 826 1.41 elad * Register built-in scopes: generic, system, process, network, machdep, device. 827 1.2 elad */ 828 1.2 elad void 829 1.2 elad kauth_init(void) 830 1.2 elad { 831 1.44 ad rw_init(&kauth_lock); 832 1.2 elad 833 1.53 ad kauth_cred_cache = pool_cache_init(sizeof(struct kauth_cred), 834 1.58 ad coherency_unit, 0, 0, "kcredpl", NULL, IPL_NONE, 835 1.55 ad NULL, NULL, NULL); 836 1.53 ad 837 1.41 elad /* Create specificdata domain. */ 838 1.41 elad kauth_domain = specificdata_domain_create(); 839 1.41 elad 840 1.41 elad /* Register credentials scope. */ 841 1.41 elad kauth_builtin_scope_cred = 842 1.41 elad kauth_register_scope(KAUTH_SCOPE_CRED, NULL, NULL); 843 1.41 elad 844 1.2 elad /* Register generic scope. */ 845 1.2 elad kauth_builtin_scope_generic = kauth_register_scope(KAUTH_SCOPE_GENERIC, 846 1.19 elad NULL, NULL); 847 1.19 elad 848 1.19 elad /* Register system scope. */ 849 1.19 elad kauth_builtin_scope_system = kauth_register_scope(KAUTH_SCOPE_SYSTEM, 850 1.19 elad NULL, NULL); 851 1.2 elad 852 1.2 elad /* Register process scope. */ 853 1.2 elad kauth_builtin_scope_process = kauth_register_scope(KAUTH_SCOPE_PROCESS, 854 1.19 elad NULL, NULL); 855 1.19 elad 856 1.19 elad /* Register network scope. */ 857 1.19 elad kauth_builtin_scope_network = kauth_register_scope(KAUTH_SCOPE_NETWORK, 858 1.19 elad NULL, NULL); 859 1.19 elad 860 1.19 elad /* Register machdep scope. */ 861 1.19 elad kauth_builtin_scope_machdep = kauth_register_scope(KAUTH_SCOPE_MACHDEP, 862 1.19 elad NULL, NULL); 863 1.25 elad 864 1.25 elad /* Register device scope. */ 865 1.25 elad kauth_builtin_scope_device = kauth_register_scope(KAUTH_SCOPE_DEVICE, 866 1.25 elad NULL, NULL); 867 1.64 elad 868 1.64 elad /* Register vnode scope. */ 869 1.64 elad kauth_builtin_scope_vnode = kauth_register_scope(KAUTH_SCOPE_VNODE, 870 1.64 elad NULL, NULL); 871 1.2 elad } 872 1.2 elad 873 1.2 elad /* 874 1.2 elad * Deregister a scope. 875 1.2 elad * Requires scope list lock to be held by the caller. 876 1.2 elad * 877 1.2 elad * scope - the scope to deregister 878 1.2 elad */ 879 1.2 elad void 880 1.2 elad kauth_deregister_scope(kauth_scope_t scope) 881 1.2 elad { 882 1.2 elad if (scope != NULL) { 883 1.2 elad /* Remove scope from list */ 884 1.2 elad SIMPLEQ_REMOVE(&scope_list, scope, kauth_scope, next_scope); 885 1.36 elad kmem_free(scope, sizeof(*scope)); 886 1.2 elad } 887 1.2 elad } 888 1.2 elad 889 1.2 elad /* 890 1.2 elad * Register a listener. 891 1.2 elad * 892 1.2 elad * id - scope identifier. 893 1.2 elad * callback - the callback routine for the listener. 894 1.2 elad * cookie - cookie to pass unmoidfied to the callback. 895 1.2 elad */ 896 1.2 elad kauth_listener_t 897 1.2 elad kauth_listen_scope(const char *id, kauth_scope_callback_t callback, 898 1.30 yamt void *cookie) 899 1.2 elad { 900 1.2 elad kauth_scope_t scope; 901 1.2 elad kauth_listener_t listener; 902 1.2 elad 903 1.44 ad listener = kmem_alloc(sizeof(*listener), KM_SLEEP); 904 1.44 ad rw_enter(&kauth_lock, RW_WRITER); 905 1.44 ad 906 1.34 ad /* 907 1.34 ad * Find scope struct. 908 1.34 ad */ 909 1.2 elad scope = kauth_ifindscope(id); 910 1.44 ad if (scope == NULL) { 911 1.44 ad rw_exit(&kauth_lock); 912 1.44 ad kmem_free(listener, sizeof(*listener)); 913 1.2 elad return (NULL); 914 1.44 ad } 915 1.2 elad 916 1.2 elad /* Allocate listener */ 917 1.2 elad 918 1.2 elad /* Initialize listener with parameters */ 919 1.2 elad listener->func = callback; 920 1.2 elad listener->refcnt = 0; 921 1.2 elad 922 1.2 elad /* Add listener to scope */ 923 1.2 elad SIMPLEQ_INSERT_TAIL(&scope->listenq, listener, listener_next); 924 1.2 elad 925 1.2 elad /* Raise number of listeners on scope. */ 926 1.2 elad scope->nlisteners++; 927 1.2 elad listener->scope = scope; 928 1.2 elad 929 1.44 ad rw_exit(&kauth_lock); 930 1.44 ad 931 1.2 elad return (listener); 932 1.2 elad } 933 1.2 elad 934 1.2 elad /* 935 1.2 elad * Deregister a listener. 936 1.2 elad * 937 1.2 elad * listener - listener reference as returned from kauth_listen_scope(). 938 1.2 elad */ 939 1.2 elad void 940 1.2 elad kauth_unlisten_scope(kauth_listener_t listener) 941 1.2 elad { 942 1.44 ad 943 1.2 elad if (listener != NULL) { 944 1.44 ad rw_enter(&kauth_lock, RW_WRITER); 945 1.3 yamt SIMPLEQ_REMOVE(&listener->scope->listenq, listener, 946 1.3 yamt kauth_listener, listener_next); 947 1.2 elad listener->scope->nlisteners--; 948 1.44 ad rw_exit(&kauth_lock); 949 1.36 elad kmem_free(listener, sizeof(*listener)); 950 1.2 elad } 951 1.2 elad } 952 1.2 elad 953 1.2 elad /* 954 1.2 elad * Authorize a request. 955 1.2 elad * 956 1.2 elad * scope - the scope of the request as defined by KAUTH_SCOPE_* or as 957 1.2 elad * returned from kauth_register_scope(). 958 1.2 elad * credential - credentials of the user ("actor") making the request. 959 1.2 elad * action - request identifier. 960 1.2 elad * arg[0-3] - passed unmodified to listener(s). 961 1.64 elad * 962 1.64 elad * Returns the aggregated result: 963 1.64 elad * - KAUTH_RESULT_ALLOW if there is at least one KAUTH_RESULT_ALLOW and 964 1.64 elad * zero KAUTH_DESULT_DENY 965 1.64 elad * - KAUTH_RESULT_DENY if there is at least one KAUTH_RESULT_DENY 966 1.64 elad * - KAUTH_RESULT_DEFER if there is nothing but KAUTH_RESULT_DEFER 967 1.2 elad */ 968 1.64 elad static int 969 1.64 elad kauth_authorize_action_internal(kauth_scope_t scope, kauth_cred_t cred, 970 1.64 elad kauth_action_t action, void *arg0, void *arg1, void *arg2, void *arg3) 971 1.2 elad { 972 1.2 elad kauth_listener_t listener; 973 1.2 elad int error, allow, fail; 974 1.2 elad 975 1.26 elad KASSERT(cred != NULL); 976 1.26 elad KASSERT(action != 0); 977 1.2 elad 978 1.17 christos /* Short-circuit requests coming from the kernel. */ 979 1.17 christos if (cred == NOCRED || cred == FSCRED) 980 1.72 christos return KAUTH_RESULT_ALLOW; 981 1.17 christos 982 1.26 elad KASSERT(scope != NULL); 983 1.26 elad 984 1.2 elad fail = 0; 985 1.2 elad allow = 0; 986 1.39 elad 987 1.44 ad /* rw_enter(&kauth_lock, RW_READER); XXX not yet */ 988 1.2 elad SIMPLEQ_FOREACH(listener, &scope->listenq, listener_next) { 989 1.2 elad error = listener->func(cred, action, scope->cookie, arg0, 990 1.44 ad arg1, arg2, arg3); 991 1.2 elad 992 1.2 elad if (error == KAUTH_RESULT_ALLOW) 993 1.2 elad allow = 1; 994 1.2 elad else if (error == KAUTH_RESULT_DENY) 995 1.2 elad fail = 1; 996 1.2 elad } 997 1.44 ad /* rw_exit(&kauth_lock); */ 998 1.2 elad 999 1.39 elad if (fail) 1000 1.64 elad return (KAUTH_RESULT_DENY); 1001 1.64 elad 1002 1.64 elad if (allow) 1003 1.64 elad return (KAUTH_RESULT_ALLOW); 1004 1.64 elad 1005 1.64 elad return (KAUTH_RESULT_DEFER); 1006 1.64 elad }; 1007 1.64 elad 1008 1.64 elad int 1009 1.64 elad kauth_authorize_action(kauth_scope_t scope, kauth_cred_t cred, 1010 1.64 elad kauth_action_t action, void *arg0, void *arg1, void *arg2, void *arg3) 1011 1.64 elad { 1012 1.64 elad int r; 1013 1.64 elad 1014 1.64 elad r = kauth_authorize_action_internal(scope, cred, action, arg0, arg1, 1015 1.64 elad arg2, arg3); 1016 1.64 elad 1017 1.64 elad if (r == KAUTH_RESULT_DENY) 1018 1.39 elad return (EPERM); 1019 1.39 elad 1020 1.64 elad if (r == KAUTH_RESULT_ALLOW) 1021 1.39 elad return (0); 1022 1.39 elad 1023 1.66 jym if (secmodel_nsecmodels() == 0) 1024 1.39 elad return (0); 1025 1.39 elad 1026 1.39 elad return (EPERM); 1027 1.64 elad } 1028 1.2 elad 1029 1.2 elad /* 1030 1.2 elad * Generic scope authorization wrapper. 1031 1.2 elad */ 1032 1.2 elad int 1033 1.2 elad kauth_authorize_generic(kauth_cred_t cred, kauth_action_t action, void *arg0) 1034 1.2 elad { 1035 1.2 elad return (kauth_authorize_action(kauth_builtin_scope_generic, cred, 1036 1.2 elad action, arg0, NULL, NULL, NULL)); 1037 1.2 elad } 1038 1.2 elad 1039 1.2 elad /* 1040 1.19 elad * System scope authorization wrapper. 1041 1.2 elad */ 1042 1.2 elad int 1043 1.19 elad kauth_authorize_system(kauth_cred_t cred, kauth_action_t action, 1044 1.19 elad enum kauth_system_req req, void *arg1, void *arg2, void *arg3) 1045 1.2 elad { 1046 1.19 elad return (kauth_authorize_action(kauth_builtin_scope_system, cred, 1047 1.19 elad action, (void *)req, arg1, arg2, arg3)); 1048 1.2 elad } 1049 1.2 elad 1050 1.2 elad /* 1051 1.2 elad * Process scope authorization wrapper. 1052 1.2 elad */ 1053 1.2 elad int 1054 1.2 elad kauth_authorize_process(kauth_cred_t cred, kauth_action_t action, 1055 1.2 elad struct proc *p, void *arg1, void *arg2, void *arg3) 1056 1.2 elad { 1057 1.2 elad return (kauth_authorize_action(kauth_builtin_scope_process, cred, 1058 1.2 elad action, p, arg1, arg2, arg3)); 1059 1.2 elad } 1060 1.19 elad 1061 1.19 elad /* 1062 1.19 elad * Network scope authorization wrapper. 1063 1.19 elad */ 1064 1.19 elad int 1065 1.19 elad kauth_authorize_network(kauth_cred_t cred, kauth_action_t action, 1066 1.23 elad enum kauth_network_req req, void *arg1, void *arg2, void *arg3) 1067 1.19 elad { 1068 1.19 elad return (kauth_authorize_action(kauth_builtin_scope_network, cred, 1069 1.23 elad action, (void *)req, arg1, arg2, arg3)); 1070 1.19 elad } 1071 1.19 elad 1072 1.19 elad int 1073 1.19 elad kauth_authorize_machdep(kauth_cred_t cred, kauth_action_t action, 1074 1.35 elad void *arg0, void *arg1, void *arg2, void *arg3) 1075 1.19 elad { 1076 1.19 elad return (kauth_authorize_action(kauth_builtin_scope_machdep, cred, 1077 1.35 elad action, arg0, arg1, arg2, arg3)); 1078 1.19 elad } 1079 1.25 elad 1080 1.25 elad int 1081 1.32 elad kauth_authorize_device(kauth_cred_t cred, kauth_action_t action, 1082 1.32 elad void *arg0, void *arg1, void *arg2, void *arg3) 1083 1.32 elad { 1084 1.32 elad return (kauth_authorize_action(kauth_builtin_scope_device, cred, 1085 1.32 elad action, arg0, arg1, arg2, arg3)); 1086 1.32 elad } 1087 1.32 elad 1088 1.32 elad int 1089 1.25 elad kauth_authorize_device_tty(kauth_cred_t cred, kauth_action_t action, 1090 1.25 elad struct tty *tty) 1091 1.25 elad { 1092 1.25 elad return (kauth_authorize_action(kauth_builtin_scope_device, cred, 1093 1.25 elad action, tty, NULL, NULL, NULL)); 1094 1.25 elad } 1095 1.31 elad 1096 1.31 elad int 1097 1.31 elad kauth_authorize_device_spec(kauth_cred_t cred, enum kauth_device_req req, 1098 1.31 elad struct vnode *vp) 1099 1.31 elad { 1100 1.31 elad return (kauth_authorize_action(kauth_builtin_scope_device, cred, 1101 1.31 elad KAUTH_DEVICE_RAWIO_SPEC, (void *)req, vp, NULL, NULL)); 1102 1.31 elad } 1103 1.31 elad 1104 1.31 elad int 1105 1.33 elad kauth_authorize_device_passthru(kauth_cred_t cred, dev_t dev, u_long bits, 1106 1.33 elad void *data) 1107 1.31 elad { 1108 1.31 elad return (kauth_authorize_action(kauth_builtin_scope_device, cred, 1109 1.33 elad KAUTH_DEVICE_RAWIO_PASSTHRU, (void *)bits, (void *)(u_long)dev, 1110 1.33 elad data, NULL)); 1111 1.31 elad } 1112 1.39 elad 1113 1.64 elad kauth_action_t 1114 1.78 christos kauth_accmode_to_action(accmode_t accmode) 1115 1.64 elad { 1116 1.64 elad kauth_action_t action = 0; 1117 1.64 elad 1118 1.78 christos // XXX: Revisit we need to have a richer set of kauth primitives 1119 1.78 christos // We also get only the Unix perms here sometimes 1120 1.78 christos if (accmode & (VSTAT_PERMS|VREAD)) 1121 1.64 elad action |= KAUTH_VNODE_READ_DATA; 1122 1.78 christos if (accmode & (VMODIFY_PERMS|VADMIN_PERMS)) 1123 1.64 elad action |= KAUTH_VNODE_WRITE_DATA; 1124 1.78 christos if (accmode & VEXEC) 1125 1.64 elad action |= KAUTH_VNODE_EXECUTE; 1126 1.78 christos return action == 0 ? KAUTH_VNODE_ACCESS : action; 1127 1.64 elad } 1128 1.64 elad 1129 1.68 elad kauth_action_t 1130 1.68 elad kauth_extattr_action(mode_t access_mode) 1131 1.68 elad { 1132 1.68 elad kauth_action_t action = 0; 1133 1.68 elad 1134 1.68 elad if (access_mode & VREAD) 1135 1.68 elad action |= KAUTH_VNODE_READ_EXTATTRIBUTES; 1136 1.68 elad if (access_mode & VWRITE) 1137 1.68 elad action |= KAUTH_VNODE_WRITE_EXTATTRIBUTES; 1138 1.68 elad 1139 1.68 elad return action; 1140 1.68 elad } 1141 1.68 elad 1142 1.64 elad int 1143 1.64 elad kauth_authorize_vnode(kauth_cred_t cred, kauth_action_t action, 1144 1.64 elad struct vnode *vp, struct vnode *dvp, int fs_decision) 1145 1.64 elad { 1146 1.64 elad int error; 1147 1.64 elad 1148 1.64 elad error = kauth_authorize_action_internal(kauth_builtin_scope_vnode, cred, 1149 1.64 elad action, vp, dvp, NULL, NULL); 1150 1.64 elad 1151 1.64 elad if (error == KAUTH_RESULT_DENY) 1152 1.64 elad return (EACCES); 1153 1.64 elad 1154 1.64 elad if (error == KAUTH_RESULT_ALLOW) 1155 1.64 elad return (0); 1156 1.64 elad 1157 1.64 elad /* 1158 1.64 elad * If the file-system does not support decision-before-action, we can 1159 1.64 elad * only short-circuit the operation (deny). If we're here, it means no 1160 1.64 elad * listener denied it, so our only alternative is to supposedly-allow 1161 1.64 elad * it and let the file-system have the last word. 1162 1.64 elad */ 1163 1.64 elad if (fs_decision == KAUTH_VNODE_REMOTEFS) 1164 1.64 elad return (0); 1165 1.64 elad 1166 1.64 elad return (fs_decision); 1167 1.64 elad } 1168 1.64 elad 1169 1.41 elad static int 1170 1.41 elad kauth_cred_hook(kauth_cred_t cred, kauth_action_t action, void *arg0, 1171 1.41 elad void *arg1) 1172 1.41 elad { 1173 1.41 elad int r; 1174 1.41 elad 1175 1.41 elad r = kauth_authorize_action(kauth_builtin_scope_cred, cred, action, 1176 1.41 elad arg0, arg1, NULL, NULL); 1177 1.41 elad 1178 1.42 elad #ifdef DIAGNOSTIC 1179 1.42 elad if (!SIMPLEQ_EMPTY(&kauth_builtin_scope_cred->listenq)) 1180 1.42 elad KASSERT(r == 0); 1181 1.42 elad #endif /* DIAGNOSTIC */ 1182 1.41 elad 1183 1.41 elad return (r); 1184 1.41 elad } 1185