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