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