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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 /* 31 * University Copyright- Copyright (c) 1982, 1986, 1988 32 * The Regents of the University of California 33 * All Rights Reserved 34 * 35 * University Acknowledgment- Portions of this document are derived from 36 * software developed by the University of California, Berkeley, and its 37 * contributors. 38 */ 39 40 #pragma ident "%Z%%M% %I% %E% SMI" 41 42 #include <sys/types.h> 43 #include <sys/sysmacros.h> 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/cred_impl.h> 47 #include <sys/policy.h> 48 #include <sys/vnode.h> 49 #include <sys/errno.h> 50 #include <sys/kmem.h> 51 #include <sys/user.h> 52 #include <sys/proc.h> 53 #include <sys/acct.h> 54 #include <sys/syscall.h> 55 #include <sys/cmn_err.h> 56 #include <sys/debug.h> 57 #include <sys/atomic.h> 58 #include <sys/ucred.h> 59 #include <sys/prsystm.h> 60 #include <sys/modctl.h> 61 #include <c2/audit.h> 62 #include <sys/zone.h> 63 64 static struct kmem_cache *cred_cache; 65 static size_t crsize = 0; 66 static int audoff = 0; 67 uint32_t ucredsize; 68 cred_t *kcred; 69 70 int rstlink; /* link(2) restricted to files owned by user? */ 71 72 static int get_c2audit_load(void); 73 74 #define CR_AUINFO(c) (auditinfo_addr_t *)((audoff == 0) ? NULL : \ 75 ((char *)(c)) + audoff) 76 77 78 /* 79 * Initialize credentials data structures. 80 */ 81 82 void 83 cred_init(void) 84 { 85 priv_init(); 86 87 crsize = sizeof (cred_t) + sizeof (gid_t) * (ngroups_max - 1); 88 /* 89 * Make sure it's word-aligned. 90 */ 91 crsize = (crsize + sizeof (int) - 1) & ~(sizeof (int) - 1); 92 93 if (get_c2audit_load() > 0) { 94 #ifdef _LP64 95 /* assure audit context is 64-bit aligned */ 96 audoff = (crsize + 97 sizeof (int64_t) - 1) & ~(sizeof (int64_t) - 1); 98 #else /* _LP64 */ 99 audoff = crsize; 100 #endif /* _LP64 */ 101 crsize = audoff + sizeof (auditinfo_addr_t); 102 crsize = (crsize + sizeof (int) - 1) & ~(sizeof (int) - 1); 103 } 104 105 cred_cache = kmem_cache_create("cred_cache", crsize, 0, 106 NULL, NULL, NULL, NULL, NULL, 0); 107 108 /* 109 * kcred is used by anything that needs all privileges; it's 110 * also the template used for crget as it has all the compatible 111 * sets filled in. 112 */ 113 kcred = cralloc(); 114 115 bzero(kcred, crsize); 116 kcred->cr_ref = 1; 117 118 /* kcred is never freed, so we don't need zone_cred_hold here */ 119 kcred->cr_zone = &zone0; 120 121 priv_fillset(&CR_LPRIV(kcred)); 122 CR_IPRIV(kcred) = *priv_basic; 123 124 /* Not a basic privilege, if chown is not restricted add it to I0 */ 125 if (!rstchown) 126 priv_addset(&CR_IPRIV(kcred), PRIV_FILE_CHOWN_SELF); 127 128 /* Basic privilege, if link is restricted remove it from I0 */ 129 if (rstlink) 130 priv_delset(&CR_IPRIV(kcred), PRIV_FILE_LINK_ANY); 131 132 CR_EPRIV(kcred) = CR_PPRIV(kcred) = CR_IPRIV(kcred); 133 /* CR_FLAGS(kcred) == 0, courtesy of bzero() */ 134 135 /* 136 * Set up credentials of p0. 137 */ 138 ttoproc(curthread)->p_cred = kcred; 139 curthread->t_cred = kcred; 140 141 ucredsize = UCRED_SIZE; 142 } 143 144 /* 145 * Allocate (nearly) uninitialized cred_t. 146 */ 147 cred_t * 148 cralloc(void) 149 { 150 cred_t *cr = kmem_cache_alloc(cred_cache, KM_SLEEP); 151 cr->cr_ref = 1; /* So we can crfree() */ 152 cr->cr_zone = NULL; 153 return (cr); 154 } 155 156 /* 157 * Allocate a initialized cred structure and crhold() it. 158 * Initialized means: all ids 0, group count 0, L=Full, E=P=I=I0 159 */ 160 cred_t * 161 crget(void) 162 { 163 cred_t *cr = kmem_cache_alloc(cred_cache, KM_SLEEP); 164 165 bcopy(kcred, cr, crsize); 166 cr->cr_ref = 1; 167 zone_cred_hold(cr->cr_zone); 168 return (cr); 169 } 170 171 /* 172 * Broadcast the cred to all the threads in the process. 173 * The current thread's credentials can be set right away, but other 174 * threads must wait until the start of the next system call or trap. 175 * This avoids changing the cred in the middle of a system call. 176 * 177 * The cred has already been held for the process and the thread (2 holds), 178 * and p->p_cred set. 179 * 180 * p->p_crlock shouldn't be held here, since p_lock must be acquired. 181 */ 182 void 183 crset(proc_t *p, cred_t *cr) 184 { 185 kthread_id_t t; 186 kthread_id_t first; 187 cred_t *oldcr; 188 189 ASSERT(p == curproc); /* assumes p_lwpcnt can't change */ 190 191 /* 192 * DTrace accesses t_cred in probe context. t_cred must always be 193 * either NULL, or point to a valid, allocated cred structure. 194 */ 195 t = curthread; 196 oldcr = t->t_cred; 197 t->t_cred = cr; /* the cred is held by caller for this thread */ 198 crfree(oldcr); /* free the old cred for the thread */ 199 200 /* 201 * Broadcast to other threads, if any. 202 */ 203 if (p->p_lwpcnt > 1) { 204 mutex_enter(&p->p_lock); /* to keep thread list safe */ 205 first = curthread; 206 for (t = first->t_forw; t != first; t = t->t_forw) 207 t->t_pre_sys = 1; /* so syscall will get new cred */ 208 mutex_exit(&p->p_lock); 209 } 210 } 211 212 /* 213 * Put a hold on a cred structure. 214 */ 215 void 216 crhold(cred_t *cr) 217 { 218 atomic_add_32(&cr->cr_ref, 1); 219 } 220 221 /* 222 * Release previous hold on a cred structure. Free it if refcnt == 0. 223 */ 224 void 225 crfree(cred_t *cr) 226 { 227 if (atomic_add_32_nv(&cr->cr_ref, -1) == 0) { 228 ASSERT(cr != kcred); 229 if (cr->cr_zone) 230 zone_cred_rele(cr->cr_zone); 231 kmem_cache_free(cred_cache, cr); 232 } 233 } 234 235 /* 236 * Copy a cred structure to a new one and free the old one. 237 * The new cred will have two references. One for the calling process, 238 * and one for the thread. 239 */ 240 cred_t * 241 crcopy(cred_t *cr) 242 { 243 cred_t *newcr; 244 245 newcr = cralloc(); 246 bcopy(cr, newcr, crsize); 247 if (newcr->cr_zone) 248 zone_cred_hold(newcr->cr_zone); 249 crfree(cr); 250 newcr->cr_ref = 2; /* caller gets two references */ 251 return (newcr); 252 } 253 254 /* 255 * Copy a cred structure to a new one and free the old one. 256 * The new cred will have two references. One for the calling process, 257 * and one for the thread. 258 * This variation on crcopy uses a pre-allocated structure for the 259 * "new" cred. 260 */ 261 void 262 crcopy_to(cred_t *oldcr, cred_t *newcr) 263 { 264 bcopy(oldcr, newcr, crsize); 265 if (newcr->cr_zone) 266 zone_cred_hold(newcr->cr_zone); 267 crfree(oldcr); 268 newcr->cr_ref = 2; /* caller gets two references */ 269 } 270 271 /* 272 * Dup a cred struct to a new held one. 273 * The old cred is not freed. 274 */ 275 cred_t * 276 crdup(cred_t *cr) 277 { 278 cred_t *newcr; 279 280 newcr = cralloc(); 281 bcopy(cr, newcr, crsize); 282 if (newcr->cr_zone) 283 zone_cred_hold(newcr->cr_zone); 284 newcr->cr_ref = 1; 285 return (newcr); 286 } 287 288 /* 289 * Dup a cred struct to a new held one. 290 * The old cred is not freed. 291 * This variation on crdup uses a pre-allocated structure for the 292 * "new" cred. 293 */ 294 void 295 crdup_to(cred_t *oldcr, cred_t *newcr) 296 { 297 bcopy(oldcr, newcr, crsize); 298 if (newcr->cr_zone) 299 zone_cred_hold(newcr->cr_zone); 300 newcr->cr_ref = 1; 301 } 302 303 /* 304 * Return the (held) credentials for the current running process. 305 */ 306 cred_t * 307 crgetcred() 308 { 309 cred_t *cr; 310 proc_t *p; 311 312 p = ttoproc(curthread); 313 mutex_enter(&p->p_crlock); 314 crhold(cr = p->p_cred); 315 mutex_exit(&p->p_crlock); 316 return (cr); 317 } 318 319 /* 320 * Backward compatibility check for suser(). 321 * Accounting flag is now set in the policy functions; auditing is 322 * done through use of privilege in the audit trail. 323 */ 324 int 325 suser(cred_t *cr) 326 { 327 return (PRIV_POLICY(cr, PRIV_SYS_SUSER_COMPAT, B_FALSE, EPERM, NULL) 328 == 0); 329 } 330 331 /* 332 * Determine whether the supplied group id is a member of the group 333 * described by the supplied credentials. 334 */ 335 int 336 groupmember(gid_t gid, const cred_t *cr) 337 { 338 if (gid == cr->cr_gid) 339 return (1); 340 return (supgroupmember(gid, cr)); 341 } 342 343 /* 344 * As groupmember but only check against the supplemental groups. 345 */ 346 int 347 supgroupmember(gid_t gid, const cred_t *cr) 348 { 349 const gid_t *gp, *endgp; 350 351 endgp = &cr->cr_groups[cr->cr_ngroups]; 352 for (gp = cr->cr_groups; gp < endgp; gp++) 353 if (*gp == gid) 354 return (1); 355 return (0); 356 } 357 358 /* 359 * This function is called to check whether the credentials set 360 * "scrp" has permission to act on credentials set "tcrp". It enforces the 361 * permission requirements needed to send a signal to a process. 362 * The same requirements are imposed by other system calls, however. 363 * 364 * The rules are: 365 * (1) if the credentials are the same, the check succeeds 366 * (2) if the zone ids don't match, and scrp is not in the global zone or 367 * does not have the PRIV_PROC_ZONE privilege, the check fails 368 * (3) if the real or effective user id of scrp matches the real or saved 369 * user id of tcrp or scrp has the PRIV_PROC_OWNER privilege, the check 370 * succeeds 371 * (4) otherwise, the check fails 372 */ 373 int 374 hasprocperm(const cred_t *tcrp, const cred_t *scrp) 375 { 376 if (scrp == tcrp) 377 return (1); 378 if (scrp->cr_zone != tcrp->cr_zone && 379 (scrp->cr_zone != global_zone || 380 secpolicy_proc_zone(scrp) != 0)) 381 return (0); 382 if (scrp->cr_uid == tcrp->cr_ruid || 383 scrp->cr_ruid == tcrp->cr_ruid || 384 scrp->cr_uid == tcrp->cr_suid || 385 scrp->cr_ruid == tcrp->cr_suid || 386 !PRIV_POLICY(scrp, PRIV_PROC_OWNER, B_FALSE, EPERM, "hasprocperm")) 387 return (1); 388 return (0); 389 } 390 391 /* 392 * This interface replaces hasprocperm; it works like hasprocperm but 393 * additionally returns success if the proc_t's match 394 * It is the preferred interface for most uses. 395 * And it will acquire pcrlock itself, so it assert's that it shouldn't 396 * be held. 397 */ 398 int 399 prochasprocperm(proc_t *tp, proc_t *sp, const cred_t *scrp) 400 { 401 int rets; 402 cred_t *tcrp; 403 404 ASSERT(MUTEX_NOT_HELD(&tp->p_crlock)); 405 406 if (tp == sp) 407 return (1); 408 409 if (tp->p_sessp != sp->p_sessp && secpolicy_basic_proc(scrp) != 0) 410 return (0); 411 412 mutex_enter(&tp->p_crlock); 413 tcrp = tp->p_cred; 414 rets = hasprocperm(tcrp, scrp); 415 mutex_exit(&tp->p_crlock); 416 417 return (rets); 418 } 419 420 /* 421 * This routine is used to compare two credentials to determine if 422 * they refer to the same "user". If the pointers are equal, then 423 * they must refer to the same user. Otherwise, the contents of 424 * the credentials are compared to see whether they are equivalent. 425 * 426 * This routine returns 0 if the credentials refer to the same user, 427 * 1 if they do not. 428 */ 429 int 430 crcmp(const cred_t *cr1, const cred_t *cr2) 431 { 432 433 if (cr1 == cr2) 434 return (0); 435 436 if (cr1->cr_uid == cr2->cr_uid && 437 cr1->cr_gid == cr2->cr_gid && 438 cr1->cr_ruid == cr2->cr_ruid && 439 cr1->cr_rgid == cr2->cr_rgid && 440 cr1->cr_ngroups == cr2->cr_ngroups && 441 cr1->cr_zone == cr2->cr_zone && 442 bcmp(cr1->cr_groups, cr2->cr_groups, 443 cr1->cr_ngroups * sizeof (gid_t)) == 0) { 444 return (!priv_isequalset(&CR_OEPRIV(cr1), &CR_OEPRIV(cr2))); 445 } 446 return (1); 447 } 448 449 /* 450 * Read access functions to cred_t. 451 */ 452 uid_t 453 crgetuid(const cred_t *cr) 454 { 455 return (cr->cr_uid); 456 } 457 458 uid_t 459 crgetruid(const cred_t *cr) 460 { 461 return (cr->cr_ruid); 462 } 463 464 uid_t 465 crgetsuid(const cred_t *cr) 466 { 467 return (cr->cr_suid); 468 } 469 470 gid_t 471 crgetgid(const cred_t *cr) 472 { 473 return (cr->cr_gid); 474 } 475 476 gid_t 477 crgetrgid(const cred_t *cr) 478 { 479 return (cr->cr_rgid); 480 } 481 482 gid_t 483 crgetsgid(const cred_t *cr) 484 { 485 return (cr->cr_sgid); 486 } 487 488 const auditinfo_addr_t * 489 crgetauinfo(const cred_t *cr) 490 { 491 return ((const auditinfo_addr_t *)CR_AUINFO(cr)); 492 } 493 494 auditinfo_addr_t * 495 crgetauinfo_modifiable(cred_t *cr) 496 { 497 return (CR_AUINFO(cr)); 498 } 499 500 zoneid_t 501 crgetzoneid(const cred_t *cr) 502 { 503 return (cr->cr_zone->zone_id); 504 } 505 506 projid_t 507 crgetprojid(const cred_t *cr) 508 { 509 return (cr->cr_projid); 510 } 511 512 #define BADID(x) ((x) != -1 && (unsigned int)(x) > MAXUID) 513 514 int 515 crsetresuid(cred_t *cr, uid_t r, uid_t e, uid_t s) 516 { 517 ASSERT(cr->cr_ref <= 2); 518 519 if (BADID(r) || BADID(e) || BADID(s)) 520 return (-1); 521 522 if (r != -1) 523 cr->cr_ruid = r; 524 if (e != -1) 525 cr->cr_uid = e; 526 if (s != -1) 527 cr->cr_suid = s; 528 529 return (0); 530 } 531 532 int 533 crsetresgid(cred_t *cr, gid_t r, gid_t e, gid_t s) 534 { 535 ASSERT(cr->cr_ref <= 2); 536 537 if (BADID(r) || BADID(e) || BADID(s)) 538 return (-1); 539 540 if (r != -1) 541 cr->cr_rgid = r; 542 if (e != -1) 543 cr->cr_gid = e; 544 if (s != -1) 545 cr->cr_sgid = s; 546 547 return (0); 548 } 549 550 int 551 crsetugid(cred_t *cr, uid_t uid, gid_t gid) 552 { 553 ASSERT(cr->cr_ref <= 2); 554 555 if (uid < 0 || uid > MAXUID || gid < 0 || gid > MAXUID) 556 return (-1); 557 558 cr->cr_uid = cr->cr_ruid = cr->cr_suid = uid; 559 cr->cr_gid = cr->cr_rgid = cr->cr_sgid = gid; 560 561 return (0); 562 } 563 564 int 565 crsetgroups(cred_t *cr, int n, gid_t *grp) 566 { 567 ASSERT(cr->cr_ref <= 2); 568 569 if (n > ngroups_max || n < 0) 570 return (-1); 571 572 cr->cr_ngroups = n; 573 574 if (n > 0) 575 bcopy(grp, cr->cr_groups, n * sizeof (gid_t)); 576 577 return (0); 578 } 579 580 void 581 crsetprojid(cred_t *cr, projid_t projid) 582 { 583 ASSERT(projid >= 0 && projid <= MAXPROJID); 584 cr->cr_projid = projid; 585 } 586 587 /* 588 * This routine returns the pointer to the first element of the cr_groups 589 * array. It can move around in an implementation defined way. 590 */ 591 const gid_t * 592 crgetgroups(const cred_t *cr) 593 { 594 return (cr->cr_groups); 595 } 596 597 int 598 crgetngroups(const cred_t *cr) 599 { 600 return (cr->cr_ngroups); 601 } 602 603 void 604 cred2prcred(const cred_t *cr, prcred_t *pcrp) 605 { 606 pcrp->pr_euid = cr->cr_uid; 607 pcrp->pr_ruid = cr->cr_ruid; 608 pcrp->pr_suid = cr->cr_suid; 609 pcrp->pr_egid = cr->cr_gid; 610 pcrp->pr_rgid = cr->cr_rgid; 611 pcrp->pr_sgid = cr->cr_sgid; 612 pcrp->pr_ngroups = MIN(cr->cr_ngroups, (uint_t)ngroups_max); 613 pcrp->pr_groups[0] = 0; /* in case ngroups == 0 */ 614 615 if (pcrp->pr_ngroups != 0) 616 bcopy(cr->cr_groups, pcrp->pr_groups, 617 sizeof (gid_t) * cr->cr_ngroups); 618 } 619 620 static int 621 cred2ucaud(const cred_t *cr, auditinfo64_addr_t *ainfo) 622 { 623 auditinfo_addr_t *ai; 624 au_tid_addr_t tid; 625 626 if (secpolicy_audit_getattr(CRED()) != 0) 627 return (-1); 628 629 ai = CR_AUINFO(cr); /* caller makes sure this is non-NULL */ 630 tid = ai->ai_termid; 631 632 ainfo->ai_auid = ai->ai_auid; 633 ainfo->ai_mask = ai->ai_mask; 634 ainfo->ai_asid = ai->ai_asid; 635 636 ainfo->ai_termid.at_type = tid.at_type; 637 bcopy(&tid.at_addr, &ainfo->ai_termid.at_addr, 4 * sizeof (uint_t)); 638 639 ainfo->ai_termid.at_port.at_major = (uint32_t)getmajor(tid.at_port); 640 ainfo->ai_termid.at_port.at_minor = (uint32_t)getminor(tid.at_port); 641 642 return (0); 643 } 644 645 /* 646 * Convert a credential into a "ucred". Allow the caller to specify 647 * and aligned buffer, e.g., in an mblk, so we don't have to allocate 648 * memory and copy it twice. 649 */ 650 struct ucred_s * 651 cred2ucred(const cred_t *cr, pid_t pid, void *buf) 652 { 653 struct ucred_s *uc; 654 655 /* The structure isn't always completely filled in, so zero it */ 656 if (buf == NULL) { 657 uc = kmem_zalloc(ucredsize, KM_SLEEP); 658 } else { 659 bzero(buf, ucredsize); 660 uc = buf; 661 } 662 uc->uc_size = ucredsize; 663 uc->uc_credoff = UCRED_CRED_OFF; 664 uc->uc_privoff = UCRED_PRIV_OFF; 665 uc->uc_audoff = UCRED_AUD_OFF; 666 uc->uc_pid = pid; 667 uc->uc_projid = cr->cr_projid; 668 uc->uc_zoneid = crgetzoneid(cr); 669 670 cred2prcred(cr, UCCRED(uc)); 671 cred2prpriv(cr, UCPRIV(uc)); 672 if (audoff == 0 || cred2ucaud(cr, UCAUD(uc)) != 0) 673 uc->uc_audoff = 0; 674 675 return (uc); 676 } 677 678 /* 679 * Get the "ucred" of a process. 680 */ 681 struct ucred_s * 682 pgetucred(proc_t *p) 683 { 684 cred_t *cr; 685 struct ucred_s *uc; 686 687 mutex_enter(&p->p_crlock); 688 cr = p->p_cred; 689 crhold(cr); 690 mutex_exit(&p->p_crlock); 691 692 uc = cred2ucred(cr, p->p_pid, NULL); 693 crfree(cr); 694 695 return (uc); 696 } 697 698 /* 699 * If the reply status is NFSERR_EACCES, it may be because we are 700 * root (no root net access). Check the real uid, if it isn't root 701 * make that the uid instead and retry the call. 702 * Private interface for NFS. 703 */ 704 cred_t * 705 crnetadjust(cred_t *cr) 706 { 707 if (cr->cr_uid == 0 && cr->cr_ruid != 0) { 708 cr = crdup(cr); 709 cr->cr_uid = cr->cr_ruid; 710 return (cr); 711 } 712 return (NULL); 713 } 714 715 /* 716 * The reference count is of interest when you want to check 717 * whether it is ok to modify the credential in place. 718 */ 719 uint_t 720 crgetref(const cred_t *cr) 721 { 722 return (cr->cr_ref); 723 } 724 725 static int 726 get_c2audit_load(void) 727 { 728 static int gotit = 0; 729 static int c2audit_load; 730 u_longlong_t audit_load_val; 731 732 if (gotit) 733 return (c2audit_load); 734 audit_load_val = 0; /* set default value once */ 735 (void) mod_sysvar("c2audit", "audit_load", &audit_load_val); 736 c2audit_load = (int)audit_load_val; 737 gotit++; 738 return (c2audit_load); 739 } 740 741 int 742 get_audit_ucrsize(void) 743 { 744 return (get_c2audit_load() ? sizeof (auditinfo64_addr_t) : 0); 745 } 746 747 /* 748 * Set zone pointer in credential to indicated value. First adds a 749 * hold for the new zone, then drops the hold on previous zone (if any). 750 * This is done in this order in case the old and new zones are the 751 * same. 752 */ 753 void 754 crsetzone(cred_t *cr, zone_t *zptr) 755 { 756 zone_t *oldzptr = cr->cr_zone; 757 758 ASSERT(cr != kcred); 759 ASSERT(cr->cr_ref <= 2); 760 cr->cr_zone = zptr; 761 zone_cred_hold(zptr); 762 if (oldzptr) 763 zone_cred_rele(oldzptr); 764 } 765