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