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 2007 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 <sys/avl.h> 59 #include <c2/audit.h> 60 #include <sys/zone.h> 61 #include <sys/tsol/label.h> 62 #include <sys/sid.h> 63 #include <sys/idmap.h> 64 65 typedef struct ephidmap_data { 66 uid_t min_uid, last_uid; 67 gid_t min_gid, last_gid; 68 cred_t *nobody; 69 kmutex_t eph_lock; 70 } ephidmap_data_t; 71 72 static struct kmem_cache *cred_cache; 73 static size_t crsize = 0; 74 static int audoff = 0; 75 uint32_t ucredsize; 76 cred_t *kcred; 77 static cred_t *dummycr; 78 79 int rstlink; /* link(2) restricted to files owned by user? */ 80 81 static int get_c2audit_load(void); 82 83 #define CR_AUINFO(c) (auditinfo_addr_t *)((audoff == 0) ? NULL : \ 84 ((char *)(c)) + audoff) 85 86 #define REMOTE_PEER_CRED(c) ((c)->cr_gid == -1) 87 88 /* 89 * XXX: should be per-zone. 90 * Start with an invalid value for atomic increments. 91 */ 92 static ephidmap_data_t ephemeral_data = { 93 MAXUID, IDMAP_WK__MAX_UID, MAXUID, IDMAP_WK__MAX_GID 94 }; 95 96 static boolean_t hasephids = B_FALSE; 97 98 /* 99 * Initialize credentials data structures. 100 */ 101 102 void 103 cred_init(void) 104 { 105 priv_init(); 106 107 crsize = sizeof (cred_t) + sizeof (gid_t) * (ngroups_max - 1); 108 /* 109 * Make sure it's word-aligned. 110 */ 111 crsize = (crsize + sizeof (int) - 1) & ~(sizeof (int) - 1); 112 113 if (get_c2audit_load() > 0) { 114 #ifdef _LP64 115 /* assure audit context is 64-bit aligned */ 116 audoff = (crsize + 117 sizeof (int64_t) - 1) & ~(sizeof (int64_t) - 1); 118 #else /* _LP64 */ 119 audoff = crsize; 120 #endif /* _LP64 */ 121 crsize = audoff + sizeof (auditinfo_addr_t); 122 crsize = (crsize + sizeof (int) - 1) & ~(sizeof (int) - 1); 123 } 124 125 cred_cache = kmem_cache_create("cred_cache", crsize, 0, 126 NULL, NULL, NULL, NULL, NULL, 0); 127 128 /* 129 * dummycr is used to copy initial state for creds. 130 */ 131 dummycr = cralloc(); 132 bzero(dummycr, crsize); 133 dummycr->cr_ref = 1; 134 dummycr->cr_uid = (uid_t)-1; 135 dummycr->cr_gid = (gid_t)-1; 136 dummycr->cr_ruid = (uid_t)-1; 137 dummycr->cr_rgid = (gid_t)-1; 138 dummycr->cr_suid = (uid_t)-1; 139 dummycr->cr_sgid = (gid_t)-1; 140 141 142 /* 143 * kcred is used by anything that needs all privileges; it's 144 * also the template used for crget as it has all the compatible 145 * sets filled in. 146 */ 147 kcred = cralloc(); 148 149 bzero(kcred, crsize); 150 kcred->cr_ref = 1; 151 152 /* kcred is never freed, so we don't need zone_cred_hold here */ 153 kcred->cr_zone = &zone0; 154 155 priv_fillset(&CR_LPRIV(kcred)); 156 CR_IPRIV(kcred) = *priv_basic; 157 158 /* Not a basic privilege, if chown is not restricted add it to I0 */ 159 if (!rstchown) 160 priv_addset(&CR_IPRIV(kcred), PRIV_FILE_CHOWN_SELF); 161 162 /* Basic privilege, if link is restricted remove it from I0 */ 163 if (rstlink) 164 priv_delset(&CR_IPRIV(kcred), PRIV_FILE_LINK_ANY); 165 166 CR_EPRIV(kcred) = CR_PPRIV(kcred) = CR_IPRIV(kcred); 167 168 CR_FLAGS(kcred) = NET_MAC_AWARE; 169 170 /* 171 * Set up credentials of p0. 172 */ 173 ttoproc(curthread)->p_cred = kcred; 174 curthread->t_cred = kcred; 175 176 /* 177 * nobody is used to map SID containing CRs. 178 */ 179 ephemeral_data.nobody = crdup(kcred); 180 (void) crsetugid(ephemeral_data.nobody, UID_NOBODY, GID_NOBODY); 181 CR_FLAGS(kcred) = 0; 182 183 ucredsize = UCRED_SIZE; 184 } 185 186 /* 187 * Allocate (nearly) uninitialized cred_t. 188 */ 189 cred_t * 190 cralloc(void) 191 { 192 cred_t *cr = kmem_cache_alloc(cred_cache, KM_SLEEP); 193 cr->cr_ref = 1; /* So we can crfree() */ 194 cr->cr_zone = NULL; 195 cr->cr_label = NULL; 196 cr->cr_ksid = NULL; 197 return (cr); 198 } 199 200 /* 201 * As cralloc but prepared for ksid change (if appropriate). 202 */ 203 cred_t * 204 cralloc_ksid(void) 205 { 206 cred_t *cr = cralloc(); 207 if (hasephids) 208 cr->cr_ksid = kcrsid_alloc(); 209 return (cr); 210 } 211 212 /* 213 * Allocate a initialized cred structure and crhold() it. 214 * Initialized means: all ids 0, group count 0, L=Full, E=P=I=I0 215 */ 216 cred_t * 217 crget(void) 218 { 219 cred_t *cr = kmem_cache_alloc(cred_cache, KM_SLEEP); 220 221 bcopy(kcred, cr, crsize); 222 cr->cr_ref = 1; 223 zone_cred_hold(cr->cr_zone); 224 if (cr->cr_label) 225 label_hold(cr->cr_label); 226 return (cr); 227 } 228 229 /* 230 * Broadcast the cred to all the threads in the process. 231 * The current thread's credentials can be set right away, but other 232 * threads must wait until the start of the next system call or trap. 233 * This avoids changing the cred in the middle of a system call. 234 * 235 * The cred has already been held for the process and the thread (2 holds), 236 * and p->p_cred set. 237 * 238 * p->p_crlock shouldn't be held here, since p_lock must be acquired. 239 */ 240 void 241 crset(proc_t *p, cred_t *cr) 242 { 243 kthread_id_t t; 244 kthread_id_t first; 245 cred_t *oldcr; 246 247 ASSERT(p == curproc); /* assumes p_lwpcnt can't change */ 248 249 /* 250 * DTrace accesses t_cred in probe context. t_cred must always be 251 * either NULL, or point to a valid, allocated cred structure. 252 */ 253 t = curthread; 254 oldcr = t->t_cred; 255 t->t_cred = cr; /* the cred is held by caller for this thread */ 256 crfree(oldcr); /* free the old cred for the thread */ 257 258 /* 259 * Broadcast to other threads, if any. 260 */ 261 if (p->p_lwpcnt > 1) { 262 mutex_enter(&p->p_lock); /* to keep thread list safe */ 263 first = curthread; 264 for (t = first->t_forw; t != first; t = t->t_forw) 265 t->t_pre_sys = 1; /* so syscall will get new cred */ 266 mutex_exit(&p->p_lock); 267 } 268 } 269 270 /* 271 * Put a hold on a cred structure. 272 */ 273 void 274 crhold(cred_t *cr) 275 { 276 atomic_add_32(&cr->cr_ref, 1); 277 } 278 279 /* 280 * Release previous hold on a cred structure. Free it if refcnt == 0. 281 * If cred uses label different from zone label, free it. 282 */ 283 void 284 crfree(cred_t *cr) 285 { 286 if (atomic_add_32_nv(&cr->cr_ref, -1) == 0) { 287 ASSERT(cr != kcred); 288 if (cr->cr_label) 289 label_rele(cr->cr_label); 290 if (cr->cr_zone) 291 zone_cred_rele(cr->cr_zone); 292 if (cr->cr_ksid) 293 kcrsid_rele(cr->cr_ksid); 294 kmem_cache_free(cred_cache, cr); 295 } 296 } 297 298 /* 299 * Copy a cred structure to a new one and free the old one. 300 * The new cred will have two references. One for the calling process, 301 * and one for the thread. 302 */ 303 cred_t * 304 crcopy(cred_t *cr) 305 { 306 cred_t *newcr; 307 308 newcr = cralloc(); 309 bcopy(cr, newcr, crsize); 310 if (newcr->cr_zone) 311 zone_cred_hold(newcr->cr_zone); 312 if (newcr->cr_label) 313 label_hold(cr->cr_label); 314 if (newcr->cr_ksid) 315 kcrsid_hold(cr->cr_ksid); 316 crfree(cr); 317 newcr->cr_ref = 2; /* caller gets two references */ 318 return (newcr); 319 } 320 321 /* 322 * Copy a cred structure to a new one and free the old one. 323 * The new cred will have two references. One for the calling process, 324 * and one for the thread. 325 * This variation on crcopy uses a pre-allocated structure for the 326 * "new" cred. 327 */ 328 void 329 crcopy_to(cred_t *oldcr, cred_t *newcr) 330 { 331 credsid_t *nkcr = newcr->cr_ksid; 332 333 bcopy(oldcr, newcr, crsize); 334 if (newcr->cr_zone) 335 zone_cred_hold(newcr->cr_zone); 336 if (newcr->cr_label) 337 label_hold(newcr->cr_label); 338 if (nkcr) { 339 newcr->cr_ksid = nkcr; 340 kcrsidcopy_to(oldcr->cr_ksid, newcr->cr_ksid); 341 } else if (newcr->cr_ksid) 342 kcrsid_hold(newcr->cr_ksid); 343 crfree(oldcr); 344 newcr->cr_ref = 2; /* caller gets two references */ 345 } 346 347 /* 348 * Dup a cred struct to a new held one. 349 * The old cred is not freed. 350 */ 351 cred_t * 352 crdup(cred_t *cr) 353 { 354 cred_t *newcr; 355 356 newcr = cralloc(); 357 bcopy(cr, newcr, crsize); 358 if (newcr->cr_zone) 359 zone_cred_hold(newcr->cr_zone); 360 if (newcr->cr_label) 361 label_hold(newcr->cr_label); 362 if (newcr->cr_ksid) 363 kcrsid_hold(newcr->cr_ksid); 364 newcr->cr_ref = 1; 365 return (newcr); 366 } 367 368 /* 369 * Dup a cred struct to a new held one. 370 * The old cred is not freed. 371 * This variation on crdup uses a pre-allocated structure for the 372 * "new" cred. 373 */ 374 void 375 crdup_to(cred_t *oldcr, cred_t *newcr) 376 { 377 credsid_t *nkcr = newcr->cr_ksid; 378 379 bcopy(oldcr, newcr, crsize); 380 if (newcr->cr_zone) 381 zone_cred_hold(newcr->cr_zone); 382 if (newcr->cr_label) 383 label_hold(newcr->cr_label); 384 if (nkcr) { 385 newcr->cr_ksid = nkcr; 386 kcrsidcopy_to(oldcr->cr_ksid, newcr->cr_ksid); 387 } else if (newcr->cr_ksid) 388 kcrsid_hold(newcr->cr_ksid); 389 newcr->cr_ref = 1; 390 } 391 392 /* 393 * Return the (held) credentials for the current running process. 394 */ 395 cred_t * 396 crgetcred(void) 397 { 398 cred_t *cr; 399 proc_t *p; 400 401 p = ttoproc(curthread); 402 mutex_enter(&p->p_crlock); 403 crhold(cr = p->p_cred); 404 mutex_exit(&p->p_crlock); 405 return (cr); 406 } 407 408 /* 409 * Backward compatibility check for suser(). 410 * Accounting flag is now set in the policy functions; auditing is 411 * done through use of privilege in the audit trail. 412 */ 413 int 414 suser(cred_t *cr) 415 { 416 return (PRIV_POLICY(cr, PRIV_SYS_SUSER_COMPAT, B_FALSE, EPERM, NULL) 417 == 0); 418 } 419 420 /* 421 * Determine whether the supplied group id is a member of the group 422 * described by the supplied credentials. 423 */ 424 int 425 groupmember(gid_t gid, const cred_t *cr) 426 { 427 if (gid == cr->cr_gid) 428 return (1); 429 return (supgroupmember(gid, cr)); 430 } 431 432 /* 433 * As groupmember but only check against the supplemental groups. 434 */ 435 int 436 supgroupmember(gid_t gid, const cred_t *cr) 437 { 438 const gid_t *gp, *endgp; 439 440 endgp = &cr->cr_groups[cr->cr_ngroups]; 441 for (gp = cr->cr_groups; gp < endgp; gp++) 442 if (*gp == gid) 443 return (1); 444 return (0); 445 } 446 447 /* 448 * This function is called to check whether the credentials set 449 * "scrp" has permission to act on credentials set "tcrp". It enforces the 450 * permission requirements needed to send a signal to a process. 451 * The same requirements are imposed by other system calls, however. 452 * 453 * The rules are: 454 * (1) if the credentials are the same, the check succeeds 455 * (2) if the zone ids don't match, and scrp is not in the global zone or 456 * does not have the PRIV_PROC_ZONE privilege, the check fails 457 * (3) if the real or effective user id of scrp matches the real or saved 458 * user id of tcrp or scrp has the PRIV_PROC_OWNER privilege, the check 459 * succeeds 460 * (4) otherwise, the check fails 461 */ 462 int 463 hasprocperm(const cred_t *tcrp, const cred_t *scrp) 464 { 465 if (scrp == tcrp) 466 return (1); 467 if (scrp->cr_zone != tcrp->cr_zone && 468 (scrp->cr_zone != global_zone || 469 secpolicy_proc_zone(scrp) != 0)) 470 return (0); 471 if (scrp->cr_uid == tcrp->cr_ruid || 472 scrp->cr_ruid == tcrp->cr_ruid || 473 scrp->cr_uid == tcrp->cr_suid || 474 scrp->cr_ruid == tcrp->cr_suid || 475 !PRIV_POLICY(scrp, PRIV_PROC_OWNER, B_FALSE, EPERM, "hasprocperm")) 476 return (1); 477 return (0); 478 } 479 480 /* 481 * This interface replaces hasprocperm; it works like hasprocperm but 482 * additionally returns success if the proc_t's match 483 * It is the preferred interface for most uses. 484 * And it will acquire pcrlock itself, so it assert's that it shouldn't 485 * be held. 486 */ 487 int 488 prochasprocperm(proc_t *tp, proc_t *sp, const cred_t *scrp) 489 { 490 int rets; 491 cred_t *tcrp; 492 493 ASSERT(MUTEX_NOT_HELD(&tp->p_crlock)); 494 495 if (tp == sp) 496 return (1); 497 498 if (tp->p_sessp != sp->p_sessp && secpolicy_basic_proc(scrp) != 0) 499 return (0); 500 501 mutex_enter(&tp->p_crlock); 502 tcrp = tp->p_cred; 503 rets = hasprocperm(tcrp, scrp); 504 mutex_exit(&tp->p_crlock); 505 506 return (rets); 507 } 508 509 /* 510 * This routine is used to compare two credentials to determine if 511 * they refer to the same "user". If the pointers are equal, then 512 * they must refer to the same user. Otherwise, the contents of 513 * the credentials are compared to see whether they are equivalent. 514 * 515 * This routine returns 0 if the credentials refer to the same user, 516 * 1 if they do not. 517 */ 518 int 519 crcmp(const cred_t *cr1, const cred_t *cr2) 520 { 521 522 if (cr1 == cr2) 523 return (0); 524 525 if (cr1->cr_uid == cr2->cr_uid && 526 cr1->cr_gid == cr2->cr_gid && 527 cr1->cr_ruid == cr2->cr_ruid && 528 cr1->cr_rgid == cr2->cr_rgid && 529 cr1->cr_ngroups == cr2->cr_ngroups && 530 cr1->cr_zone == cr2->cr_zone && 531 bcmp(cr1->cr_groups, cr2->cr_groups, 532 cr1->cr_ngroups * sizeof (gid_t)) == 0) { 533 return (!priv_isequalset(&CR_OEPRIV(cr1), &CR_OEPRIV(cr2))); 534 } 535 return (1); 536 } 537 538 /* 539 * Read access functions to cred_t. 540 */ 541 uid_t 542 crgetuid(const cred_t *cr) 543 { 544 return (cr->cr_uid); 545 } 546 547 uid_t 548 crgetruid(const cred_t *cr) 549 { 550 return (cr->cr_ruid); 551 } 552 553 uid_t 554 crgetsuid(const cred_t *cr) 555 { 556 return (cr->cr_suid); 557 } 558 559 gid_t 560 crgetgid(const cred_t *cr) 561 { 562 return (cr->cr_gid); 563 } 564 565 gid_t 566 crgetrgid(const cred_t *cr) 567 { 568 return (cr->cr_rgid); 569 } 570 571 gid_t 572 crgetsgid(const cred_t *cr) 573 { 574 return (cr->cr_sgid); 575 } 576 577 const auditinfo_addr_t * 578 crgetauinfo(const cred_t *cr) 579 { 580 return ((const auditinfo_addr_t *)CR_AUINFO(cr)); 581 } 582 583 auditinfo_addr_t * 584 crgetauinfo_modifiable(cred_t *cr) 585 { 586 return (CR_AUINFO(cr)); 587 } 588 589 zoneid_t 590 crgetzoneid(const cred_t *cr) 591 { 592 return (cr->cr_zone == NULL ? 593 (cr->cr_uid == -1 ? (zoneid_t)-1 : GLOBAL_ZONEID) : 594 cr->cr_zone->zone_id); 595 } 596 597 projid_t 598 crgetprojid(const cred_t *cr) 599 { 600 return (cr->cr_projid); 601 } 602 603 zone_t * 604 crgetzone(const cred_t *cr) 605 { 606 return (cr->cr_zone); 607 } 608 609 struct ts_label_s * 610 crgetlabel(const cred_t *cr) 611 { 612 return (cr->cr_label ? 613 cr->cr_label : 614 (cr->cr_zone ? cr->cr_zone->zone_slabel : NULL)); 615 } 616 617 boolean_t 618 crisremote(const cred_t *cr) 619 { 620 return (REMOTE_PEER_CRED(cr)); 621 } 622 623 #define BADUID(x) ((x) != -1 && !VALID_UID(x)) 624 #define BADGID(x) ((x) != -1 && !VALID_GID(x)) 625 626 int 627 crsetresuid(cred_t *cr, uid_t r, uid_t e, uid_t s) 628 { 629 ASSERT(cr->cr_ref <= 2); 630 631 if (BADUID(r) || BADUID(e) || BADUID(s)) 632 return (-1); 633 634 if (r != -1) 635 cr->cr_ruid = r; 636 if (e != -1) 637 cr->cr_uid = e; 638 if (s != -1) 639 cr->cr_suid = s; 640 641 return (0); 642 } 643 644 int 645 crsetresgid(cred_t *cr, gid_t r, gid_t e, gid_t s) 646 { 647 ASSERT(cr->cr_ref <= 2); 648 649 if (BADGID(r) || BADGID(e) || BADGID(s)) 650 return (-1); 651 652 if (r != -1) 653 cr->cr_rgid = r; 654 if (e != -1) 655 cr->cr_gid = e; 656 if (s != -1) 657 cr->cr_sgid = s; 658 659 return (0); 660 } 661 662 int 663 crsetugid(cred_t *cr, uid_t uid, gid_t gid) 664 { 665 ASSERT(cr->cr_ref <= 2); 666 667 if (!VALID_UID(uid) || !VALID_GID(gid)) 668 return (-1); 669 670 cr->cr_uid = cr->cr_ruid = cr->cr_suid = uid; 671 cr->cr_gid = cr->cr_rgid = cr->cr_sgid = gid; 672 673 return (0); 674 } 675 676 int 677 crsetgroups(cred_t *cr, int n, gid_t *grp) 678 { 679 ASSERT(cr->cr_ref <= 2); 680 681 if (n > ngroups_max || n < 0) 682 return (-1); 683 684 cr->cr_ngroups = n; 685 686 if (n > 0) 687 bcopy(grp, cr->cr_groups, n * sizeof (gid_t)); 688 689 return (0); 690 } 691 692 void 693 crsetprojid(cred_t *cr, projid_t projid) 694 { 695 ASSERT(projid >= 0 && projid <= MAXPROJID); 696 cr->cr_projid = projid; 697 } 698 699 /* 700 * This routine returns the pointer to the first element of the cr_groups 701 * array. It can move around in an implementation defined way. 702 */ 703 const gid_t * 704 crgetgroups(const cred_t *cr) 705 { 706 return (cr->cr_groups); 707 } 708 709 int 710 crgetngroups(const cred_t *cr) 711 { 712 return (cr->cr_ngroups); 713 } 714 715 void 716 cred2prcred(const cred_t *cr, prcred_t *pcrp) 717 { 718 pcrp->pr_euid = cr->cr_uid; 719 pcrp->pr_ruid = cr->cr_ruid; 720 pcrp->pr_suid = cr->cr_suid; 721 pcrp->pr_egid = cr->cr_gid; 722 pcrp->pr_rgid = cr->cr_rgid; 723 pcrp->pr_sgid = cr->cr_sgid; 724 pcrp->pr_ngroups = MIN(cr->cr_ngroups, (uint_t)ngroups_max); 725 pcrp->pr_groups[0] = 0; /* in case ngroups == 0 */ 726 727 if (pcrp->pr_ngroups != 0) 728 bcopy(cr->cr_groups, pcrp->pr_groups, 729 sizeof (gid_t) * cr->cr_ngroups); 730 } 731 732 static int 733 cred2ucaud(const cred_t *cr, auditinfo64_addr_t *ainfo, const cred_t *rcr) 734 { 735 auditinfo_addr_t *ai; 736 au_tid_addr_t tid; 737 738 if (secpolicy_audit_getattr(rcr) != 0) 739 return (-1); 740 741 ai = CR_AUINFO(cr); /* caller makes sure this is non-NULL */ 742 tid = ai->ai_termid; 743 744 ainfo->ai_auid = ai->ai_auid; 745 ainfo->ai_mask = ai->ai_mask; 746 ainfo->ai_asid = ai->ai_asid; 747 748 ainfo->ai_termid.at_type = tid.at_type; 749 bcopy(&tid.at_addr, &ainfo->ai_termid.at_addr, 4 * sizeof (uint_t)); 750 751 ainfo->ai_termid.at_port.at_major = (uint32_t)getmajor(tid.at_port); 752 ainfo->ai_termid.at_port.at_minor = (uint32_t)getminor(tid.at_port); 753 754 return (0); 755 } 756 757 void 758 cred2uclabel(const cred_t *cr, bslabel_t *labelp) 759 { 760 ts_label_t *tslp; 761 762 if ((tslp = crgetlabel(cr)) != NULL) 763 bcopy(&tslp->tsl_label, labelp, sizeof (bslabel_t)); 764 } 765 766 /* 767 * Convert a credential into a "ucred". Allow the caller to specify 768 * and aligned buffer, e.g., in an mblk, so we don't have to allocate 769 * memory and copy it twice. 770 * 771 * This function may call cred2ucaud(), which calls CRED(). Since this 772 * can be called from an interrupt thread, receiver's cred (rcr) is needed 773 * to determine whether audit info should be included. 774 */ 775 struct ucred_s * 776 cred2ucred(const cred_t *cr, pid_t pid, void *buf, const cred_t *rcr) 777 { 778 struct ucred_s *uc; 779 780 /* The structure isn't always completely filled in, so zero it */ 781 if (buf == NULL) { 782 uc = kmem_zalloc(ucredsize, KM_SLEEP); 783 } else { 784 bzero(buf, ucredsize); 785 uc = buf; 786 } 787 uc->uc_size = ucredsize; 788 uc->uc_credoff = UCRED_CRED_OFF; 789 uc->uc_privoff = UCRED_PRIV_OFF; 790 uc->uc_audoff = UCRED_AUD_OFF; 791 uc->uc_labeloff = UCRED_LABEL_OFF; 792 uc->uc_pid = pid; 793 uc->uc_projid = cr->cr_projid; 794 uc->uc_zoneid = crgetzoneid(cr); 795 796 /* 797 * Note that cred2uclabel() call should not be factored out 798 * to the bottom of the if-else. UCXXX() macros depend on 799 * uc_xxxoff values to work correctly. 800 */ 801 if (REMOTE_PEER_CRED(cr)) { 802 /* 803 * other than label, the rest of cred info about a 804 * remote peer isn't available. 805 */ 806 cred2uclabel(cr, UCLABEL(uc)); 807 uc->uc_credoff = 0; 808 uc->uc_privoff = 0; 809 uc->uc_audoff = 0; 810 } else { 811 cred2prcred(cr, UCCRED(uc)); 812 cred2prpriv(cr, UCPRIV(uc)); 813 if (audoff == 0 || cred2ucaud(cr, UCAUD(uc), rcr) != 0) 814 uc->uc_audoff = 0; 815 cred2uclabel(cr, UCLABEL(uc)); 816 } 817 818 return (uc); 819 } 820 821 /* 822 * Get the "ucred" of a process. 823 */ 824 struct ucred_s * 825 pgetucred(proc_t *p) 826 { 827 cred_t *cr; 828 struct ucred_s *uc; 829 830 mutex_enter(&p->p_crlock); 831 cr = p->p_cred; 832 crhold(cr); 833 mutex_exit(&p->p_crlock); 834 835 uc = cred2ucred(cr, p->p_pid, NULL, CRED()); 836 crfree(cr); 837 838 return (uc); 839 } 840 841 /* 842 * If the reply status is NFSERR_EACCES, it may be because we are 843 * root (no root net access). Check the real uid, if it isn't root 844 * make that the uid instead and retry the call. 845 * Private interface for NFS. 846 */ 847 cred_t * 848 crnetadjust(cred_t *cr) 849 { 850 if (cr->cr_uid == 0 && cr->cr_ruid != 0) { 851 cr = crdup(cr); 852 cr->cr_uid = cr->cr_ruid; 853 return (cr); 854 } 855 return (NULL); 856 } 857 858 /* 859 * The reference count is of interest when you want to check 860 * whether it is ok to modify the credential in place. 861 */ 862 uint_t 863 crgetref(const cred_t *cr) 864 { 865 return (cr->cr_ref); 866 } 867 868 static int 869 get_c2audit_load(void) 870 { 871 static int gotit = 0; 872 static int c2audit_load; 873 u_longlong_t audit_load_val; 874 875 if (gotit) 876 return (c2audit_load); 877 audit_load_val = 0; /* set default value once */ 878 (void) mod_sysvar("c2audit", "audit_load", &audit_load_val); 879 c2audit_load = (int)audit_load_val; 880 gotit++; 881 return (c2audit_load); 882 } 883 884 int 885 get_audit_ucrsize(void) 886 { 887 return (get_c2audit_load() ? sizeof (auditinfo64_addr_t) : 0); 888 } 889 890 /* 891 * Set zone pointer in credential to indicated value. First adds a 892 * hold for the new zone, then drops the hold on previous zone (if any). 893 * This is done in this order in case the old and new zones are the 894 * same. 895 */ 896 void 897 crsetzone(cred_t *cr, zone_t *zptr) 898 { 899 zone_t *oldzptr = cr->cr_zone; 900 901 ASSERT(cr != kcred); 902 ASSERT(cr->cr_ref <= 2); 903 cr->cr_zone = zptr; 904 zone_cred_hold(zptr); 905 if (oldzptr) 906 zone_cred_rele(oldzptr); 907 } 908 909 /* 910 * Create a new cred based on the supplied label 911 */ 912 cred_t * 913 newcred_from_bslabel(bslabel_t *blabel, uint32_t doi, int flags) 914 { 915 ts_label_t *lbl = labelalloc(blabel, doi, flags); 916 cred_t *cr = NULL; 917 918 if (lbl != NULL) { 919 if ((cr = kmem_cache_alloc(cred_cache, flags)) != NULL) { 920 bcopy(dummycr, cr, crsize); 921 cr->cr_label = lbl; 922 } else { 923 label_rele(lbl); 924 } 925 } 926 927 return (cr); 928 } 929 930 /* 931 * Derive a new cred from the existing cred, but with a different label. 932 * To be used when a cred is being shared, but the label needs to be changed 933 * by a caller without affecting other users 934 */ 935 cred_t * 936 copycred_from_bslabel(cred_t *cr, bslabel_t *blabel, uint32_t doi, int flags) 937 { 938 ts_label_t *lbl = labelalloc(blabel, doi, flags); 939 cred_t *newcr = NULL; 940 941 if (lbl != NULL) { 942 if ((newcr = kmem_cache_alloc(cred_cache, flags)) != NULL) { 943 bcopy(cr, newcr, crsize); 944 if (newcr->cr_zone) 945 zone_cred_hold(newcr->cr_zone); 946 newcr->cr_label = lbl; 947 newcr->cr_ref = 1; 948 } else { 949 label_rele(lbl); 950 } 951 } 952 953 return (newcr); 954 } 955 956 /* 957 * This function returns a pointer to the kcred-equivalent in the current zone. 958 */ 959 cred_t * 960 zone_kcred(void) 961 { 962 zone_t *zone; 963 964 if ((zone = CRED()->cr_zone) != NULL) 965 return (zone->zone_kcred); 966 else 967 return (kcred); 968 } 969 970 boolean_t 971 valid_ephemeral_uid(uid_t id) 972 { 973 membar_consumer(); 974 return (id < IDMAP_WK__MAX_UID || 975 (id > ephemeral_data.min_uid && id <= ephemeral_data.last_uid)); 976 } 977 978 boolean_t 979 valid_ephemeral_gid(gid_t id) 980 { 981 membar_consumer(); 982 return (id < IDMAP_WK__MAX_GID || 983 (id > ephemeral_data.min_gid && id <= ephemeral_data.last_gid)); 984 } 985 986 int 987 eph_uid_alloc(int flags, uid_t *start, int count) 988 { 989 mutex_enter(&ephemeral_data.eph_lock); 990 991 /* Test for unsigned integer wrap around */ 992 if (ephemeral_data.last_uid + count < ephemeral_data.last_uid) { 993 mutex_exit(&ephemeral_data.eph_lock); 994 return (-1); 995 } 996 997 /* first call or idmap crashed and state corrupted */ 998 if (flags != 0) 999 ephemeral_data.min_uid = ephemeral_data.last_uid; 1000 1001 hasephids = B_TRUE; 1002 *start = ephemeral_data.last_uid + 1; 1003 atomic_add_32(&ephemeral_data.last_uid, count); 1004 mutex_exit(&ephemeral_data.eph_lock); 1005 return (0); 1006 } 1007 1008 int 1009 eph_gid_alloc(int flags, gid_t *start, int count) 1010 { 1011 mutex_enter(&ephemeral_data.eph_lock); 1012 1013 /* Test for unsigned integer wrap around */ 1014 if (ephemeral_data.last_gid + count < ephemeral_data.last_gid) { 1015 mutex_exit(&ephemeral_data.eph_lock); 1016 return (-1); 1017 } 1018 1019 /* first call or idmap crashed and state corrupted */ 1020 if (flags != 0) 1021 ephemeral_data.min_gid = ephemeral_data.last_gid; 1022 1023 hasephids = B_TRUE; 1024 *start = ephemeral_data.last_gid + 1; 1025 atomic_add_32(&ephemeral_data.last_gid, count); 1026 mutex_exit(&ephemeral_data.eph_lock); 1027 return (0); 1028 } 1029 1030 /* 1031 * If the credential contains any ephemeral IDs, map the credential 1032 * to nobody. 1033 */ 1034 cred_t * 1035 crgetmapped(const cred_t *cr) 1036 { 1037 /* 1038 * Someone incorrectly passed a NULL cred to a vnode operation 1039 * either on purpose or by calling CRED() in interrupt context. 1040 */ 1041 if (cr == NULL) 1042 return (NULL); 1043 1044 if (cr->cr_ksid != NULL) { 1045 int i; 1046 1047 for (i = 0; i < KSID_COUNT; i++) 1048 if (cr->cr_ksid->kr_sidx[i].ks_id > MAXUID) 1049 return (ephemeral_data.nobody); 1050 if (cr->cr_ksid->kr_sidlist != NULL && 1051 cr->cr_ksid->kr_sidlist->ksl_neid > 0) { 1052 return (ephemeral_data.nobody); 1053 } 1054 } 1055 1056 return ((cred_t *)cr); 1057 } 1058 1059 /* index should be in range for a ksidindex_t */ 1060 void 1061 crsetsid(cred_t *cr, ksid_t *ksp, int index) 1062 { 1063 ASSERT(cr->cr_ref <= 2); 1064 ASSERT(index >= 0 && index < KSID_COUNT); 1065 if (cr->cr_ksid == NULL && ksp == NULL) 1066 return; 1067 cr->cr_ksid = kcrsid_setsid(cr->cr_ksid, ksp, index); 1068 } 1069 1070 void 1071 crsetsidlist(cred_t *cr, ksidlist_t *ksl) 1072 { 1073 ASSERT(cr->cr_ref <= 2); 1074 if (cr->cr_ksid == NULL && ksl == NULL) 1075 return; 1076 cr->cr_ksid = kcrsid_setsidlist(cr->cr_ksid, ksl); 1077 } 1078 1079 ksid_t * 1080 crgetsid(const cred_t *cr, int i) 1081 { 1082 ASSERT(i >= 0 && i < KSID_COUNT); 1083 if (cr->cr_ksid != NULL && cr->cr_ksid->kr_sidx[i].ks_domain) 1084 return ((ksid_t *)&cr->cr_ksid->kr_sidx[i]); 1085 return (NULL); 1086 } 1087 1088 ksidlist_t * 1089 crgetsidlist(const cred_t *cr) 1090 { 1091 if (cr->cr_ksid != NULL && cr->cr_ksid->kr_sidlist != NULL) 1092 return ((ksidlist_t *)&cr->cr_ksid->kr_sidlist); 1093 return (NULL); 1094 } 1095