1 /* $NetBSD: linux_uid16.c,v 1.1 2008/01/15 22:38:35 njoly Exp $ */ 2 3 /*- 4 * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Frank van der Linden and Eric Haszlakiewicz. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <sys/cdefs.h> 40 __KERNEL_RCSID(0, "$NetBSD: linux_uid16.c,v 1.1 2008/01/15 22:38:35 njoly Exp $"); 41 42 #include <sys/param.h> 43 #include <sys/proc.h> 44 #include <sys/kauth.h> 45 #include <sys/syscallargs.h> 46 47 #include <compat/linux/common/linux_types.h> 48 #include <compat/linux/common/linux_signal.h> 49 #include <compat/linux/linux_syscallargs.h> 50 51 #define LINUXTOBSD_UID(u) \ 52 (((u) == (linux_uid16_t)-1) ? -1 : (u)) 53 #define LINUXTOBSD_GID(g) \ 54 (((g) == (linux_gid16_t)-1) ? -1 : (g)) 55 56 #define BSDTOLINUX_UID(u) \ 57 (((u) & ~0xffff) ? (linux_uid16_t)65534 : (linux_uid16_t)(u)) 58 #define BSDTOLINUX_GID(g) \ 59 (((g) & ~0xffff) ? (linux_gid16_t)65534 : (linux_gid16_t)(g)) 60 61 #ifndef COMPAT_LINUX32 62 int 63 linux_sys_chown16(struct lwp *l, const struct linux_sys_chown16_args *uap, register_t *retval) 64 { 65 /* { 66 syscallarg(const char *) path; 67 syscallarg(linux_uid16_t) uid; 68 syscallarg(linux_gid16_t) gid; 69 } */ 70 struct sys___posix_chown_args bca; 71 72 SCARG(&bca, path) = SCARG(uap, path); 73 SCARG(&bca, uid) = LINUXTOBSD_UID(SCARG(uap, uid)); 74 SCARG(&bca, gid) = LINUXTOBSD_GID(SCARG(uap, gid)); 75 76 return sys___posix_chown(l, &bca, retval); 77 } 78 79 int 80 linux_sys_fchown16(struct lwp *l, const struct linux_sys_fchown16_args *uap, register_t *retval) 81 { 82 /* { 83 syscallarg(int) fd; 84 syscallarg(linux_uid16_t) uid; 85 syscallarg(linux_gid16_t) gid; 86 } */ 87 struct sys___posix_fchown_args bfa; 88 89 SCARG(&bfa, fd) = SCARG(uap, fd); 90 SCARG(&bfa, uid) = LINUXTOBSD_UID(SCARG(uap, uid)); 91 SCARG(&bfa, gid) = LINUXTOBSD_GID(SCARG(uap, gid)); 92 93 return sys___posix_fchown(l, &bfa, retval); 94 } 95 96 int 97 linux_sys_lchown16(struct lwp *l, const struct linux_sys_lchown16_args *uap, register_t *retval) 98 { 99 /* { 100 syscallarg(char *) path; 101 syscallarg(linux_uid16_t) uid; 102 syscallarg(linux_gid16_t) gid; 103 } */ 104 struct sys___posix_lchown_args bla; 105 106 SCARG(&bla, path) = SCARG(uap, path); 107 SCARG(&bla, uid) = LINUXTOBSD_UID(SCARG(uap, uid)); 108 SCARG(&bla, gid) = LINUXTOBSD_GID(SCARG(uap, gid)); 109 110 return sys___posix_lchown(l, &bla, retval); 111 } 112 113 int 114 linux_sys_setreuid16(struct lwp *l, const struct linux_sys_setreuid16_args *uap, register_t *retval) 115 { 116 /* { 117 syscallarg(linux_uid16_t) ruid; 118 syscallarg(linux_uid16_t) euid; 119 } */ 120 struct sys_setreuid_args bsa; 121 122 SCARG(&bsa, ruid) = LINUXTOBSD_UID(SCARG(uap, ruid)); 123 SCARG(&bsa, euid) = LINUXTOBSD_UID(SCARG(uap, euid)); 124 125 return sys_setreuid(l, &bsa, retval); 126 } 127 128 int 129 linux_sys_setregid16(struct lwp *l, const struct linux_sys_setregid16_args *uap, register_t *retval) 130 { 131 /* { 132 syscallarg(linux_gid16_t) rgid; 133 syscallarg(linux_gid16_t) egid; 134 } */ 135 struct sys_setregid_args bsa; 136 137 SCARG(&bsa, rgid) = LINUXTOBSD_GID(SCARG(uap, rgid)); 138 SCARG(&bsa, egid) = LINUXTOBSD_GID(SCARG(uap, egid)); 139 140 return sys_setregid(l, &bsa, retval); 141 } 142 143 int 144 linux_sys_setresuid16(struct lwp *l, const struct linux_sys_setresuid16_args *uap, register_t *retval) 145 { 146 /* { 147 syscallarg(linux_uid16_t) ruid; 148 syscallarg(linux_uid16_t) euid; 149 syscallarg(linux_uid16_t) suid; 150 } */ 151 struct linux_sys_setresuid_args lsa; 152 153 SCARG(&lsa, ruid) = LINUXTOBSD_UID(SCARG(uap, ruid)); 154 SCARG(&lsa, euid) = LINUXTOBSD_UID(SCARG(uap, euid)); 155 SCARG(&lsa, suid) = LINUXTOBSD_UID(SCARG(uap, suid)); 156 157 return linux_sys_setresuid(l, &lsa, retval); 158 } 159 160 int 161 linux_sys_setresgid16(struct lwp *l, const struct linux_sys_setresgid16_args *uap, register_t *retval) 162 { 163 /* { 164 syscallarg(linux_gid16_t) rgid; 165 syscallarg(linux_gid16_t) egid; 166 syscallarg(linux_gid16_t) sgid; 167 } */ 168 struct linux_sys_setresgid_args lsa; 169 170 SCARG(&lsa, rgid) = LINUXTOBSD_GID(SCARG(uap, rgid)); 171 SCARG(&lsa, egid) = LINUXTOBSD_GID(SCARG(uap, egid)); 172 SCARG(&lsa, sgid) = LINUXTOBSD_GID(SCARG(uap, sgid)); 173 174 return linux_sys_setresgid(l, &lsa, retval); 175 } 176 177 int 178 linux_sys_getresuid16(struct lwp *l, const struct linux_sys_getresuid16_args *uap, register_t *retval) 179 { 180 /* { 181 syscallarg(linux_uid16_t) ruid; 182 syscallarg(linux_uid16_t) euid; 183 syscallarg(linux_uid16_t) suid; 184 } */ 185 kauth_cred_t pc = l->l_cred; 186 int error; 187 uid_t buid; 188 linux_uid16_t luid; 189 190 buid = kauth_cred_getuid(pc); 191 luid = BSDTOLINUX_UID(buid); 192 if ((error = copyout(&luid, SCARG(uap, ruid), sizeof(luid))) != 0) 193 return error; 194 195 buid = kauth_cred_geteuid(pc); 196 luid = BSDTOLINUX_UID(buid); 197 if ((error = copyout(&luid, SCARG(uap, euid), sizeof(luid))) != 0) 198 return error; 199 200 buid = kauth_cred_getsvuid(pc); 201 luid = BSDTOLINUX_UID(buid); 202 return (copyout(&luid, SCARG(uap, suid), sizeof(luid))); 203 } 204 205 int 206 linux_sys_getresgid16(struct lwp *l, const struct linux_sys_getresgid16_args *uap, register_t *retval) 207 { 208 /* { 209 syscallarg(linux_gid16_t) rgid; 210 syscallarg(linux_gid16_t) egid; 211 syscallarg(linux_gid16_t) sgid; 212 } */ 213 kauth_cred_t pc = l->l_cred; 214 int error; 215 gid_t bgid; 216 linux_gid16_t lgid; 217 218 bgid = kauth_cred_getgid(pc); 219 lgid = BSDTOLINUX_GID(bgid); 220 if ((error = copyout(&lgid, SCARG(uap, rgid), sizeof(lgid))) != 0) 221 return error; 222 223 bgid = kauth_cred_getegid(pc); 224 lgid = BSDTOLINUX_GID(bgid); 225 if ((error = copyout(&lgid, SCARG(uap, egid), sizeof(lgid))) != 0) 226 return error; 227 228 bgid = kauth_cred_getsvgid(pc); 229 lgid = BSDTOLINUX_GID(bgid); 230 return (copyout(&lgid, SCARG(uap, sgid), sizeof(lgid))); 231 } 232 #endif /* !COMPAT_LINUX32 */ 233 234 int 235 linux_sys_getgroups16(struct lwp *l, const struct linux_sys_getgroups16_args *uap, register_t *retval) 236 { 237 /* { 238 syscallarg(int) gidsetsize; 239 syscallarg(linux_gid16_t *) gidset; 240 } */ 241 linux_gid16_t lset[16]; 242 linux_gid16_t *gidset; 243 unsigned int ngrps; 244 int i, n, j; 245 int error; 246 247 ngrps = kauth_cred_ngroups(l->l_cred); 248 *retval = ngrps; 249 if (SCARG(uap, gidsetsize) == 0) 250 return 0; 251 if (SCARG(uap, gidsetsize) < ngrps) 252 return EINVAL; 253 254 gidset = SCARG(uap, gidset); 255 for (i = 0; i < (n = ngrps); i += n, gidset += n) { 256 n -= i; 257 if (n > __arraycount(lset)) 258 n = __arraycount(lset); 259 for (j = 0; j < n; j++) 260 lset[j] = kauth_cred_group(l->l_cred, i + j); 261 error = copyout(lset, gidset, n * sizeof(lset[0])); 262 if (error != 0) 263 return error; 264 } 265 266 return 0; 267 } 268 269 /* 270 * It is very unlikly that any problem using 16bit groups is written 271 * to allow for more than 16 of them, so don't bother trying to 272 * support that. 273 */ 274 #define COMPAT_NGROUPS16 16 275 276 int 277 linux_sys_setgroups16(struct lwp *l, const struct linux_sys_setgroups16_args *uap, register_t *retval) 278 { 279 /* { 280 syscallarg(int) gidsetsize; 281 syscallarg(linux_gid16_t *) gidset; 282 } */ 283 linux_gid16_t lset[COMPAT_NGROUPS16]; 284 kauth_cred_t ncred; 285 int error; 286 gid_t grbuf[COMPAT_NGROUPS16]; 287 unsigned int i, ngroups = SCARG(uap, gidsetsize); 288 289 if (ngroups > COMPAT_NGROUPS16) 290 return EINVAL; 291 error = copyin(SCARG(uap, gidset), lset, ngroups); 292 if (error != 0) 293 return error; 294 295 for (i = 0; i < ngroups; i++) 296 grbuf[i] = lset[i]; 297 298 ncred = kauth_cred_alloc(); 299 error = kauth_cred_setgroups(ncred, grbuf, SCARG(uap, gidsetsize), 300 -1, UIO_SYSSPACE); 301 if (error != 0) { 302 kauth_cred_free(ncred); 303 return error; 304 } 305 306 return kauth_proc_setgroups(l, ncred); 307 } 308