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 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/param.h> 30 #include <sys/types.h> 31 #include <sys/ucred.h> 32 #include <sys/file.h> 33 #include <sys/errno.h> 34 #include <sys/systm.h> 35 #include <sys/stream.h> 36 #include <sys/strsun.h> 37 #include <sys/stropts.h> 38 #include <sys/vfs.h> 39 #include <sys/vnode.h> 40 #include <sys/cmn_err.h> 41 #include <sys/socket.h> 42 #include <sys/strsubr.h> 43 #include <c2/audit.h> 44 45 /* 46 * Getpeerucred system call implementation. 47 */ 48 static int 49 getpeerucred(int fd, void *buf) 50 { 51 file_t *fp; 52 struct ucred_s *uc; 53 vnode_t *vp; 54 k_peercred_t kpc; 55 int err; 56 int32_t rval; 57 58 kpc.pc_cr = NULL; 59 kpc.pc_cpid = -1; 60 61 if ((fp = getf(fd)) == NULL) 62 return (set_errno(EBADF)); 63 64 vp = fp->f_vnode; 65 66 switch (vp->v_type) { 67 case VFIFO: 68 case VSOCK: 69 err = VOP_IOCTL(vp, _I_GETPEERCRED, (intptr_t)&kpc, 70 FKIOCTL, CRED(), &rval); 71 break; 72 case VCHR: { 73 struct strioctl strioc; 74 75 if (vp->v_stream == NULL) { 76 err = ENOTSUP; 77 break; 78 } 79 strioc.ic_cmd = _I_GETPEERCRED; 80 strioc.ic_timout = INFTIM; 81 strioc.ic_len = (int)sizeof (k_peercred_t); 82 strioc.ic_dp = (char *)&kpc; 83 84 err = strdoioctl(vp->v_stream, &strioc, FNATIVE|FKIOCTL, 85 STR_NOSIG|K_TO_K, CRED(), &rval); 86 87 /* 88 * Map all unexpected error codes to ENOTSUP. 89 */ 90 switch (err) { 91 case 0: 92 case ENOTSUP: 93 case ENOTCONN: 94 case ENOMEM: 95 break; 96 default: 97 err = ENOTSUP; 98 break; 99 } 100 break; 101 } 102 default: 103 err = ENOTSUP; 104 break; 105 } 106 releasef(fd); 107 108 /* 109 * If someone gave us a credential, err will be 0. 110 */ 111 if (kpc.pc_cr != NULL) { 112 ASSERT(err == 0); 113 114 uc = cred2ucred(kpc.pc_cr, kpc.pc_cpid, NULL); 115 116 crfree(kpc.pc_cr); 117 118 err = copyout(uc, buf, uc->uc_size); 119 120 kmem_free(uc, uc->uc_size); 121 122 if (err != 0) 123 return (set_errno(EFAULT)); 124 125 return (0); 126 } 127 return (set_errno(err)); 128 } 129 130 static int 131 ucred_get(pid_t pid, void *ubuf) 132 { 133 proc_t *p; 134 cred_t *pcr; 135 int err; 136 struct ucred_s *uc; 137 138 if (pid == P_MYID || pid == curproc->p_pid) { 139 pcr = CRED(); 140 crhold(pcr); 141 pid = curproc->p_pid; 142 } else { 143 cred_t *updcred = NULL; 144 145 if (pid < 0) 146 return (set_errno(EINVAL)); 147 148 if (audit_active) 149 updcred = cralloc(); 150 151 mutex_enter(&pidlock); 152 p = prfind(pid); 153 154 if (p == NULL) { 155 mutex_exit(&pidlock); 156 if (updcred != NULL) 157 crfree(updcred); 158 return (set_errno(ESRCH)); 159 } 160 161 /* 162 * Assure that audit data in cred is up-to-date. 163 * updcred will be used or freed. 164 */ 165 if (audit_active) 166 audit_update_context(p, updcred); 167 168 err = priv_proc_cred_perm(CRED(), p, &pcr, VREAD); 169 mutex_exit(&pidlock); 170 171 if (err != 0) 172 return (set_errno(err)); 173 } 174 175 uc = cred2ucred(pcr, pid, NULL); 176 177 crfree(pcr); 178 179 err = copyout(uc, ubuf, uc->uc_size); 180 181 kmem_free(uc, uc->uc_size); 182 183 if (err) 184 return (set_errno(EFAULT)); 185 186 return (0); 187 } 188 189 int 190 ucredsys(int code, int obj, void *buf) 191 { 192 switch (code) { 193 case UCREDSYS_UCREDGET: 194 return (ucred_get((pid_t)obj, buf)); 195 case UCREDSYS_GETPEERUCRED: 196 return (getpeerucred(obj, buf)); 197 default: 198 return (set_errno(EINVAL)); 199 } 200 } 201 202 #ifdef _SYSCALL32_IMPL 203 int 204 ucredsys32(int arg1, int arg2, caddr32_t arg3) 205 { 206 return (ucredsys(arg1, arg2, (void *)(uintptr_t)arg3)); 207 } 208 #endif 209