1*1815fcddSnjoly /* $NetBSD: linux_uid16.c,v 1.4 2014/05/20 17:31:18 njoly Exp $ */
25cec0f49Snjoly
35cec0f49Snjoly /*-
45cec0f49Snjoly * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc.
55cec0f49Snjoly * All rights reserved.
65cec0f49Snjoly *
75cec0f49Snjoly * This code is derived from software contributed to The NetBSD Foundation
85cec0f49Snjoly * by Frank van der Linden and Eric Haszlakiewicz.
95cec0f49Snjoly *
105cec0f49Snjoly * Redistribution and use in source and binary forms, with or without
115cec0f49Snjoly * modification, are permitted provided that the following conditions
125cec0f49Snjoly * are met:
135cec0f49Snjoly * 1. Redistributions of source code must retain the above copyright
145cec0f49Snjoly * notice, this list of conditions and the following disclaimer.
155cec0f49Snjoly * 2. Redistributions in binary form must reproduce the above copyright
165cec0f49Snjoly * notice, this list of conditions and the following disclaimer in the
175cec0f49Snjoly * documentation and/or other materials provided with the distribution.
185cec0f49Snjoly *
195cec0f49Snjoly * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
205cec0f49Snjoly * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
215cec0f49Snjoly * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
225cec0f49Snjoly * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
235cec0f49Snjoly * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
245cec0f49Snjoly * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
255cec0f49Snjoly * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
265cec0f49Snjoly * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
275cec0f49Snjoly * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
285cec0f49Snjoly * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
295cec0f49Snjoly * POSSIBILITY OF SUCH DAMAGE.
305cec0f49Snjoly */
315cec0f49Snjoly
325cec0f49Snjoly #include <sys/cdefs.h>
33*1815fcddSnjoly __KERNEL_RCSID(0, "$NetBSD: linux_uid16.c,v 1.4 2014/05/20 17:31:18 njoly Exp $");
345cec0f49Snjoly
355cec0f49Snjoly #include <sys/param.h>
365cec0f49Snjoly #include <sys/proc.h>
375cec0f49Snjoly #include <sys/kauth.h>
385cec0f49Snjoly #include <sys/syscallargs.h>
395cec0f49Snjoly
405cec0f49Snjoly #include <compat/linux/common/linux_types.h>
415cec0f49Snjoly #include <compat/linux/common/linux_signal.h>
425cec0f49Snjoly #include <compat/linux/linux_syscallargs.h>
435cec0f49Snjoly
445cec0f49Snjoly #define LINUXTOBSD_UID(u) \
455cec0f49Snjoly (((u) == (linux_uid16_t)-1) ? -1 : (u))
465cec0f49Snjoly #define LINUXTOBSD_GID(g) \
475cec0f49Snjoly (((g) == (linux_gid16_t)-1) ? -1 : (g))
485cec0f49Snjoly
495cec0f49Snjoly #define BSDTOLINUX_UID(u) \
505cec0f49Snjoly (((u) & ~0xffff) ? (linux_uid16_t)65534 : (linux_uid16_t)(u))
515cec0f49Snjoly #define BSDTOLINUX_GID(g) \
525cec0f49Snjoly (((g) & ~0xffff) ? (linux_gid16_t)65534 : (linux_gid16_t)(g))
535cec0f49Snjoly
545cec0f49Snjoly #ifndef COMPAT_LINUX32
555cec0f49Snjoly int
linux_sys_chown16(struct lwp * l,const struct linux_sys_chown16_args * uap,register_t * retval)565cec0f49Snjoly linux_sys_chown16(struct lwp *l, const struct linux_sys_chown16_args *uap, register_t *retval)
575cec0f49Snjoly {
585cec0f49Snjoly /* {
595cec0f49Snjoly syscallarg(const char *) path;
605cec0f49Snjoly syscallarg(linux_uid16_t) uid;
615cec0f49Snjoly syscallarg(linux_gid16_t) gid;
625cec0f49Snjoly } */
635cec0f49Snjoly struct sys___posix_chown_args bca;
645cec0f49Snjoly
655cec0f49Snjoly SCARG(&bca, path) = SCARG(uap, path);
665cec0f49Snjoly SCARG(&bca, uid) = LINUXTOBSD_UID(SCARG(uap, uid));
675cec0f49Snjoly SCARG(&bca, gid) = LINUXTOBSD_GID(SCARG(uap, gid));
685cec0f49Snjoly
695cec0f49Snjoly return sys___posix_chown(l, &bca, retval);
705cec0f49Snjoly }
715cec0f49Snjoly
725cec0f49Snjoly int
linux_sys_fchown16(struct lwp * l,const struct linux_sys_fchown16_args * uap,register_t * retval)735cec0f49Snjoly linux_sys_fchown16(struct lwp *l, const struct linux_sys_fchown16_args *uap, register_t *retval)
745cec0f49Snjoly {
755cec0f49Snjoly /* {
765cec0f49Snjoly syscallarg(int) fd;
775cec0f49Snjoly syscallarg(linux_uid16_t) uid;
785cec0f49Snjoly syscallarg(linux_gid16_t) gid;
795cec0f49Snjoly } */
805cec0f49Snjoly struct sys___posix_fchown_args bfa;
815cec0f49Snjoly
825cec0f49Snjoly SCARG(&bfa, fd) = SCARG(uap, fd);
835cec0f49Snjoly SCARG(&bfa, uid) = LINUXTOBSD_UID(SCARG(uap, uid));
845cec0f49Snjoly SCARG(&bfa, gid) = LINUXTOBSD_GID(SCARG(uap, gid));
855cec0f49Snjoly
865cec0f49Snjoly return sys___posix_fchown(l, &bfa, retval);
875cec0f49Snjoly }
885cec0f49Snjoly
895cec0f49Snjoly int
linux_sys_lchown16(struct lwp * l,const struct linux_sys_lchown16_args * uap,register_t * retval)905cec0f49Snjoly linux_sys_lchown16(struct lwp *l, const struct linux_sys_lchown16_args *uap, register_t *retval)
915cec0f49Snjoly {
925cec0f49Snjoly /* {
935cec0f49Snjoly syscallarg(char *) path;
945cec0f49Snjoly syscallarg(linux_uid16_t) uid;
955cec0f49Snjoly syscallarg(linux_gid16_t) gid;
965cec0f49Snjoly } */
975cec0f49Snjoly struct sys___posix_lchown_args bla;
985cec0f49Snjoly
995cec0f49Snjoly SCARG(&bla, path) = SCARG(uap, path);
1005cec0f49Snjoly SCARG(&bla, uid) = LINUXTOBSD_UID(SCARG(uap, uid));
1015cec0f49Snjoly SCARG(&bla, gid) = LINUXTOBSD_GID(SCARG(uap, gid));
1025cec0f49Snjoly
1035cec0f49Snjoly return sys___posix_lchown(l, &bla, retval);
1045cec0f49Snjoly }
1055cec0f49Snjoly
1065cec0f49Snjoly int
linux_sys_setreuid16(struct lwp * l,const struct linux_sys_setreuid16_args * uap,register_t * retval)1075cec0f49Snjoly linux_sys_setreuid16(struct lwp *l, const struct linux_sys_setreuid16_args *uap, register_t *retval)
1085cec0f49Snjoly {
1095cec0f49Snjoly /* {
1105cec0f49Snjoly syscallarg(linux_uid16_t) ruid;
1115cec0f49Snjoly syscallarg(linux_uid16_t) euid;
1125cec0f49Snjoly } */
1135cec0f49Snjoly struct sys_setreuid_args bsa;
1145cec0f49Snjoly
1155cec0f49Snjoly SCARG(&bsa, ruid) = LINUXTOBSD_UID(SCARG(uap, ruid));
1165cec0f49Snjoly SCARG(&bsa, euid) = LINUXTOBSD_UID(SCARG(uap, euid));
1175cec0f49Snjoly
1185cec0f49Snjoly return sys_setreuid(l, &bsa, retval);
1195cec0f49Snjoly }
1205cec0f49Snjoly
1215cec0f49Snjoly int
linux_sys_setregid16(struct lwp * l,const struct linux_sys_setregid16_args * uap,register_t * retval)1225cec0f49Snjoly linux_sys_setregid16(struct lwp *l, const struct linux_sys_setregid16_args *uap, register_t *retval)
1235cec0f49Snjoly {
1245cec0f49Snjoly /* {
1255cec0f49Snjoly syscallarg(linux_gid16_t) rgid;
1265cec0f49Snjoly syscallarg(linux_gid16_t) egid;
1275cec0f49Snjoly } */
1285cec0f49Snjoly struct sys_setregid_args bsa;
1295cec0f49Snjoly
1305cec0f49Snjoly SCARG(&bsa, rgid) = LINUXTOBSD_GID(SCARG(uap, rgid));
1315cec0f49Snjoly SCARG(&bsa, egid) = LINUXTOBSD_GID(SCARG(uap, egid));
1325cec0f49Snjoly
1335cec0f49Snjoly return sys_setregid(l, &bsa, retval);
1345cec0f49Snjoly }
1355cec0f49Snjoly
1365cec0f49Snjoly int
linux_sys_setresuid16(struct lwp * l,const struct linux_sys_setresuid16_args * uap,register_t * retval)1375cec0f49Snjoly linux_sys_setresuid16(struct lwp *l, const struct linux_sys_setresuid16_args *uap, register_t *retval)
1385cec0f49Snjoly {
1395cec0f49Snjoly /* {
1405cec0f49Snjoly syscallarg(linux_uid16_t) ruid;
1415cec0f49Snjoly syscallarg(linux_uid16_t) euid;
1425cec0f49Snjoly syscallarg(linux_uid16_t) suid;
1435cec0f49Snjoly } */
1445cec0f49Snjoly struct linux_sys_setresuid_args lsa;
1455cec0f49Snjoly
1465cec0f49Snjoly SCARG(&lsa, ruid) = LINUXTOBSD_UID(SCARG(uap, ruid));
1475cec0f49Snjoly SCARG(&lsa, euid) = LINUXTOBSD_UID(SCARG(uap, euid));
1485cec0f49Snjoly SCARG(&lsa, suid) = LINUXTOBSD_UID(SCARG(uap, suid));
1495cec0f49Snjoly
1505cec0f49Snjoly return linux_sys_setresuid(l, &lsa, retval);
1515cec0f49Snjoly }
1525cec0f49Snjoly
1535cec0f49Snjoly int
linux_sys_setresgid16(struct lwp * l,const struct linux_sys_setresgid16_args * uap,register_t * retval)1545cec0f49Snjoly linux_sys_setresgid16(struct lwp *l, const struct linux_sys_setresgid16_args *uap, register_t *retval)
1555cec0f49Snjoly {
1565cec0f49Snjoly /* {
1575cec0f49Snjoly syscallarg(linux_gid16_t) rgid;
1585cec0f49Snjoly syscallarg(linux_gid16_t) egid;
1595cec0f49Snjoly syscallarg(linux_gid16_t) sgid;
1605cec0f49Snjoly } */
1615cec0f49Snjoly struct linux_sys_setresgid_args lsa;
1625cec0f49Snjoly
1635cec0f49Snjoly SCARG(&lsa, rgid) = LINUXTOBSD_GID(SCARG(uap, rgid));
1645cec0f49Snjoly SCARG(&lsa, egid) = LINUXTOBSD_GID(SCARG(uap, egid));
1655cec0f49Snjoly SCARG(&lsa, sgid) = LINUXTOBSD_GID(SCARG(uap, sgid));
1665cec0f49Snjoly
1675cec0f49Snjoly return linux_sys_setresgid(l, &lsa, retval);
1685cec0f49Snjoly }
1695cec0f49Snjoly
1705cec0f49Snjoly int
linux_sys_getresuid16(struct lwp * l,const struct linux_sys_getresuid16_args * uap,register_t * retval)1715cec0f49Snjoly linux_sys_getresuid16(struct lwp *l, const struct linux_sys_getresuid16_args *uap, register_t *retval)
1725cec0f49Snjoly {
1735cec0f49Snjoly /* {
174763d4d36Snjoly syscallarg(linux_uid16_t *) ruid;
175763d4d36Snjoly syscallarg(linux_uid16_t *) euid;
176763d4d36Snjoly syscallarg(linux_uid16_t *) suid;
1775cec0f49Snjoly } */
1785cec0f49Snjoly kauth_cred_t pc = l->l_cred;
1795cec0f49Snjoly int error;
1805cec0f49Snjoly uid_t buid;
1815cec0f49Snjoly linux_uid16_t luid;
1825cec0f49Snjoly
1835cec0f49Snjoly buid = kauth_cred_getuid(pc);
1845cec0f49Snjoly luid = BSDTOLINUX_UID(buid);
1855cec0f49Snjoly if ((error = copyout(&luid, SCARG(uap, ruid), sizeof(luid))) != 0)
1865cec0f49Snjoly return error;
1875cec0f49Snjoly
1885cec0f49Snjoly buid = kauth_cred_geteuid(pc);
1895cec0f49Snjoly luid = BSDTOLINUX_UID(buid);
1905cec0f49Snjoly if ((error = copyout(&luid, SCARG(uap, euid), sizeof(luid))) != 0)
1915cec0f49Snjoly return error;
1925cec0f49Snjoly
1935cec0f49Snjoly buid = kauth_cred_getsvuid(pc);
1945cec0f49Snjoly luid = BSDTOLINUX_UID(buid);
1955cec0f49Snjoly return (copyout(&luid, SCARG(uap, suid), sizeof(luid)));
1965cec0f49Snjoly }
1975cec0f49Snjoly
1985cec0f49Snjoly int
linux_sys_getresgid16(struct lwp * l,const struct linux_sys_getresgid16_args * uap,register_t * retval)1995cec0f49Snjoly linux_sys_getresgid16(struct lwp *l, const struct linux_sys_getresgid16_args *uap, register_t *retval)
2005cec0f49Snjoly {
2015cec0f49Snjoly /* {
202763d4d36Snjoly syscallarg(linux_gid16_t *) rgid;
203763d4d36Snjoly syscallarg(linux_gid16_t *) egid;
204763d4d36Snjoly syscallarg(linux_gid16_t *) sgid;
2055cec0f49Snjoly } */
2065cec0f49Snjoly kauth_cred_t pc = l->l_cred;
2075cec0f49Snjoly int error;
2085cec0f49Snjoly gid_t bgid;
2095cec0f49Snjoly linux_gid16_t lgid;
2105cec0f49Snjoly
2115cec0f49Snjoly bgid = kauth_cred_getgid(pc);
2125cec0f49Snjoly lgid = BSDTOLINUX_GID(bgid);
2135cec0f49Snjoly if ((error = copyout(&lgid, SCARG(uap, rgid), sizeof(lgid))) != 0)
2145cec0f49Snjoly return error;
2155cec0f49Snjoly
2165cec0f49Snjoly bgid = kauth_cred_getegid(pc);
2175cec0f49Snjoly lgid = BSDTOLINUX_GID(bgid);
2185cec0f49Snjoly if ((error = copyout(&lgid, SCARG(uap, egid), sizeof(lgid))) != 0)
2195cec0f49Snjoly return error;
2205cec0f49Snjoly
2215cec0f49Snjoly bgid = kauth_cred_getsvgid(pc);
2225cec0f49Snjoly lgid = BSDTOLINUX_GID(bgid);
2235cec0f49Snjoly return (copyout(&lgid, SCARG(uap, sgid), sizeof(lgid)));
2245cec0f49Snjoly }
2255cec0f49Snjoly #endif /* !COMPAT_LINUX32 */
2265cec0f49Snjoly
2275cec0f49Snjoly int
linux_sys_getgroups16(struct lwp * l,const struct linux_sys_getgroups16_args * uap,register_t * retval)2285cec0f49Snjoly linux_sys_getgroups16(struct lwp *l, const struct linux_sys_getgroups16_args *uap, register_t *retval)
2295cec0f49Snjoly {
2305cec0f49Snjoly /* {
2315cec0f49Snjoly syscallarg(int) gidsetsize;
2325cec0f49Snjoly syscallarg(linux_gid16_t *) gidset;
2335cec0f49Snjoly } */
2345cec0f49Snjoly linux_gid16_t lset[16];
2355cec0f49Snjoly linux_gid16_t *gidset;
2365cec0f49Snjoly unsigned int ngrps;
2375cec0f49Snjoly int i, n, j;
2385cec0f49Snjoly int error;
2395cec0f49Snjoly
2405cec0f49Snjoly ngrps = kauth_cred_ngroups(l->l_cred);
2415cec0f49Snjoly *retval = ngrps;
2425cec0f49Snjoly if (SCARG(uap, gidsetsize) == 0)
2435cec0f49Snjoly return 0;
244*1815fcddSnjoly if (SCARG(uap, gidsetsize) < (int)ngrps)
2455cec0f49Snjoly return EINVAL;
2465cec0f49Snjoly
2475cec0f49Snjoly gidset = SCARG(uap, gidset);
2485cec0f49Snjoly for (i = 0; i < (n = ngrps); i += n, gidset += n) {
2495cec0f49Snjoly n -= i;
2505cec0f49Snjoly if (n > __arraycount(lset))
2515cec0f49Snjoly n = __arraycount(lset);
2525cec0f49Snjoly for (j = 0; j < n; j++)
2535cec0f49Snjoly lset[j] = kauth_cred_group(l->l_cred, i + j);
2545cec0f49Snjoly error = copyout(lset, gidset, n * sizeof(lset[0]));
2555cec0f49Snjoly if (error != 0)
2565cec0f49Snjoly return error;
2575cec0f49Snjoly }
2585cec0f49Snjoly
2595cec0f49Snjoly return 0;
2605cec0f49Snjoly }
2615cec0f49Snjoly
2625cec0f49Snjoly /*
2635cec0f49Snjoly * It is very unlikly that any problem using 16bit groups is written
2645cec0f49Snjoly * to allow for more than 16 of them, so don't bother trying to
2655cec0f49Snjoly * support that.
2665cec0f49Snjoly */
2675cec0f49Snjoly #define COMPAT_NGROUPS16 16
2685cec0f49Snjoly
2695cec0f49Snjoly int
linux_sys_setgroups16(struct lwp * l,const struct linux_sys_setgroups16_args * uap,register_t * retval)2705cec0f49Snjoly linux_sys_setgroups16(struct lwp *l, const struct linux_sys_setgroups16_args *uap, register_t *retval)
2715cec0f49Snjoly {
2725cec0f49Snjoly /* {
2735cec0f49Snjoly syscallarg(int) gidsetsize;
2745cec0f49Snjoly syscallarg(linux_gid16_t *) gidset;
2755cec0f49Snjoly } */
2765cec0f49Snjoly linux_gid16_t lset[COMPAT_NGROUPS16];
2775cec0f49Snjoly kauth_cred_t ncred;
2785cec0f49Snjoly int error;
2795cec0f49Snjoly gid_t grbuf[COMPAT_NGROUPS16];
2805cec0f49Snjoly unsigned int i, ngroups = SCARG(uap, gidsetsize);
2815cec0f49Snjoly
2825cec0f49Snjoly if (ngroups > COMPAT_NGROUPS16)
2835cec0f49Snjoly return EINVAL;
2845cec0f49Snjoly error = copyin(SCARG(uap, gidset), lset, ngroups);
2855cec0f49Snjoly if (error != 0)
2865cec0f49Snjoly return error;
2875cec0f49Snjoly
2885cec0f49Snjoly for (i = 0; i < ngroups; i++)
2895cec0f49Snjoly grbuf[i] = lset[i];
2905cec0f49Snjoly
2915cec0f49Snjoly ncred = kauth_cred_alloc();
2925cec0f49Snjoly error = kauth_cred_setgroups(ncred, grbuf, SCARG(uap, gidsetsize),
2935cec0f49Snjoly -1, UIO_SYSSPACE);
2945cec0f49Snjoly if (error != 0) {
2955cec0f49Snjoly kauth_cred_free(ncred);
2965cec0f49Snjoly return error;
2975cec0f49Snjoly }
2985cec0f49Snjoly
2995cec0f49Snjoly return kauth_proc_setgroups(l, ncred);
3005cec0f49Snjoly }
301