1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 27 /* All Rights Reserved */ 28 29 /* 30 * University Copyright- Copyright (c) 1982, 1986, 1988 31 * The Regents of the University of California 32 * All Rights Reserved 33 * 34 * University Acknowledgment- Portions of this document are derived from 35 * software developed by the University of California, Berkeley, and its 36 * contributors. 37 */ 38 39 #pragma ident "%Z%%M% %I% %E% SMI" 40 41 #include <sys/types.h> 42 #include <sys/sysmacros.h> 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/cred_impl.h> 46 #include <sys/policy.h> 47 #include <sys/vnode.h> 48 #include <sys/errno.h> 49 #include <sys/kmem.h> 50 #include <sys/user.h> 51 #include <sys/proc.h> 52 #include <sys/syscall.h> 53 #include <sys/debug.h> 54 #include <sys/atomic.h> 55 #include <sys/ucred.h> 56 #include <sys/prsystm.h> 57 #include <sys/modctl.h> 58 #include <c2/audit.h> 59 #include <sys/zone.h> 60 #include <sys/tsol/label.h> 61 62 static struct kmem_cache *cred_cache; 63 static size_t crsize = 0; 64 static int audoff = 0; 65 uint32_t ucredsize; 66 cred_t *kcred; 67 static cred_t *dummycr; 68 69 int rstlink; /* link(2) restricted to files owned by user? */ 70 71 static int get_c2audit_load(void); 72 73 #define CR_AUINFO(c) (auditinfo_addr_t *)((audoff == 0) ? NULL : \ 74 ((char *)(c)) + audoff) 75 76 #define REMOTE_PEER_CRED(c) ((c)->cr_gid == -1) 77 78 /* 79 * Initialize credentials data structures. 80 */ 81 82 void 83 cred_init(void) 84 { 85 priv_init(); 86 87 crsize = sizeof (cred_t) + sizeof (gid_t) * (ngroups_max - 1); 88 /* 89 * Make sure it's word-aligned. 90 */ 91 crsize = (crsize + sizeof (int) - 1) & ~(sizeof (int) - 1); 92 93 if (get_c2audit_load() > 0) { 94 #ifdef _LP64 95 /* assure audit context is 64-bit aligned */ 96 audoff = (crsize + 97 sizeof (int64_t) - 1) & ~(sizeof (int64_t) - 1); 98 #else /* _LP64 */ 99 audoff = crsize; 100 #endif /* _LP64 */ 101 crsize = audoff + sizeof (auditinfo_addr_t); 102 crsize = (crsize + sizeof (int) - 1) & ~(sizeof (int) - 1); 103 } 104 105 cred_cache = kmem_cache_create("cred_cache", crsize, 0, 106 NULL, NULL, NULL, NULL, NULL, 0); 107 108 /* 109 * dummycr is used to copy initial state for creds. 110 */ 111 dummycr = cralloc(); 112 bzero(dummycr, crsize); 113 dummycr->cr_ref = 1; 114 dummycr->cr_uid = -1; 115 dummycr->cr_gid = -1; 116 dummycr->cr_ruid = -1; 117 dummycr->cr_rgid = -1; 118 dummycr->cr_suid = -1; 119 dummycr->cr_sgid = -1; 120 121 /* 122 * kcred is used by anything that needs all privileges; it's 123 * also the template used for crget as it has all the compatible 124 * sets filled in. 125 */ 126 kcred = cralloc(); 127 128 bzero(kcred, crsize); 129 kcred->cr_ref = 1; 130 131 /* kcred is never freed, so we don't need zone_cred_hold here */ 132 kcred->cr_zone = &zone0; 133 134 priv_fillset(&CR_LPRIV(kcred)); 135 CR_IPRIV(kcred) = *priv_basic; 136 137 /* Not a basic privilege, if chown is not restricted add it to I0 */ 138 if (!rstchown) 139 priv_addset(&CR_IPRIV(kcred), PRIV_FILE_CHOWN_SELF); 140 141 /* Basic privilege, if link is restricted remove it from I0 */ 142 if (rstlink) 143 priv_delset(&CR_IPRIV(kcred), PRIV_FILE_LINK_ANY); 144 145 CR_EPRIV(kcred) = CR_PPRIV(kcred) = CR_IPRIV(kcred); 146 147 CR_FLAGS(kcred) = NET_MAC_AWARE; 148 149 /* 150 * Set up credentials of p0. 151 */ 152 ttoproc(curthread)->p_cred = kcred; 153 curthread->t_cred = kcred; 154 155 ucredsize = UCRED_SIZE; 156 } 157 158 /* 159 * Allocate (nearly) uninitialized cred_t. 160 */ 161 cred_t * 162 cralloc(void) 163 { 164 cred_t *cr = kmem_cache_alloc(cred_cache, KM_SLEEP); 165 cr->cr_ref = 1; /* So we can crfree() */ 166 cr->cr_zone = NULL; 167 cr->cr_label = NULL; 168 return (cr); 169 } 170 171 /* 172 * Allocate a initialized cred structure and crhold() it. 173 * Initialized means: all ids 0, group count 0, L=Full, E=P=I=I0 174 */ 175 cred_t * 176 crget(void) 177 { 178 cred_t *cr = kmem_cache_alloc(cred_cache, KM_SLEEP); 179 180 bcopy(kcred, cr, crsize); 181 cr->cr_ref = 1; 182 zone_cred_hold(cr->cr_zone); 183 if (cr->cr_label) 184 label_hold(cr->cr_label); 185 return (cr); 186 } 187 188 /* 189 * Broadcast the cred to all the threads in the process. 190 * The current thread's credentials can be set right away, but other 191 * threads must wait until the start of the next system call or trap. 192 * This avoids changing the cred in the middle of a system call. 193 * 194 * The cred has already been held for the process and the thread (2 holds), 195 * and p->p_cred set. 196 * 197 * p->p_crlock shouldn't be held here, since p_lock must be acquired. 198 */ 199 void 200 crset(proc_t *p, cred_t *cr) 201 { 202 kthread_id_t t; 203 kthread_id_t first; 204 cred_t *oldcr; 205 206 ASSERT(p == curproc); /* assumes p_lwpcnt can't change */ 207 208 /* 209 * DTrace accesses t_cred in probe context. t_cred must always be 210 * either NULL, or point to a valid, allocated cred structure. 211 */ 212 t = curthread; 213 oldcr = t->t_cred; 214 t->t_cred = cr; /* the cred is held by caller for this thread */ 215 crfree(oldcr); /* free the old cred for the thread */ 216 217 /* 218 * Broadcast to other threads, if any. 219 */ 220 if (p->p_lwpcnt > 1) { 221 mutex_enter(&p->p_lock); /* to keep thread list safe */ 222 first = curthread; 223 for (t = first->t_forw; t != first; t = t->t_forw) 224 t->t_pre_sys = 1; /* so syscall will get new cred */ 225 mutex_exit(&p->p_lock); 226 } 227 } 228 229 /* 230 * Put a hold on a cred structure. 231 */ 232 void 233 crhold(cred_t *cr) 234 { 235 atomic_add_32(&cr->cr_ref, 1); 236 } 237 238 /* 239 * Release previous hold on a cred structure. Free it if refcnt == 0. 240 * If cred uses label different from zone label, free it. 241 */ 242 void 243 crfree(cred_t *cr) 244 { 245 if (atomic_add_32_nv(&cr->cr_ref, -1) == 0) { 246 ASSERT(cr != kcred); 247 if (cr->cr_label) 248 label_rele(cr->cr_label); 249 if (cr->cr_zone) 250 zone_cred_rele(cr->cr_zone); 251 kmem_cache_free(cred_cache, cr); 252 } 253 } 254 255 /* 256 * Copy a cred structure to a new one and free the old one. 257 * The new cred will have two references. One for the calling process, 258 * and one for the thread. 259 */ 260 cred_t * 261 crcopy(cred_t *cr) 262 { 263 cred_t *newcr; 264 265 newcr = cralloc(); 266 bcopy(cr, newcr, crsize); 267 if (newcr->cr_zone) 268 zone_cred_hold(newcr->cr_zone); 269 if (newcr->cr_label) 270 label_hold(cr->cr_label); 271 crfree(cr); 272 newcr->cr_ref = 2; /* caller gets two references */ 273 return (newcr); 274 } 275 276 /* 277 * Copy a cred structure to a new one and free the old one. 278 * The new cred will have two references. One for the calling process, 279 * and one for the thread. 280 * This variation on crcopy uses a pre-allocated structure for the 281 * "new" cred. 282 */ 283 void 284 crcopy_to(cred_t *oldcr, cred_t *newcr) 285 { 286 bcopy(oldcr, newcr, crsize); 287 if (newcr->cr_zone) 288 zone_cred_hold(newcr->cr_zone); 289 if (newcr->cr_label) 290 label_hold(newcr->cr_label); 291 crfree(oldcr); 292 newcr->cr_ref = 2; /* caller gets two references */ 293 } 294 295 /* 296 * Dup a cred struct to a new held one. 297 * The old cred is not freed. 298 */ 299 cred_t * 300 crdup(cred_t *cr) 301 { 302 cred_t *newcr; 303 304 newcr = cralloc(); 305 bcopy(cr, newcr, crsize); 306 if (newcr->cr_zone) 307 zone_cred_hold(newcr->cr_zone); 308 if (newcr->cr_label) 309 label_hold(newcr->cr_label); 310 newcr->cr_ref = 1; 311 return (newcr); 312 } 313 314 /* 315 * Dup a cred struct to a new held one. 316 * The old cred is not freed. 317 * This variation on crdup uses a pre-allocated structure for the 318 * "new" cred. 319 */ 320 void 321 crdup_to(cred_t *oldcr, cred_t *newcr) 322 { 323 bcopy(oldcr, newcr, crsize); 324 if (newcr->cr_zone) 325 zone_cred_hold(newcr->cr_zone); 326 if (newcr->cr_label) 327 label_hold(newcr->cr_label); 328 newcr->cr_ref = 1; 329 } 330 331 /* 332 * Return the (held) credentials for the current running process. 333 */ 334 cred_t * 335 crgetcred(void) 336 { 337 cred_t *cr; 338 proc_t *p; 339 340 p = ttoproc(curthread); 341 mutex_enter(&p->p_crlock); 342 crhold(cr = p->p_cred); 343 mutex_exit(&p->p_crlock); 344 return (cr); 345 } 346 347 /* 348 * Backward compatibility check for suser(). 349 * Accounting flag is now set in the policy functions; auditing is 350 * done through use of privilege in the audit trail. 351 */ 352 int 353 suser(cred_t *cr) 354 { 355 return (PRIV_POLICY(cr, PRIV_SYS_SUSER_COMPAT, B_FALSE, EPERM, NULL) 356 == 0); 357 } 358 359 /* 360 * Determine whether the supplied group id is a member of the group 361 * described by the supplied credentials. 362 */ 363 int 364 groupmember(gid_t gid, const cred_t *cr) 365 { 366 if (gid == cr->cr_gid) 367 return (1); 368 return (supgroupmember(gid, cr)); 369 } 370 371 /* 372 * As groupmember but only check against the supplemental groups. 373 */ 374 int 375 supgroupmember(gid_t gid, const cred_t *cr) 376 { 377 const gid_t *gp, *endgp; 378 379 endgp = &cr->cr_groups[cr->cr_ngroups]; 380 for (gp = cr->cr_groups; gp < endgp; gp++) 381 if (*gp == gid) 382 return (1); 383 return (0); 384 } 385 386 /* 387 * This function is called to check whether the credentials set 388 * "scrp" has permission to act on credentials set "tcrp". It enforces the 389 * permission requirements needed to send a signal to a process. 390 * The same requirements are imposed by other system calls, however. 391 * 392 * The rules are: 393 * (1) if the credentials are the same, the check succeeds 394 * (2) if the zone ids don't match, and scrp is not in the global zone or 395 * does not have the PRIV_PROC_ZONE privilege, the check fails 396 * (3) if the real or effective user id of scrp matches the real or saved 397 * user id of tcrp or scrp has the PRIV_PROC_OWNER privilege, the check 398 * succeeds 399 * (4) otherwise, the check fails 400 */ 401 int 402 hasprocperm(const cred_t *tcrp, const cred_t *scrp) 403 { 404 if (scrp == tcrp) 405 return (1); 406 if (scrp->cr_zone != tcrp->cr_zone && 407 (scrp->cr_zone != global_zone || 408 secpolicy_proc_zone(scrp) != 0)) 409 return (0); 410 if (scrp->cr_uid == tcrp->cr_ruid || 411 scrp->cr_ruid == tcrp->cr_ruid || 412 scrp->cr_uid == tcrp->cr_suid || 413 scrp->cr_ruid == tcrp->cr_suid || 414 !PRIV_POLICY(scrp, PRIV_PROC_OWNER, B_FALSE, EPERM, "hasprocperm")) 415 return (1); 416 return (0); 417 } 418 419 /* 420 * This interface replaces hasprocperm; it works like hasprocperm but 421 * additionally returns success if the proc_t's match 422 * It is the preferred interface for most uses. 423 * And it will acquire pcrlock itself, so it assert's that it shouldn't 424 * be held. 425 */ 426 int 427 prochasprocperm(proc_t *tp, proc_t *sp, const cred_t *scrp) 428 { 429 int rets; 430 cred_t *tcrp; 431 432 ASSERT(MUTEX_NOT_HELD(&tp->p_crlock)); 433 434 if (tp == sp) 435 return (1); 436 437 if (tp->p_sessp != sp->p_sessp && secpolicy_basic_proc(scrp) != 0) 438 return (0); 439 440 mutex_enter(&tp->p_crlock); 441 tcrp = tp->p_cred; 442 rets = hasprocperm(tcrp, scrp); 443 mutex_exit(&tp->p_crlock); 444 445 return (rets); 446 } 447 448 /* 449 * This routine is used to compare two credentials to determine if 450 * they refer to the same "user". If the pointers are equal, then 451 * they must refer to the same user. Otherwise, the contents of 452 * the credentials are compared to see whether they are equivalent. 453 * 454 * This routine returns 0 if the credentials refer to the same user, 455 * 1 if they do not. 456 */ 457 int 458 crcmp(const cred_t *cr1, const cred_t *cr2) 459 { 460 461 if (cr1 == cr2) 462 return (0); 463 464 if (cr1->cr_uid == cr2->cr_uid && 465 cr1->cr_gid == cr2->cr_gid && 466 cr1->cr_ruid == cr2->cr_ruid && 467 cr1->cr_rgid == cr2->cr_rgid && 468 cr1->cr_ngroups == cr2->cr_ngroups && 469 cr1->cr_zone == cr2->cr_zone && 470 bcmp(cr1->cr_groups, cr2->cr_groups, 471 cr1->cr_ngroups * sizeof (gid_t)) == 0) { 472 return (!priv_isequalset(&CR_OEPRIV(cr1), &CR_OEPRIV(cr2))); 473 } 474 return (1); 475 } 476 477 /* 478 * Read access functions to cred_t. 479 */ 480 uid_t 481 crgetuid(const cred_t *cr) 482 { 483 return (cr->cr_uid); 484 } 485 486 uid_t 487 crgetruid(const cred_t *cr) 488 { 489 return (cr->cr_ruid); 490 } 491 492 uid_t 493 crgetsuid(const cred_t *cr) 494 { 495 return (cr->cr_suid); 496 } 497 498 gid_t 499 crgetgid(const cred_t *cr) 500 { 501 return (cr->cr_gid); 502 } 503 504 gid_t 505 crgetrgid(const cred_t *cr) 506 { 507 return (cr->cr_rgid); 508 } 509 510 gid_t 511 crgetsgid(const cred_t *cr) 512 { 513 return (cr->cr_sgid); 514 } 515 516 const auditinfo_addr_t * 517 crgetauinfo(const cred_t *cr) 518 { 519 return ((const auditinfo_addr_t *)CR_AUINFO(cr)); 520 } 521 522 auditinfo_addr_t * 523 crgetauinfo_modifiable(cred_t *cr) 524 { 525 return (CR_AUINFO(cr)); 526 } 527 528 zoneid_t 529 crgetzoneid(const cred_t *cr) 530 { 531 return (cr->cr_zone == NULL ? 532 (cr->cr_uid == -1 ? (zoneid_t)-1 : GLOBAL_ZONEID) : 533 cr->cr_zone->zone_id); 534 } 535 536 projid_t 537 crgetprojid(const cred_t *cr) 538 { 539 return (cr->cr_projid); 540 } 541 542 zone_t * 543 crgetzone(const cred_t *cr) 544 { 545 return (cr->cr_zone); 546 } 547 548 struct ts_label_s * 549 crgetlabel(const cred_t *cr) 550 { 551 return (cr->cr_label ? 552 cr->cr_label : 553 (cr->cr_zone ? cr->cr_zone->zone_slabel : NULL)); 554 } 555 556 boolean_t 557 crisremote(const cred_t *cr) 558 { 559 return (REMOTE_PEER_CRED(cr)); 560 } 561 562 #define BADID(x) ((x) != -1 && (unsigned int)(x) > MAXUID) 563 564 int 565 crsetresuid(cred_t *cr, uid_t r, uid_t e, uid_t s) 566 { 567 ASSERT(cr->cr_ref <= 2); 568 569 if (BADID(r) || BADID(e) || BADID(s)) 570 return (-1); 571 572 if (r != -1) 573 cr->cr_ruid = r; 574 if (e != -1) 575 cr->cr_uid = e; 576 if (s != -1) 577 cr->cr_suid = s; 578 579 return (0); 580 } 581 582 int 583 crsetresgid(cred_t *cr, gid_t r, gid_t e, gid_t s) 584 { 585 ASSERT(cr->cr_ref <= 2); 586 587 if (BADID(r) || BADID(e) || BADID(s)) 588 return (-1); 589 590 if (r != -1) 591 cr->cr_rgid = r; 592 if (e != -1) 593 cr->cr_gid = e; 594 if (s != -1) 595 cr->cr_sgid = s; 596 597 return (0); 598 } 599 600 int 601 crsetugid(cred_t *cr, uid_t uid, gid_t gid) 602 { 603 ASSERT(cr->cr_ref <= 2); 604 605 if (uid < 0 || uid > MAXUID || gid < 0 || gid > MAXUID) 606 return (-1); 607 608 cr->cr_uid = cr->cr_ruid = cr->cr_suid = uid; 609 cr->cr_gid = cr->cr_rgid = cr->cr_sgid = gid; 610 611 return (0); 612 } 613 614 int 615 crsetgroups(cred_t *cr, int n, gid_t *grp) 616 { 617 ASSERT(cr->cr_ref <= 2); 618 619 if (n > ngroups_max || n < 0) 620 return (-1); 621 622 cr->cr_ngroups = n; 623 624 if (n > 0) 625 bcopy(grp, cr->cr_groups, n * sizeof (gid_t)); 626 627 return (0); 628 } 629 630 void 631 crsetprojid(cred_t *cr, projid_t projid) 632 { 633 ASSERT(projid >= 0 && projid <= MAXPROJID); 634 cr->cr_projid = projid; 635 } 636 637 /* 638 * This routine returns the pointer to the first element of the cr_groups 639 * array. It can move around in an implementation defined way. 640 */ 641 const gid_t * 642 crgetgroups(const cred_t *cr) 643 { 644 return (cr->cr_groups); 645 } 646 647 int 648 crgetngroups(const cred_t *cr) 649 { 650 return (cr->cr_ngroups); 651 } 652 653 void 654 cred2prcred(const cred_t *cr, prcred_t *pcrp) 655 { 656 pcrp->pr_euid = cr->cr_uid; 657 pcrp->pr_ruid = cr->cr_ruid; 658 pcrp->pr_suid = cr->cr_suid; 659 pcrp->pr_egid = cr->cr_gid; 660 pcrp->pr_rgid = cr->cr_rgid; 661 pcrp->pr_sgid = cr->cr_sgid; 662 pcrp->pr_ngroups = MIN(cr->cr_ngroups, (uint_t)ngroups_max); 663 pcrp->pr_groups[0] = 0; /* in case ngroups == 0 */ 664 665 if (pcrp->pr_ngroups != 0) 666 bcopy(cr->cr_groups, pcrp->pr_groups, 667 sizeof (gid_t) * cr->cr_ngroups); 668 } 669 670 static int 671 cred2ucaud(const cred_t *cr, auditinfo64_addr_t *ainfo, const cred_t *rcr) 672 { 673 auditinfo_addr_t *ai; 674 au_tid_addr_t tid; 675 676 if (secpolicy_audit_getattr(rcr) != 0) 677 return (-1); 678 679 ai = CR_AUINFO(cr); /* caller makes sure this is non-NULL */ 680 tid = ai->ai_termid; 681 682 ainfo->ai_auid = ai->ai_auid; 683 ainfo->ai_mask = ai->ai_mask; 684 ainfo->ai_asid = ai->ai_asid; 685 686 ainfo->ai_termid.at_type = tid.at_type; 687 bcopy(&tid.at_addr, &ainfo->ai_termid.at_addr, 4 * sizeof (uint_t)); 688 689 ainfo->ai_termid.at_port.at_major = (uint32_t)getmajor(tid.at_port); 690 ainfo->ai_termid.at_port.at_minor = (uint32_t)getminor(tid.at_port); 691 692 return (0); 693 } 694 695 void 696 cred2uclabel(const cred_t *cr, bslabel_t *labelp) 697 { 698 ts_label_t *tslp; 699 700 if ((tslp = crgetlabel(cr)) != NULL) 701 bcopy(&tslp->tsl_label, labelp, sizeof (bslabel_t)); 702 } 703 704 /* 705 * Convert a credential into a "ucred". Allow the caller to specify 706 * and aligned buffer, e.g., in an mblk, so we don't have to allocate 707 * memory and copy it twice. 708 * 709 * This function may call cred2ucaud(), which calls CRED(). Since this 710 * can be called from an interrupt thread, receiver's cred (rcr) is needed 711 * to determine whether audit info should be included. 712 */ 713 struct ucred_s * 714 cred2ucred(const cred_t *cr, pid_t pid, void *buf, const cred_t *rcr) 715 { 716 struct ucred_s *uc; 717 718 /* The structure isn't always completely filled in, so zero it */ 719 if (buf == NULL) { 720 uc = kmem_zalloc(ucredsize, KM_SLEEP); 721 } else { 722 bzero(buf, ucredsize); 723 uc = buf; 724 } 725 uc->uc_size = ucredsize; 726 uc->uc_credoff = UCRED_CRED_OFF; 727 uc->uc_privoff = UCRED_PRIV_OFF; 728 uc->uc_audoff = UCRED_AUD_OFF; 729 uc->uc_labeloff = UCRED_LABEL_OFF; 730 uc->uc_pid = pid; 731 uc->uc_projid = cr->cr_projid; 732 uc->uc_zoneid = crgetzoneid(cr); 733 734 /* 735 * Note that cred2uclabel() call should not be factored out 736 * to the bottom of the if-else. UCXXX() macros depend on 737 * uc_xxxoff values to work correctly. 738 */ 739 if (REMOTE_PEER_CRED(cr)) { 740 /* 741 * other than label, the rest of cred info about a 742 * remote peer isn't available. 743 */ 744 cred2uclabel(cr, UCLABEL(uc)); 745 uc->uc_credoff = 0; 746 uc->uc_privoff = 0; 747 uc->uc_audoff = 0; 748 } else { 749 cred2prcred(cr, UCCRED(uc)); 750 cred2prpriv(cr, UCPRIV(uc)); 751 if (audoff == 0 || cred2ucaud(cr, UCAUD(uc), rcr) != 0) 752 uc->uc_audoff = 0; 753 cred2uclabel(cr, UCLABEL(uc)); 754 } 755 756 return (uc); 757 } 758 759 /* 760 * Get the "ucred" of a process. 761 */ 762 struct ucred_s * 763 pgetucred(proc_t *p) 764 { 765 cred_t *cr; 766 struct ucred_s *uc; 767 768 mutex_enter(&p->p_crlock); 769 cr = p->p_cred; 770 crhold(cr); 771 mutex_exit(&p->p_crlock); 772 773 uc = cred2ucred(cr, p->p_pid, NULL, CRED()); 774 crfree(cr); 775 776 return (uc); 777 } 778 779 /* 780 * If the reply status is NFSERR_EACCES, it may be because we are 781 * root (no root net access). Check the real uid, if it isn't root 782 * make that the uid instead and retry the call. 783 * Private interface for NFS. 784 */ 785 cred_t * 786 crnetadjust(cred_t *cr) 787 { 788 if (cr->cr_uid == 0 && cr->cr_ruid != 0) { 789 cr = crdup(cr); 790 cr->cr_uid = cr->cr_ruid; 791 return (cr); 792 } 793 return (NULL); 794 } 795 796 /* 797 * The reference count is of interest when you want to check 798 * whether it is ok to modify the credential in place. 799 */ 800 uint_t 801 crgetref(const cred_t *cr) 802 { 803 return (cr->cr_ref); 804 } 805 806 static int 807 get_c2audit_load(void) 808 { 809 static int gotit = 0; 810 static int c2audit_load; 811 u_longlong_t audit_load_val; 812 813 if (gotit) 814 return (c2audit_load); 815 audit_load_val = 0; /* set default value once */ 816 (void) mod_sysvar("c2audit", "audit_load", &audit_load_val); 817 c2audit_load = (int)audit_load_val; 818 gotit++; 819 return (c2audit_load); 820 } 821 822 int 823 get_audit_ucrsize(void) 824 { 825 return (get_c2audit_load() ? sizeof (auditinfo64_addr_t) : 0); 826 } 827 828 /* 829 * Set zone pointer in credential to indicated value. First adds a 830 * hold for the new zone, then drops the hold on previous zone (if any). 831 * This is done in this order in case the old and new zones are the 832 * same. 833 */ 834 void 835 crsetzone(cred_t *cr, zone_t *zptr) 836 { 837 zone_t *oldzptr = cr->cr_zone; 838 839 ASSERT(cr != kcred); 840 ASSERT(cr->cr_ref <= 2); 841 cr->cr_zone = zptr; 842 zone_cred_hold(zptr); 843 if (oldzptr) 844 zone_cred_rele(oldzptr); 845 } 846 847 /* 848 * Create a new cred based on the supplied label 849 */ 850 cred_t * 851 newcred_from_bslabel(bslabel_t *blabel, uint32_t doi, int flags) 852 { 853 ts_label_t *lbl = labelalloc(blabel, doi, flags); 854 cred_t *cr = NULL; 855 856 if (lbl != NULL) { 857 if ((cr = kmem_cache_alloc(cred_cache, flags)) != NULL) { 858 bcopy(dummycr, cr, crsize); 859 cr->cr_label = lbl; 860 } else { 861 label_rele(lbl); 862 } 863 } 864 865 return (cr); 866 } 867 868 /* 869 * Derive a new cred from the existing cred, but with a different label. 870 * To be used when a cred is being shared, but the label needs to be changed 871 * by a caller without affecting other users 872 */ 873 cred_t * 874 copycred_from_bslabel(cred_t *cr, bslabel_t *blabel, uint32_t doi, int flags) 875 { 876 ts_label_t *lbl = labelalloc(blabel, doi, flags); 877 cred_t *newcr = NULL; 878 879 if (lbl != NULL) { 880 if ((newcr = kmem_cache_alloc(cred_cache, flags)) != NULL) { 881 bcopy(cr, newcr, crsize); 882 if (newcr->cr_zone) 883 zone_cred_hold(newcr->cr_zone); 884 newcr->cr_label = lbl; 885 newcr->cr_ref = 1; 886 } else { 887 label_rele(lbl); 888 } 889 } 890 891 return (newcr); 892 } 893 894 /* 895 * This function returns a pointer to the kcred-equivalent in the current zone. 896 */ 897 cred_t * 898 zone_kcred(void) 899 { 900 zone_t *zone; 901 902 if ((zone = CRED()->cr_zone) != NULL) 903 return (zone->zone_kcred); 904 else 905 return (kcred); 906 } 907