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