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