1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
30*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
31*7c478bd9Sstevel@tonic-gate #include <sys/ucred.h>
32*7c478bd9Sstevel@tonic-gate #include <sys/file.h>
33*7c478bd9Sstevel@tonic-gate #include <sys/errno.h>
34*7c478bd9Sstevel@tonic-gate #include <sys/systm.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/stream.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/strsun.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/stropts.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/vfs.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/socket.h>
42*7c478bd9Sstevel@tonic-gate #include <sys/strsubr.h>
43*7c478bd9Sstevel@tonic-gate #include <c2/audit.h>
44*7c478bd9Sstevel@tonic-gate 
45*7c478bd9Sstevel@tonic-gate /*
46*7c478bd9Sstevel@tonic-gate  * Getpeerucred system call implementation.
47*7c478bd9Sstevel@tonic-gate  */
48*7c478bd9Sstevel@tonic-gate static int
49*7c478bd9Sstevel@tonic-gate getpeerucred(int fd, void *buf)
50*7c478bd9Sstevel@tonic-gate {
51*7c478bd9Sstevel@tonic-gate 	file_t *fp;
52*7c478bd9Sstevel@tonic-gate 	struct ucred_s *uc;
53*7c478bd9Sstevel@tonic-gate 	vnode_t *vp;
54*7c478bd9Sstevel@tonic-gate 	k_peercred_t kpc;
55*7c478bd9Sstevel@tonic-gate 	int err;
56*7c478bd9Sstevel@tonic-gate 	int32_t rval;
57*7c478bd9Sstevel@tonic-gate 
58*7c478bd9Sstevel@tonic-gate 	kpc.pc_cr = NULL;
59*7c478bd9Sstevel@tonic-gate 	kpc.pc_cpid = -1;
60*7c478bd9Sstevel@tonic-gate 
61*7c478bd9Sstevel@tonic-gate 	if ((fp = getf(fd)) == NULL)
62*7c478bd9Sstevel@tonic-gate 		return (set_errno(EBADF));
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate 	vp = fp->f_vnode;
65*7c478bd9Sstevel@tonic-gate 
66*7c478bd9Sstevel@tonic-gate 	switch (vp->v_type) {
67*7c478bd9Sstevel@tonic-gate 	case VFIFO:
68*7c478bd9Sstevel@tonic-gate 	case VSOCK:
69*7c478bd9Sstevel@tonic-gate 		err = VOP_IOCTL(vp, _I_GETPEERCRED, (intptr_t)&kpc,
70*7c478bd9Sstevel@tonic-gate 		    FKIOCTL, CRED(), &rval);
71*7c478bd9Sstevel@tonic-gate 		break;
72*7c478bd9Sstevel@tonic-gate 	case VCHR: {
73*7c478bd9Sstevel@tonic-gate 		struct strioctl strioc;
74*7c478bd9Sstevel@tonic-gate 
75*7c478bd9Sstevel@tonic-gate 		if (vp->v_stream == NULL) {
76*7c478bd9Sstevel@tonic-gate 			err = ENOTSUP;
77*7c478bd9Sstevel@tonic-gate 			break;
78*7c478bd9Sstevel@tonic-gate 		}
79*7c478bd9Sstevel@tonic-gate 		strioc.ic_cmd = _I_GETPEERCRED;
80*7c478bd9Sstevel@tonic-gate 		strioc.ic_timout = INFTIM;
81*7c478bd9Sstevel@tonic-gate 		strioc.ic_len = (int)sizeof (k_peercred_t);
82*7c478bd9Sstevel@tonic-gate 		strioc.ic_dp = (char *)&kpc;
83*7c478bd9Sstevel@tonic-gate 
84*7c478bd9Sstevel@tonic-gate 		err = strdoioctl(vp->v_stream, &strioc, FNATIVE|FKIOCTL,
85*7c478bd9Sstevel@tonic-gate 		    STR_NOSIG|K_TO_K, CRED(), &rval);
86*7c478bd9Sstevel@tonic-gate 
87*7c478bd9Sstevel@tonic-gate 		/*
88*7c478bd9Sstevel@tonic-gate 		 * Map all unexpected error codes to ENOTSUP.
89*7c478bd9Sstevel@tonic-gate 		 */
90*7c478bd9Sstevel@tonic-gate 		switch (err) {
91*7c478bd9Sstevel@tonic-gate 		case 0:
92*7c478bd9Sstevel@tonic-gate 		case ENOTSUP:
93*7c478bd9Sstevel@tonic-gate 		case ENOTCONN:
94*7c478bd9Sstevel@tonic-gate 		case ENOMEM:
95*7c478bd9Sstevel@tonic-gate 			break;
96*7c478bd9Sstevel@tonic-gate 		default:
97*7c478bd9Sstevel@tonic-gate 			err = ENOTSUP;
98*7c478bd9Sstevel@tonic-gate 			break;
99*7c478bd9Sstevel@tonic-gate 		}
100*7c478bd9Sstevel@tonic-gate 		break;
101*7c478bd9Sstevel@tonic-gate 	}
102*7c478bd9Sstevel@tonic-gate 	default:
103*7c478bd9Sstevel@tonic-gate 		err = ENOTSUP;
104*7c478bd9Sstevel@tonic-gate 		break;
105*7c478bd9Sstevel@tonic-gate 	}
106*7c478bd9Sstevel@tonic-gate 	releasef(fd);
107*7c478bd9Sstevel@tonic-gate 
108*7c478bd9Sstevel@tonic-gate 	/*
109*7c478bd9Sstevel@tonic-gate 	 * If someone gave us a credential, err will be 0.
110*7c478bd9Sstevel@tonic-gate 	 */
111*7c478bd9Sstevel@tonic-gate 	if (kpc.pc_cr != NULL) {
112*7c478bd9Sstevel@tonic-gate 		ASSERT(err == 0);
113*7c478bd9Sstevel@tonic-gate 
114*7c478bd9Sstevel@tonic-gate 		uc = cred2ucred(kpc.pc_cr, kpc.pc_cpid, NULL);
115*7c478bd9Sstevel@tonic-gate 
116*7c478bd9Sstevel@tonic-gate 		crfree(kpc.pc_cr);
117*7c478bd9Sstevel@tonic-gate 
118*7c478bd9Sstevel@tonic-gate 		err = copyout(uc, buf, uc->uc_size);
119*7c478bd9Sstevel@tonic-gate 
120*7c478bd9Sstevel@tonic-gate 		kmem_free(uc, uc->uc_size);
121*7c478bd9Sstevel@tonic-gate 
122*7c478bd9Sstevel@tonic-gate 		if (err != 0)
123*7c478bd9Sstevel@tonic-gate 			return (set_errno(EFAULT));
124*7c478bd9Sstevel@tonic-gate 
125*7c478bd9Sstevel@tonic-gate 		return (0);
126*7c478bd9Sstevel@tonic-gate 	}
127*7c478bd9Sstevel@tonic-gate 	return (set_errno(err));
128*7c478bd9Sstevel@tonic-gate }
129*7c478bd9Sstevel@tonic-gate 
130*7c478bd9Sstevel@tonic-gate static int
131*7c478bd9Sstevel@tonic-gate ucred_get(pid_t pid, void *ubuf)
132*7c478bd9Sstevel@tonic-gate {
133*7c478bd9Sstevel@tonic-gate 	proc_t *p;
134*7c478bd9Sstevel@tonic-gate 	cred_t *pcr;
135*7c478bd9Sstevel@tonic-gate 	int err;
136*7c478bd9Sstevel@tonic-gate 	struct ucred_s *uc;
137*7c478bd9Sstevel@tonic-gate 
138*7c478bd9Sstevel@tonic-gate 	if (pid == P_MYID || pid == curproc->p_pid) {
139*7c478bd9Sstevel@tonic-gate 		pcr = CRED();
140*7c478bd9Sstevel@tonic-gate 		crhold(pcr);
141*7c478bd9Sstevel@tonic-gate 		pid = curproc->p_pid;
142*7c478bd9Sstevel@tonic-gate 	} else {
143*7c478bd9Sstevel@tonic-gate 		cred_t	*updcred = NULL;
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate 		if (pid < 0)
146*7c478bd9Sstevel@tonic-gate 			return (set_errno(EINVAL));
147*7c478bd9Sstevel@tonic-gate 
148*7c478bd9Sstevel@tonic-gate 		if (audit_active)
149*7c478bd9Sstevel@tonic-gate 			updcred = cralloc();
150*7c478bd9Sstevel@tonic-gate 
151*7c478bd9Sstevel@tonic-gate 		mutex_enter(&pidlock);
152*7c478bd9Sstevel@tonic-gate 		p = prfind(pid);
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate 		if (p == NULL) {
155*7c478bd9Sstevel@tonic-gate 			mutex_exit(&pidlock);
156*7c478bd9Sstevel@tonic-gate 			if (updcred != NULL)
157*7c478bd9Sstevel@tonic-gate 				crfree(updcred);
158*7c478bd9Sstevel@tonic-gate 			return (set_errno(ESRCH));
159*7c478bd9Sstevel@tonic-gate 		}
160*7c478bd9Sstevel@tonic-gate 
161*7c478bd9Sstevel@tonic-gate 		/*
162*7c478bd9Sstevel@tonic-gate 		 * Assure that audit data in cred is up-to-date.
163*7c478bd9Sstevel@tonic-gate 		 * updcred will be used or freed.
164*7c478bd9Sstevel@tonic-gate 		 */
165*7c478bd9Sstevel@tonic-gate 		if (audit_active)
166*7c478bd9Sstevel@tonic-gate 			audit_update_context(p, updcred);
167*7c478bd9Sstevel@tonic-gate 
168*7c478bd9Sstevel@tonic-gate 		err = priv_proc_cred_perm(CRED(), p, &pcr, VREAD);
169*7c478bd9Sstevel@tonic-gate 		mutex_exit(&pidlock);
170*7c478bd9Sstevel@tonic-gate 
171*7c478bd9Sstevel@tonic-gate 		if (err != 0)
172*7c478bd9Sstevel@tonic-gate 			return (set_errno(err));
173*7c478bd9Sstevel@tonic-gate 	}
174*7c478bd9Sstevel@tonic-gate 
175*7c478bd9Sstevel@tonic-gate 	uc = cred2ucred(pcr, pid, NULL);
176*7c478bd9Sstevel@tonic-gate 
177*7c478bd9Sstevel@tonic-gate 	crfree(pcr);
178*7c478bd9Sstevel@tonic-gate 
179*7c478bd9Sstevel@tonic-gate 	err = copyout(uc, ubuf, uc->uc_size);
180*7c478bd9Sstevel@tonic-gate 
181*7c478bd9Sstevel@tonic-gate 	kmem_free(uc, uc->uc_size);
182*7c478bd9Sstevel@tonic-gate 
183*7c478bd9Sstevel@tonic-gate 	if (err)
184*7c478bd9Sstevel@tonic-gate 		return (set_errno(EFAULT));
185*7c478bd9Sstevel@tonic-gate 
186*7c478bd9Sstevel@tonic-gate 	return (0);
187*7c478bd9Sstevel@tonic-gate }
188*7c478bd9Sstevel@tonic-gate 
189*7c478bd9Sstevel@tonic-gate int
190*7c478bd9Sstevel@tonic-gate ucredsys(int code, int obj, void *buf)
191*7c478bd9Sstevel@tonic-gate {
192*7c478bd9Sstevel@tonic-gate 	switch (code) {
193*7c478bd9Sstevel@tonic-gate 	case UCREDSYS_UCREDGET:
194*7c478bd9Sstevel@tonic-gate 		return (ucred_get((pid_t)obj, buf));
195*7c478bd9Sstevel@tonic-gate 	case UCREDSYS_GETPEERUCRED:
196*7c478bd9Sstevel@tonic-gate 		return (getpeerucred(obj, buf));
197*7c478bd9Sstevel@tonic-gate 	default:
198*7c478bd9Sstevel@tonic-gate 		return (set_errno(EINVAL));
199*7c478bd9Sstevel@tonic-gate 	}
200*7c478bd9Sstevel@tonic-gate }
201*7c478bd9Sstevel@tonic-gate 
202*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
203*7c478bd9Sstevel@tonic-gate int
204*7c478bd9Sstevel@tonic-gate ucredsys32(int arg1, int arg2, caddr32_t arg3)
205*7c478bd9Sstevel@tonic-gate {
206*7c478bd9Sstevel@tonic-gate 	return (ucredsys(arg1, arg2, (void *)(uintptr_t)arg3));
207*7c478bd9Sstevel@tonic-gate }
208*7c478bd9Sstevel@tonic-gate #endif
209