xref: /titanic_44/usr/src/uts/common/os/cred.c (revision 116f76291c541446e47b233d739d94b4a7c675c2)
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