1 /* $NetBSD: kern_auth.c,v 1.8 2006/06/13 22:56:46 dyoung 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 */ 54 uint32_t 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 uint16_t 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 uint32_t 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 uint32_t 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 121 simple_lock(&cred->cr_lock); 122 cred->cr_refcnt++; 123 simple_unlock(&cred->cr_lock); 124 } 125 126 /* Decrease reference count to cred. If reached zero, free it. */ 127 void 128 kauth_cred_free(kauth_cred_t cred) 129 { 130 KASSERT(cred != NULL); 131 132 simple_lock(&cred->cr_lock); 133 cred->cr_refcnt--; 134 simple_unlock(&cred->cr_lock); 135 136 if (cred->cr_refcnt == 0) 137 pool_put(&kauth_cred_pool, cred); 138 } 139 140 void 141 kauth_cred_clone(kauth_cred_t from, kauth_cred_t to) 142 { 143 KASSERT(from != NULL); 144 KASSERT(to != NULL); 145 146 to->cr_uid = from->cr_uid; 147 to->cr_euid = from->cr_euid; 148 to->cr_svuid = from->cr_svuid; 149 to->cr_gid = from->cr_gid; 150 to->cr_egid = from->cr_egid; 151 to->cr_svgid = from->cr_svgid; 152 to->cr_ngroups = from->cr_ngroups; 153 memcpy(to->cr_groups, from->cr_groups, 154 sizeof(to->cr_groups)); 155 } 156 157 /* 158 * Duplicate cred and return a new kauth_cred_t. 159 */ 160 kauth_cred_t 161 kauth_cred_dup(kauth_cred_t cred) 162 { 163 kauth_cred_t new_cred; 164 165 KASSERT(cred != NULL); 166 167 new_cred = kauth_cred_alloc(); 168 169 kauth_cred_clone(cred, new_cred); 170 171 return (new_cred); 172 } 173 174 /* 175 * Similar to crcopy(), only on a kauth_cred_t. 176 * XXX: Is this even needed? [kauth_cred_copy] 177 */ 178 kauth_cred_t 179 kauth_cred_copy(kauth_cred_t cred) 180 { 181 kauth_cred_t new_cred; 182 183 KASSERT(cred != NULL); 184 185 /* If the provided credentials already have one reference, use them. */ 186 if (cred->cr_refcnt == 1) 187 return (cred); 188 189 new_cred = kauth_cred_alloc(); 190 191 kauth_cred_clone(cred, new_cred); 192 193 kauth_cred_free(cred); 194 195 return (new_cred); 196 } 197 198 uid_t 199 kauth_cred_getuid(kauth_cred_t cred) 200 { 201 KASSERT(cred != NULL); 202 203 return (cred->cr_uid); 204 } 205 206 uid_t 207 kauth_cred_geteuid(kauth_cred_t cred) 208 { 209 KASSERT(cred != NULL); 210 211 return (cred->cr_euid); 212 } 213 214 uid_t 215 kauth_cred_getsvuid(kauth_cred_t cred) 216 { 217 KASSERT(cred != NULL); 218 219 return (cred->cr_svuid); 220 } 221 222 gid_t 223 kauth_cred_getgid(kauth_cred_t cred) 224 { 225 KASSERT(cred != NULL); 226 227 return (cred->cr_gid); 228 } 229 230 gid_t 231 kauth_cred_getegid(kauth_cred_t cred) 232 { 233 KASSERT(cred != NULL); 234 235 return (cred->cr_egid); 236 } 237 238 gid_t 239 kauth_cred_getsvgid(kauth_cred_t cred) 240 { 241 KASSERT(cred != NULL); 242 243 return (cred->cr_svgid); 244 } 245 246 void 247 kauth_cred_setuid(kauth_cred_t cred, uid_t uid) 248 { 249 KASSERT(cred != NULL); 250 251 cred->cr_uid = uid; 252 } 253 254 void 255 kauth_cred_seteuid(kauth_cred_t cred, uid_t uid) 256 { 257 KASSERT(cred != NULL); 258 259 cred->cr_euid = uid; 260 } 261 262 void 263 kauth_cred_setsvuid(kauth_cred_t cred, uid_t uid) 264 { 265 KASSERT(cred != NULL); 266 267 cred->cr_svuid = uid; 268 } 269 270 void 271 kauth_cred_setgid(kauth_cred_t cred, gid_t gid) 272 { 273 KASSERT(cred != NULL); 274 275 cred->cr_gid = gid; 276 } 277 278 void 279 kauth_cred_setegid(kauth_cred_t cred, gid_t gid) 280 { 281 KASSERT(cred != NULL); 282 283 cred->cr_egid = gid; 284 } 285 286 void 287 kauth_cred_setsvgid(kauth_cred_t cred, gid_t gid) 288 { 289 KASSERT(cred != NULL); 290 291 cred->cr_svgid = gid; 292 } 293 294 /* Checks if gid is a member of the groups in cred. */ 295 int 296 kauth_cred_ismember_gid(kauth_cred_t cred, gid_t gid, int *resultp) 297 { 298 int i; 299 300 KASSERT(cred != NULL); 301 KASSERT(resultp != NULL); 302 303 *resultp = 0; 304 305 for (i = 0; i < cred->cr_ngroups; i++) 306 if (cred->cr_groups[i] == gid) { 307 *resultp = 1; 308 break; 309 } 310 311 return (0); 312 } 313 314 uint16_t 315 kauth_cred_ngroups(kauth_cred_t cred) 316 { 317 KASSERT(cred != NULL); 318 319 return (cred->cr_ngroups); 320 } 321 322 /* 323 * Return the group at index idx from the groups in cred. 324 */ 325 gid_t 326 kauth_cred_group(kauth_cred_t cred, uint16_t idx) 327 { 328 KASSERT(cred != NULL); 329 KASSERT(idx < cred->cr_ngroups); 330 331 return (cred->cr_groups[idx]); 332 } 333 334 /* XXX elad: gmuid is unused for now. */ 335 int 336 kauth_cred_setgroups(kauth_cred_t cred, gid_t *grbuf, size_t len, uid_t gmuid) 337 { 338 KASSERT(cred != NULL); 339 KASSERT(len < sizeof(cred->cr_groups) / sizeof(cred->cr_groups[0])); 340 341 simple_lock(&cred->cr_lock); 342 343 if (len) 344 memcpy(cred->cr_groups, grbuf, len * sizeof(cred->cr_groups[0])); 345 memset(cred->cr_groups + len, 0xff, 346 sizeof(cred->cr_groups) - (len * sizeof(cred->cr_groups[0]))); 347 348 cred->cr_ngroups = len; 349 350 simple_unlock(&cred->cr_lock); 351 352 return (0); 353 } 354 355 int 356 kauth_cred_getgroups(kauth_cred_t cred, gid_t *grbuf, size_t len) 357 { 358 KASSERT(cred != NULL); 359 KASSERT(len <= cred->cr_ngroups); 360 361 memset(grbuf, 0xff, sizeof(*grbuf) * len); 362 simple_lock(&cred->cr_lock); 363 memcpy(grbuf, cred->cr_groups, sizeof(*grbuf) * len); 364 simple_unlock(&cred->cr_lock); 365 366 return (0); 367 } 368 369 /* 370 * Match uids in two credentials. Checks if cred1 can access stuff owned by 371 * cred2. 372 * XXX: root bypasses this! 373 */ 374 static int 375 kauth_cred_uidmatch(kauth_cred_t cred1, kauth_cred_t cred2) 376 { 377 KASSERT(cred1 != NULL); 378 KASSERT(cred2 != NULL); 379 380 /* Are we root? */ 381 if (cred1->cr_euid == 0) 382 return (1); 383 384 if (cred1->cr_uid == cred2->cr_uid || 385 cred1->cr_euid == cred2->cr_uid || 386 cred1->cr_uid == cred2->cr_euid || 387 cred1->cr_euid == cred2->cr_euid) 388 return (1); 389 390 return (0); 391 } 392 393 uint32_t 394 kauth_cred_getrefcnt(kauth_cred_t cred) 395 { 396 KASSERT(cred != NULL); 397 398 return (cred->cr_refcnt); 399 } 400 401 /* 402 * Convert userland credentials (struct uucred) to kauth_cred_t. 403 * XXX: For NFS code. 404 */ 405 void 406 kauth_cred_uucvt(kauth_cred_t cred, const struct uucred *uuc) 407 { 408 KASSERT(cred != NULL); 409 KASSERT(uuc != NULL); 410 411 cred->cr_refcnt = 1; 412 cred->cr_uid = uuc->cr_uid; 413 cred->cr_euid = uuc->cr_uid; 414 cred->cr_svuid = uuc->cr_uid; 415 cred->cr_gid = uuc->cr_gid; 416 cred->cr_egid = uuc->cr_gid; 417 cred->cr_svgid = uuc->cr_gid; 418 cred->cr_ngroups = min(uuc->cr_ngroups, NGROUPS); 419 kauth_cred_setgroups(cred, __UNCONST(uuc->cr_groups), 420 cred->cr_ngroups, -1); 421 } 422 423 /* 424 * Compare kauth_cred_t and uucred credentials. 425 * XXX: Modelled after crcmp() for NFS. 426 */ 427 int 428 kauth_cred_uucmp(kauth_cred_t cred, const struct uucred *uuc) 429 { 430 KASSERT(cred != NULL); 431 KASSERT(uuc != NULL); 432 433 if (cred->cr_euid == uuc->cr_uid && 434 cred->cr_egid == uuc->cr_gid && 435 cred->cr_ngroups == uuc->cr_ngroups) { 436 int i; 437 438 /* Check if all groups from uuc appear in cred. */ 439 for (i = 0; i < uuc->cr_ngroups; i++) { 440 int ismember; 441 442 ismember = 0; 443 if (kauth_cred_ismember_gid(cred, uuc->cr_groups[i], 444 &ismember) != 0 || !ismember) 445 return (1); 446 } 447 448 return (0); 449 } 450 451 return (1); 452 } 453 454 /* 455 * Make a struct ucred out of a kauth_cred_t. 456 * XXX: For sysctl. 457 */ 458 void 459 kauth_cred_toucred(kauth_cred_t cred, struct ucred *uc) 460 { 461 KASSERT(cred != NULL); 462 KASSERT(uc != NULL); 463 464 uc->cr_uid = cred->cr_euid; 465 uc->cr_gid = cred->cr_egid; 466 uc->cr_ngroups = min(cred->cr_ngroups, 467 sizeof(uc->cr_groups) / sizeof(uc->cr_groups[0])); 468 memcpy(uc->cr_groups, cred->cr_groups, 469 uc->cr_ngroups * sizeof(uc->cr_groups[0])); 470 } 471 472 /* 473 * Make a struct pcred out of a kauth_cred_t. 474 * XXX: For sysctl. 475 */ 476 void 477 kauth_cred_topcred(kauth_cred_t cred, struct pcred *pc) 478 { 479 KASSERT(cred != NULL); 480 KASSERT(pc != NULL); 481 482 pc->pc_ucred = (struct ucred *)cred; /* XXX this is just wrong */ 483 pc->p_ruid = cred->cr_uid; 484 pc->p_svuid = cred->cr_svuid; 485 pc->p_rgid = cred->cr_gid; 486 pc->p_svgid = cred->cr_svgid; 487 pc->p_refcnt = cred->cr_refcnt; 488 } 489 490 /* 491 * Return kauth_cred_t for the current process. 492 */ 493 kauth_cred_t 494 kauth_cred_get(void) 495 { 496 return (curproc->p_cred); 497 } 498 499 /* 500 * Returns a scope matching the provided id. 501 * Requires the scope list lock to be held by the caller. 502 */ 503 static kauth_scope_t 504 kauth_ifindscope(const char *id) 505 { 506 kauth_scope_t scope; 507 508 /* XXX: assert lock on scope list? */ 509 510 scope = NULL; 511 SIMPLEQ_FOREACH(scope, &scope_list, next_scope) { 512 if (strcmp(scope->id, id) == 0) 513 break; 514 } 515 516 return (scope); 517 } 518 519 /* 520 * Register a new scope. 521 * 522 * id - identifier for the scope 523 * callback - the scope's default listener 524 * cookie - cookie to be passed to the listener(s) 525 */ 526 kauth_scope_t 527 kauth_register_scope(const char *id, kauth_scope_callback_t callback, 528 void *cookie) 529 { 530 kauth_scope_t scope; 531 kauth_listener_t listener; 532 533 /* Sanitize input */ 534 if (id == NULL || callback == NULL) 535 return (NULL); 536 537 /* Allocate space for a new scope and listener. */ 538 scope = pool_get(&kauth_scope_pool, PR_WAITOK); 539 listener = pool_get(&kauth_listener_pool, PR_WAITOK); 540 541 /* Acquire scope list lock. */ 542 simple_lock(&scopes_lock); 543 544 /* Check we don't already have a scope with the same id */ 545 if (kauth_ifindscope(id) != NULL) { 546 simple_unlock(&scopes_lock); 547 548 pool_put(&kauth_scope_pool, scope); 549 pool_put(&kauth_listener_pool, listener); 550 551 return (NULL); 552 } 553 554 /* Initialize new scope with parameters */ 555 scope->id = id; 556 scope->cookie = cookie; 557 scope->nlisteners = 1; 558 559 /* Add default listener */ 560 listener->func = callback; 561 listener->scope = scope; 562 listener->refcnt = 0; 563 SIMPLEQ_INIT(&scope->listenq); 564 SIMPLEQ_INSERT_HEAD(&scope->listenq, listener, listener_next); 565 566 /* Insert scope to scopes list */ 567 if (SIMPLEQ_EMPTY(&scope_list)) 568 SIMPLEQ_INSERT_HEAD(&scope_list, scope, next_scope); 569 else 570 SIMPLEQ_INSERT_TAIL(&scope_list, scope, next_scope); 571 572 simple_unlock(&scopes_lock); 573 574 return (scope); 575 } 576 577 /* 578 * Initialize the kernel authorization subsystem. 579 * 580 * Initialize the scopes list lock. 581 * Register built-in scopes: generic, process. 582 */ 583 void 584 kauth_init(void) 585 { 586 simple_lock_init(&scopes_lock); 587 588 /* Register generic scope. */ 589 kauth_builtin_scope_generic = kauth_register_scope(KAUTH_SCOPE_GENERIC, 590 kauth_authorize_cb_generic, NULL); 591 592 /* Register process scope. */ 593 kauth_builtin_scope_process = kauth_register_scope(KAUTH_SCOPE_PROCESS, 594 kauth_authorize_cb_process, NULL); 595 } 596 597 /* 598 * Deregister a scope. 599 * Requires scope list lock to be held by the caller. 600 * 601 * scope - the scope to deregister 602 */ 603 void 604 kauth_deregister_scope(kauth_scope_t scope) 605 { 606 if (scope != NULL) { 607 /* Remove scope from list */ 608 SIMPLEQ_REMOVE(&scope_list, scope, kauth_scope, next_scope); 609 } 610 } 611 612 /* 613 * Register a listener. 614 * 615 * id - scope identifier. 616 * callback - the callback routine for the listener. 617 * cookie - cookie to pass unmoidfied to the callback. 618 */ 619 kauth_listener_t 620 kauth_listen_scope(const char *id, kauth_scope_callback_t callback, 621 void *cookie) 622 { 623 kauth_scope_t scope; 624 kauth_listener_t listener; 625 626 /* Find scope struct */ 627 simple_lock(&scopes_lock); 628 scope = kauth_ifindscope(id); 629 simple_unlock(&scopes_lock); 630 if (scope == NULL) 631 return (NULL); 632 633 /* Allocate listener */ 634 listener = pool_get(&kauth_listener_pool, PR_WAITOK); 635 636 /* Initialize listener with parameters */ 637 listener->func = callback; 638 listener->refcnt = 0; 639 640 /* Add listener to scope */ 641 SIMPLEQ_INSERT_TAIL(&scope->listenq, listener, listener_next); 642 643 /* Raise number of listeners on scope. */ 644 scope->nlisteners++; 645 listener->scope = scope; 646 647 return (listener); 648 } 649 650 /* 651 * Deregister a listener. 652 * 653 * listener - listener reference as returned from kauth_listen_scope(). 654 */ 655 void 656 kauth_unlisten_scope(kauth_listener_t listener) 657 { 658 if (listener != NULL) { 659 SIMPLEQ_REMOVE(&listener->scope->listenq, listener, 660 kauth_listener, listener_next); 661 listener->scope->nlisteners--; 662 } 663 } 664 665 /* 666 * Authorize a request. 667 * 668 * scope - the scope of the request as defined by KAUTH_SCOPE_* or as 669 * returned from kauth_register_scope(). 670 * credential - credentials of the user ("actor") making the request. 671 * action - request identifier. 672 * arg[0-3] - passed unmodified to listener(s). 673 */ 674 int 675 kauth_authorize_action(kauth_scope_t scope, kauth_cred_t cred, 676 kauth_action_t action, void *arg0, void *arg1, 677 void *arg2, void *arg3) 678 { 679 kauth_listener_t listener; 680 int error, allow, fail; 681 682 /* Sanitize input */ 683 if (scope == NULL || cred == NULL) 684 return (EFAULT); 685 if (!action) 686 return (EINVAL); 687 688 /* 689 * Each scope is associated with at least one listener. We need to 690 * traverse that list of listeners, as long as they return either 691 * KAUTH_REQUEST_DEFER or KAUTH_REQUEST_ALLOW. 692 */ 693 fail = 0; 694 allow = 0; 695 SIMPLEQ_FOREACH(listener, &scope->listenq, listener_next) { 696 error = listener->func(cred, action, scope->cookie, arg0, 697 arg1, arg2, arg3); 698 699 if (error == KAUTH_RESULT_ALLOW) 700 allow = 1; 701 else if (error == KAUTH_RESULT_DENY) 702 fail = 1; 703 } 704 705 return ((allow && !fail) ? 0 : EPERM); 706 }; 707 708 /* 709 * Generic scope default callback. 710 */ 711 int 712 kauth_authorize_cb_generic(kauth_cred_t cred, kauth_action_t action, 713 void *cookie, void *arg0, void *arg1, void *arg2, 714 void *arg3) 715 { 716 int error; 717 718 error = KAUTH_RESULT_DEFER; 719 720 switch (action) { 721 case KAUTH_GENERIC_ISSUSER: 722 /* Check if credential belongs to superuser. */ 723 if (cred->cr_euid == 0) { 724 u_short *acflag = (u_short *)arg0; 725 726 if (acflag != NULL) 727 *acflag |= ASU; 728 729 error = KAUTH_RESULT_ALLOW; 730 } else 731 error = KAUTH_RESULT_DENY; 732 break; 733 } 734 735 return (error); 736 } 737 738 /* 739 * Generic scope authorization wrapper. 740 */ 741 int 742 kauth_authorize_generic(kauth_cred_t cred, kauth_action_t action, void *arg0) 743 { 744 return (kauth_authorize_action(kauth_builtin_scope_generic, cred, 745 action, arg0, NULL, NULL, NULL)); 746 } 747 748 /* 749 * Process scope default callback. 750 */ 751 int 752 kauth_authorize_cb_process(kauth_cred_t cred, kauth_action_t action, 753 void *cookie, void *arg0, void *arg1, void *arg2, 754 void *arg3) 755 { 756 struct proc *p; 757 int error; 758 759 error = KAUTH_RESULT_DEFER; 760 761 p = arg0; 762 763 switch (action) { 764 case KAUTH_PROCESS_CANSIGNAL: { 765 int signum; 766 767 signum = (int)(unsigned long)arg1; 768 769 if (kauth_cred_uidmatch(cred, p->p_cred) || 770 (signum == SIGCONT && (curproc->p_session == p->p_session))) 771 error = KAUTH_RESULT_ALLOW; 772 else 773 error = KAUTH_RESULT_DEFER; 774 775 break; 776 } 777 778 case KAUTH_PROCESS_CANPTRACE: 779 if (kauth_cred_uidmatch(cred, p->p_cred)) 780 error = KAUTH_RESULT_ALLOW; 781 else 782 error = KAUTH_RESULT_DENY; 783 break; 784 785 case KAUTH_PROCESS_CANSEE: 786 if (!security_curtain) { 787 error = KAUTH_RESULT_ALLOW; 788 } else { 789 if (kauth_cred_uidmatch(cred, p->p_cred)) 790 error = KAUTH_RESULT_ALLOW; 791 else 792 error = KAUTH_RESULT_DENY; 793 /* arg2 - type of information [XXX NOTIMPL] */ 794 } 795 break; 796 } 797 798 return (error); 799 } 800 801 /* 802 * Process scope authorization wrapper. 803 */ 804 int 805 kauth_authorize_process(kauth_cred_t cred, kauth_action_t action, 806 struct proc *p, void *arg1, void *arg2, void *arg3) 807 { 808 return (kauth_authorize_action(kauth_builtin_scope_process, cred, 809 action, p, arg1, arg2, arg3)); 810 } 811