xref: /netbsd-src/sys/compat/linux/common/linux_uid16.c (revision 1815fcdd2aa090c36172d54aff2a6d8789fff991)
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