1 /* $NetBSD: kern_auth.c,v 1.15 2006/07/26 17:13:26 elad Exp $ */ 2 3 /*- 4 * Copyright (c) 2005, 2006 Elad Efrat <elad@NetBSD.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Elad Efrat. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * Todo: 35 * - Garbage collection to pool_put() unused scopes/listeners. 36 */ 37 38 #include <sys/types.h> 39 #include <sys/param.h> 40 #include <sys/queue.h> 41 #include <sys/time.h> 42 #include <sys/proc.h> 43 #include <sys/ucred.h> 44 #include <sys/pool.h> 45 #include <sys/kauth.h> 46 #include <sys/acct.h> 47 #include <sys/sysctl.h> 48 49 /* 50 * Credentials. 51 */ 52 struct kauth_cred { 53 struct simplelock cr_lock; /* lock on cr_refcnt */ 54 u_int cr_refcnt; /* reference count */ 55 uid_t cr_uid; /* user id */ 56 uid_t cr_euid; /* effective user id */ 57 uid_t cr_svuid; /* saved effective user id */ 58 gid_t cr_gid; /* group id */ 59 gid_t cr_egid; /* effective group id */ 60 gid_t cr_svgid; /* saved effective group id */ 61 u_int cr_ngroups; /* number of groups */ 62 gid_t cr_groups[NGROUPS]; /* group memberships */ 63 }; 64 65 /* 66 * Listener. 67 */ 68 struct kauth_listener { 69 kauth_scope_callback_t func; /* callback */ 70 kauth_scope_t scope; /* scope backpointer */ 71 u_int refcnt; /* reference count */ 72 SIMPLEQ_ENTRY(kauth_listener) listener_next; /* listener list */ 73 }; 74 75 /* 76 * Scope. 77 */ 78 struct kauth_scope { 79 const char *id; /* scope name */ 80 void *cookie; /* user cookie */ 81 u_int nlisteners; /* # of listeners */ 82 SIMPLEQ_HEAD(, kauth_listener) listenq; /* listener list */ 83 SIMPLEQ_ENTRY(kauth_scope) next_scope; /* scope list */ 84 }; 85 86 static POOL_INIT(kauth_scope_pool, sizeof(struct kauth_scope), 0, 0, 0, 87 "kauth_scopepl", &pool_allocator_nointr); 88 static POOL_INIT(kauth_listener_pool, sizeof(struct kauth_listener), 0, 0, 0, 89 "kauth_listenerpl", &pool_allocator_nointr); 90 static POOL_INIT(kauth_cred_pool, sizeof(struct kauth_cred), 0, 0, 0, 91 "kauth_credpl", &pool_allocator_nointr); 92 93 /* List of scopes and its lock. */ 94 static SIMPLEQ_HEAD(, kauth_scope) scope_list; 95 static struct simplelock scopes_lock; 96 97 /* Built-in scopes: generic, process. */ 98 static kauth_scope_t kauth_builtin_scope_generic; 99 static kauth_scope_t kauth_builtin_scope_process; 100 101 /* Allocate new, empty kauth credentials. */ 102 kauth_cred_t 103 kauth_cred_alloc(void) 104 { 105 kauth_cred_t cred; 106 107 cred = pool_get(&kauth_cred_pool, PR_WAITOK); 108 memset(cred, 0, sizeof(*cred)); 109 simple_lock_init(&cred->cr_lock); 110 cred->cr_refcnt = 1; 111 112 return (cred); 113 } 114 115 /* Increment reference count to cred. */ 116 void 117 kauth_cred_hold(kauth_cred_t cred) 118 { 119 KASSERT(cred != NULL); 120 KASSERT(cred->cr_refcnt > 0); 121 122 simple_lock(&cred->cr_lock); 123 cred->cr_refcnt++; 124 simple_unlock(&cred->cr_lock); 125 } 126 127 /* Decrease reference count to cred. If reached zero, free it. */ 128 void 129 kauth_cred_free(kauth_cred_t cred) 130 { 131 u_int refcnt; 132 133 KASSERT(cred != NULL); 134 KASSERT(cred->cr_refcnt > 0); 135 136 simple_lock(&cred->cr_lock); 137 refcnt = --cred->cr_refcnt; 138 simple_unlock(&cred->cr_lock); 139 140 if (refcnt == 0) 141 pool_put(&kauth_cred_pool, cred); 142 } 143 144 void 145 kauth_cred_clone(kauth_cred_t from, kauth_cred_t to) 146 { 147 KASSERT(from != NULL); 148 KASSERT(to != NULL); 149 KASSERT(from->cr_refcnt > 0); 150 151 to->cr_uid = from->cr_uid; 152 to->cr_euid = from->cr_euid; 153 to->cr_svuid = from->cr_svuid; 154 to->cr_gid = from->cr_gid; 155 to->cr_egid = from->cr_egid; 156 to->cr_svgid = from->cr_svgid; 157 to->cr_ngroups = from->cr_ngroups; 158 memcpy(to->cr_groups, from->cr_groups, sizeof(to->cr_groups)); 159 } 160 161 /* 162 * Duplicate cred and return a new kauth_cred_t. 163 */ 164 kauth_cred_t 165 kauth_cred_dup(kauth_cred_t cred) 166 { 167 kauth_cred_t new_cred; 168 169 KASSERT(cred != NULL); 170 KASSERT(cred->cr_refcnt > 0); 171 172 new_cred = kauth_cred_alloc(); 173 174 kauth_cred_clone(cred, new_cred); 175 176 return (new_cred); 177 } 178 179 /* 180 * Similar to crcopy(), only on a kauth_cred_t. 181 * XXX: Is this even needed? [kauth_cred_copy] 182 */ 183 kauth_cred_t 184 kauth_cred_copy(kauth_cred_t cred) 185 { 186 kauth_cred_t new_cred; 187 188 KASSERT(cred != NULL); 189 KASSERT(cred->cr_refcnt > 0); 190 191 /* If the provided credentials already have one reference, use them. */ 192 if (cred->cr_refcnt == 1) 193 return (cred); 194 195 new_cred = kauth_cred_alloc(); 196 197 kauth_cred_clone(cred, new_cred); 198 199 kauth_cred_free(cred); 200 201 return (new_cred); 202 } 203 204 uid_t 205 kauth_cred_getuid(kauth_cred_t cred) 206 { 207 KASSERT(cred != NULL); 208 209 return (cred->cr_uid); 210 } 211 212 uid_t 213 kauth_cred_geteuid(kauth_cred_t cred) 214 { 215 KASSERT(cred != NULL); 216 217 return (cred->cr_euid); 218 } 219 220 uid_t 221 kauth_cred_getsvuid(kauth_cred_t cred) 222 { 223 KASSERT(cred != NULL); 224 225 return (cred->cr_svuid); 226 } 227 228 gid_t 229 kauth_cred_getgid(kauth_cred_t cred) 230 { 231 KASSERT(cred != NULL); 232 233 return (cred->cr_gid); 234 } 235 236 gid_t 237 kauth_cred_getegid(kauth_cred_t cred) 238 { 239 KASSERT(cred != NULL); 240 241 return (cred->cr_egid); 242 } 243 244 gid_t 245 kauth_cred_getsvgid(kauth_cred_t cred) 246 { 247 KASSERT(cred != NULL); 248 249 return (cred->cr_svgid); 250 } 251 252 void 253 kauth_cred_setuid(kauth_cred_t cred, uid_t uid) 254 { 255 KASSERT(cred != NULL); 256 KASSERT(cred->cr_refcnt == 1); 257 258 cred->cr_uid = uid; 259 } 260 261 void 262 kauth_cred_seteuid(kauth_cred_t cred, uid_t uid) 263 { 264 KASSERT(cred != NULL); 265 KASSERT(cred->cr_refcnt == 1); 266 267 cred->cr_euid = uid; 268 } 269 270 void 271 kauth_cred_setsvuid(kauth_cred_t cred, uid_t uid) 272 { 273 KASSERT(cred != NULL); 274 KASSERT(cred->cr_refcnt == 1); 275 276 cred->cr_svuid = uid; 277 } 278 279 void 280 kauth_cred_setgid(kauth_cred_t cred, gid_t gid) 281 { 282 KASSERT(cred != NULL); 283 KASSERT(cred->cr_refcnt == 1); 284 285 cred->cr_gid = gid; 286 } 287 288 void 289 kauth_cred_setegid(kauth_cred_t cred, gid_t gid) 290 { 291 KASSERT(cred != NULL); 292 KASSERT(cred->cr_refcnt == 1); 293 294 cred->cr_egid = gid; 295 } 296 297 void 298 kauth_cred_setsvgid(kauth_cred_t cred, gid_t gid) 299 { 300 KASSERT(cred != NULL); 301 KASSERT(cred->cr_refcnt == 1); 302 303 cred->cr_svgid = gid; 304 } 305 306 /* Checks if gid is a member of the groups in cred. */ 307 int 308 kauth_cred_ismember_gid(kauth_cred_t cred, gid_t gid, int *resultp) 309 { 310 int i; 311 312 KASSERT(cred != NULL); 313 KASSERT(resultp != NULL); 314 315 *resultp = 0; 316 317 for (i = 0; i < cred->cr_ngroups; i++) 318 if (cred->cr_groups[i] == gid) { 319 *resultp = 1; 320 break; 321 } 322 323 return (0); 324 } 325 326 u_int 327 kauth_cred_ngroups(kauth_cred_t cred) 328 { 329 KASSERT(cred != NULL); 330 331 return (cred->cr_ngroups); 332 } 333 334 /* 335 * Return the group at index idx from the groups in cred. 336 */ 337 gid_t 338 kauth_cred_group(kauth_cred_t cred, u_int idx) 339 { 340 KASSERT(cred != NULL); 341 KASSERT(idx < cred->cr_ngroups); 342 343 return (cred->cr_groups[idx]); 344 } 345 346 /* XXX elad: gmuid is unused for now. */ 347 int 348 kauth_cred_setgroups(kauth_cred_t cred, gid_t *grbuf, size_t len, uid_t gmuid) 349 { 350 KASSERT(cred != NULL); 351 KASSERT(cred->cr_refcnt == 1); 352 KASSERT(len <= sizeof(cred->cr_groups) / sizeof(cred->cr_groups[0])); 353 354 if (len) 355 memcpy(cred->cr_groups, grbuf, len * sizeof(cred->cr_groups[0])); 356 memset(cred->cr_groups + len, 0xff, 357 sizeof(cred->cr_groups) - (len * sizeof(cred->cr_groups[0]))); 358 359 cred->cr_ngroups = len; 360 361 return (0); 362 } 363 364 int 365 kauth_cred_getgroups(kauth_cred_t cred, gid_t *grbuf, size_t len) 366 { 367 KASSERT(cred != NULL); 368 KASSERT(len <= cred->cr_ngroups); 369 370 memset(grbuf, 0xff, sizeof(*grbuf) * len); 371 memcpy(grbuf, cred->cr_groups, sizeof(*grbuf) * len); 372 373 return (0); 374 } 375 376 /* 377 * Match uids in two credentials. Checks if cred1 can access stuff owned by 378 * cred2. 379 * XXX: root bypasses this! 380 */ 381 static int 382 kauth_cred_uidmatch(kauth_cred_t cred1, kauth_cred_t cred2) 383 { 384 KASSERT(cred1 != NULL); 385 KASSERT(cred2 != NULL); 386 387 /* Are we root? */ 388 if (cred1->cr_euid == 0) 389 return (1); 390 391 if (cred1->cr_uid == cred2->cr_uid || 392 cred1->cr_euid == cred2->cr_uid || 393 cred1->cr_uid == cred2->cr_euid || 394 cred1->cr_euid == cred2->cr_euid) 395 return (1); 396 397 return (0); 398 } 399 400 u_int 401 kauth_cred_getrefcnt(kauth_cred_t cred) 402 { 403 KASSERT(cred != NULL); 404 405 return (cred->cr_refcnt); 406 } 407 408 /* 409 * Convert userland credentials (struct uucred) to kauth_cred_t. 410 * XXX: For NFS code. 411 */ 412 void 413 kauth_cred_uucvt(kauth_cred_t cred, const struct uucred *uuc) 414 { 415 KASSERT(cred != NULL); 416 KASSERT(uuc != NULL); 417 418 cred->cr_refcnt = 1; 419 cred->cr_uid = uuc->cr_uid; 420 cred->cr_euid = uuc->cr_uid; 421 cred->cr_svuid = uuc->cr_uid; 422 cred->cr_gid = uuc->cr_gid; 423 cred->cr_egid = uuc->cr_gid; 424 cred->cr_svgid = uuc->cr_gid; 425 cred->cr_ngroups = min(uuc->cr_ngroups, NGROUPS); 426 kauth_cred_setgroups(cred, __UNCONST(uuc->cr_groups), 427 cred->cr_ngroups, -1); 428 } 429 430 /* 431 * Compare kauth_cred_t and uucred credentials. 432 * XXX: Modelled after crcmp() for NFS. 433 */ 434 int 435 kauth_cred_uucmp(kauth_cred_t cred, const struct uucred *uuc) 436 { 437 KASSERT(cred != NULL); 438 KASSERT(uuc != NULL); 439 440 if (cred->cr_euid == uuc->cr_uid && 441 cred->cr_egid == uuc->cr_gid && 442 cred->cr_ngroups == uuc->cr_ngroups) { 443 int i; 444 445 /* Check if all groups from uuc appear in cred. */ 446 for (i = 0; i < uuc->cr_ngroups; i++) { 447 int ismember; 448 449 ismember = 0; 450 if (kauth_cred_ismember_gid(cred, uuc->cr_groups[i], 451 &ismember) != 0 || !ismember) 452 return (1); 453 } 454 455 return (0); 456 } 457 458 return (1); 459 } 460 461 /* 462 * Make a struct ucred out of a kauth_cred_t. For compatibility. 463 */ 464 void 465 kauth_cred_toucred(kauth_cred_t cred, struct ucred *uc) 466 { 467 KASSERT(cred != NULL); 468 KASSERT(uc != NULL); 469 470 uc->cr_ref = cred->cr_refcnt; 471 uc->cr_uid = cred->cr_euid; 472 uc->cr_gid = cred->cr_egid; 473 uc->cr_ngroups = min(cred->cr_ngroups, 474 sizeof(uc->cr_groups) / sizeof(uc->cr_groups[0])); 475 memcpy(uc->cr_groups, cred->cr_groups, 476 uc->cr_ngroups * sizeof(uc->cr_groups[0])); 477 } 478 479 /* 480 * Make a struct pcred out of a kauth_cred_t. For compatibility. 481 */ 482 void 483 kauth_cred_topcred(kauth_cred_t cred, struct pcred *pc) 484 { 485 KASSERT(cred != NULL); 486 KASSERT(pc != NULL); 487 488 pc->pc_ucred = NULL; 489 pc->p_ruid = cred->cr_uid; 490 pc->p_svuid = cred->cr_svuid; 491 pc->p_rgid = cred->cr_gid; 492 pc->p_svgid = cred->cr_svgid; 493 pc->p_refcnt = cred->cr_refcnt; 494 } 495 496 /* 497 * Return kauth_cred_t for the current LWP. 498 */ 499 kauth_cred_t 500 kauth_cred_get(void) 501 { 502 return (curlwp->l_cred); 503 } 504 505 /* 506 * Returns a scope matching the provided id. 507 * Requires the scope list lock to be held by the caller. 508 */ 509 static kauth_scope_t 510 kauth_ifindscope(const char *id) 511 { 512 kauth_scope_t scope; 513 514 /* XXX: assert lock on scope list? */ 515 516 scope = NULL; 517 SIMPLEQ_FOREACH(scope, &scope_list, next_scope) { 518 if (strcmp(scope->id, id) == 0) 519 break; 520 } 521 522 return (scope); 523 } 524 525 /* 526 * Register a new scope. 527 * 528 * id - identifier for the scope 529 * callback - the scope's default listener 530 * cookie - cookie to be passed to the listener(s) 531 */ 532 kauth_scope_t 533 kauth_register_scope(const char *id, kauth_scope_callback_t callback, 534 void *cookie) 535 { 536 kauth_scope_t scope; 537 kauth_listener_t listener; 538 539 /* Sanitize input */ 540 if (id == NULL || callback == NULL) 541 return (NULL); 542 543 /* Allocate space for a new scope and listener. */ 544 scope = pool_get(&kauth_scope_pool, PR_WAITOK); 545 listener = pool_get(&kauth_listener_pool, PR_WAITOK); 546 547 /* Acquire scope list lock. */ 548 simple_lock(&scopes_lock); 549 550 /* Check we don't already have a scope with the same id */ 551 if (kauth_ifindscope(id) != NULL) { 552 simple_unlock(&scopes_lock); 553 554 pool_put(&kauth_scope_pool, scope); 555 pool_put(&kauth_listener_pool, listener); 556 557 return (NULL); 558 } 559 560 /* Initialize new scope with parameters */ 561 scope->id = id; 562 scope->cookie = cookie; 563 scope->nlisteners = 1; 564 565 /* Add default listener */ 566 listener->func = callback; 567 listener->scope = scope; 568 listener->refcnt = 0; 569 SIMPLEQ_INIT(&scope->listenq); 570 SIMPLEQ_INSERT_HEAD(&scope->listenq, listener, listener_next); 571 572 /* Insert scope to scopes list */ 573 if (SIMPLEQ_EMPTY(&scope_list)) 574 SIMPLEQ_INSERT_HEAD(&scope_list, scope, next_scope); 575 else 576 SIMPLEQ_INSERT_TAIL(&scope_list, scope, next_scope); 577 578 simple_unlock(&scopes_lock); 579 580 return (scope); 581 } 582 583 /* 584 * Initialize the kernel authorization subsystem. 585 * 586 * Initialize the scopes list lock. 587 * Register built-in scopes: generic, process. 588 */ 589 void 590 kauth_init(void) 591 { 592 simple_lock_init(&scopes_lock); 593 594 /* Register generic scope. */ 595 kauth_builtin_scope_generic = kauth_register_scope(KAUTH_SCOPE_GENERIC, 596 kauth_authorize_cb_generic, NULL); 597 598 /* Register process scope. */ 599 kauth_builtin_scope_process = kauth_register_scope(KAUTH_SCOPE_PROCESS, 600 kauth_authorize_cb_process, NULL); 601 } 602 603 /* 604 * Deregister a scope. 605 * Requires scope list lock to be held by the caller. 606 * 607 * scope - the scope to deregister 608 */ 609 void 610 kauth_deregister_scope(kauth_scope_t scope) 611 { 612 if (scope != NULL) { 613 /* Remove scope from list */ 614 SIMPLEQ_REMOVE(&scope_list, scope, kauth_scope, next_scope); 615 } 616 } 617 618 /* 619 * Register a listener. 620 * 621 * id - scope identifier. 622 * callback - the callback routine for the listener. 623 * cookie - cookie to pass unmoidfied to the callback. 624 */ 625 kauth_listener_t 626 kauth_listen_scope(const char *id, kauth_scope_callback_t callback, 627 void *cookie) 628 { 629 kauth_scope_t scope; 630 kauth_listener_t listener; 631 632 /* Find scope struct */ 633 simple_lock(&scopes_lock); 634 scope = kauth_ifindscope(id); 635 simple_unlock(&scopes_lock); 636 if (scope == NULL) 637 return (NULL); 638 639 /* Allocate listener */ 640 listener = pool_get(&kauth_listener_pool, PR_WAITOK); 641 642 /* Initialize listener with parameters */ 643 listener->func = callback; 644 listener->refcnt = 0; 645 646 /* Add listener to scope */ 647 SIMPLEQ_INSERT_TAIL(&scope->listenq, listener, listener_next); 648 649 /* Raise number of listeners on scope. */ 650 scope->nlisteners++; 651 listener->scope = scope; 652 653 return (listener); 654 } 655 656 /* 657 * Deregister a listener. 658 * 659 * listener - listener reference as returned from kauth_listen_scope(). 660 */ 661 void 662 kauth_unlisten_scope(kauth_listener_t listener) 663 { 664 if (listener != NULL) { 665 SIMPLEQ_REMOVE(&listener->scope->listenq, listener, 666 kauth_listener, listener_next); 667 listener->scope->nlisteners--; 668 } 669 } 670 671 /* 672 * Authorize a request. 673 * 674 * scope - the scope of the request as defined by KAUTH_SCOPE_* or as 675 * returned from kauth_register_scope(). 676 * credential - credentials of the user ("actor") making the request. 677 * action - request identifier. 678 * arg[0-3] - passed unmodified to listener(s). 679 */ 680 int 681 kauth_authorize_action(kauth_scope_t scope, kauth_cred_t cred, 682 kauth_action_t action, void *arg0, void *arg1, 683 void *arg2, void *arg3) 684 { 685 kauth_listener_t listener; 686 int error, allow, fail; 687 688 #if 0 /* defined(LOCKDEBUG) */ 689 spinlock_switchcheck(); 690 simple_lock_only_held(NULL, "kauth_authorize_action"); 691 #endif 692 693 /* Sanitize input */ 694 if (scope == NULL || cred == NULL) 695 return (EFAULT); 696 if (!action) 697 return (EINVAL); 698 699 /* 700 * Each scope is associated with at least one listener. We need to 701 * traverse that list of listeners, as long as they return either 702 * KAUTH_REQUEST_DEFER or KAUTH_REQUEST_ALLOW. 703 */ 704 fail = 0; 705 allow = 0; 706 SIMPLEQ_FOREACH(listener, &scope->listenq, listener_next) { 707 error = listener->func(cred, action, scope->cookie, arg0, 708 arg1, arg2, arg3); 709 710 if (error == KAUTH_RESULT_ALLOW) 711 allow = 1; 712 else if (error == KAUTH_RESULT_DENY) 713 fail = 1; 714 } 715 716 return ((allow && !fail) ? 0 : EPERM); 717 }; 718 719 /* 720 * Generic scope default callback. 721 */ 722 int 723 kauth_authorize_cb_generic(kauth_cred_t cred, kauth_action_t action, 724 void *cookie, void *arg0, void *arg1, void *arg2, 725 void *arg3) 726 { 727 int error; 728 729 error = KAUTH_RESULT_DEFER; 730 731 switch (action) { 732 case KAUTH_GENERIC_ISSUSER: 733 /* Check if credential belongs to superuser. */ 734 if (cred->cr_euid == 0) { 735 u_short *acflag = (u_short *)arg0; 736 737 if (acflag != NULL) 738 *acflag |= ASU; 739 740 error = KAUTH_RESULT_ALLOW; 741 } else 742 error = KAUTH_RESULT_DENY; 743 break; 744 745 case KAUTH_GENERIC_CANSEE: 746 if (!security_curtain) { 747 error = KAUTH_RESULT_ALLOW; 748 } else { 749 kauth_cred_t cred2 = arg0; 750 751 if (kauth_cred_uidmatch(cred, cred2)) 752 error = KAUTH_RESULT_ALLOW; 753 else 754 error = KAUTH_RESULT_DENY; 755 } 756 break; 757 } 758 759 return (error); 760 } 761 762 /* 763 * Generic scope authorization wrapper. 764 */ 765 int 766 kauth_authorize_generic(kauth_cred_t cred, kauth_action_t action, void *arg0) 767 { 768 return (kauth_authorize_action(kauth_builtin_scope_generic, cred, 769 action, arg0, NULL, NULL, NULL)); 770 } 771 772 /* 773 * Process scope default callback. 774 */ 775 int 776 kauth_authorize_cb_process(kauth_cred_t cred, kauth_action_t action, 777 void *cookie, void *arg0, void *arg1, void *arg2, 778 void *arg3) 779 { 780 struct proc *p; 781 int error; 782 783 error = KAUTH_RESULT_DEFER; 784 785 p = arg0; 786 787 switch (action) { 788 case KAUTH_PROCESS_CANSIGNAL: { 789 int signum; 790 791 signum = (int)(unsigned long)arg1; 792 793 if (kauth_cred_uidmatch(cred, p->p_cred) || 794 (signum == SIGCONT && (curproc->p_session == p->p_session))) 795 error = KAUTH_RESULT_ALLOW; 796 else 797 error = KAUTH_RESULT_DEFER; 798 break; 799 } 800 801 case KAUTH_PROCESS_CANPTRACE: 802 if (kauth_cred_uidmatch(cred, p->p_cred)) 803 error = KAUTH_RESULT_ALLOW; 804 else 805 error = KAUTH_RESULT_DENY; 806 break; 807 808 case KAUTH_PROCESS_CANSEE: 809 if (!security_curtain) { 810 error = KAUTH_RESULT_ALLOW; 811 } else { 812 if (kauth_cred_uidmatch(cred, p->p_cred)) 813 error = KAUTH_RESULT_ALLOW; 814 else 815 error = KAUTH_RESULT_DENY; 816 /* arg2 - type of information [XXX NOTIMPL] */ 817 } 818 break; 819 } 820 821 return (error); 822 } 823 824 /* 825 * Process scope authorization wrapper. 826 */ 827 int 828 kauth_authorize_process(kauth_cred_t cred, kauth_action_t action, 829 struct proc *p, void *arg1, void *arg2, void *arg3) 830 { 831 return (kauth_authorize_action(kauth_builtin_scope_process, cred, 832 action, p, arg1, arg2, arg3)); 833 } 834