xref: /titanic_41/usr/src/uts/common/os/cred.c (revision 56e2cc86321ec889bf83a888d902c60d6fb2ef8d)
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