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