xref: /openbmc/linux/kernel/uid16.c (revision 55731b3c)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  *	Wrapper functions for 16bit uid back compatibility. All nicely tied
41da177e4SLinus Torvalds  *	together in the faint hope we can take the out in five years time.
51da177e4SLinus Torvalds  */
61da177e4SLinus Torvalds 
71da177e4SLinus Torvalds #include <linux/mm.h>
81da177e4SLinus Torvalds #include <linux/mman.h>
91da177e4SLinus Torvalds #include <linux/notifier.h>
101da177e4SLinus Torvalds #include <linux/reboot.h>
111da177e4SLinus Torvalds #include <linux/prctl.h>
12c59ede7bSRandy.Dunlap #include <linux/capability.h>
131da177e4SLinus Torvalds #include <linux/init.h>
141da177e4SLinus Torvalds #include <linux/highuid.h>
151da177e4SLinus Torvalds #include <linux/security.h>
165b825c3aSIngo Molnar #include <linux/cred.h>
171da177e4SLinus Torvalds #include <linux/syscalls.h>
181da177e4SLinus Torvalds 
197c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
201da177e4SLinus Torvalds 
21e530dca5SDominik Brodowski #include "uid16.h"
22e530dca5SDominik Brodowski 
SYSCALL_DEFINE3(chown16,const char __user *,filename,old_uid_t,user,old_gid_t,group)23ca013e94SHeiko Carstens SYSCALL_DEFINE3(chown16, const char __user *, filename, old_uid_t, user, old_gid_t, group)
241da177e4SLinus Torvalds {
2555731b3cSDominik Brodowski 	return ksys_chown(filename, low2highuid(user), low2highgid(group));
261da177e4SLinus Torvalds }
271da177e4SLinus Torvalds 
SYSCALL_DEFINE3(lchown16,const char __user *,filename,old_uid_t,user,old_gid_t,group)28ca013e94SHeiko Carstens SYSCALL_DEFINE3(lchown16, const char __user *, filename, old_uid_t, user, old_gid_t, group)
291da177e4SLinus Torvalds {
3055731b3cSDominik Brodowski 	return ksys_lchown(filename, low2highuid(user), low2highgid(group));
311da177e4SLinus Torvalds }
321da177e4SLinus Torvalds 
SYSCALL_DEFINE3(fchown16,unsigned int,fd,old_uid_t,user,old_gid_t,group)33ca013e94SHeiko Carstens SYSCALL_DEFINE3(fchown16, unsigned int, fd, old_uid_t, user, old_gid_t, group)
341da177e4SLinus Torvalds {
3555731b3cSDominik Brodowski 	return ksys_fchown(fd, low2highuid(user), low2highgid(group));
361da177e4SLinus Torvalds }
371da177e4SLinus Torvalds 
SYSCALL_DEFINE2(setregid16,old_gid_t,rgid,old_gid_t,egid)38a6b42e83SHeiko Carstens SYSCALL_DEFINE2(setregid16, old_gid_t, rgid, old_gid_t, egid)
391da177e4SLinus Torvalds {
40e530dca5SDominik Brodowski 	return __sys_setregid(low2highgid(rgid), low2highgid(egid));
411da177e4SLinus Torvalds }
421da177e4SLinus Torvalds 
SYSCALL_DEFINE1(setgid16,old_gid_t,gid)43a6b42e83SHeiko Carstens SYSCALL_DEFINE1(setgid16, old_gid_t, gid)
441da177e4SLinus Torvalds {
45e530dca5SDominik Brodowski 	return __sys_setgid(low2highgid(gid));
461da177e4SLinus Torvalds }
471da177e4SLinus Torvalds 
SYSCALL_DEFINE2(setreuid16,old_uid_t,ruid,old_uid_t,euid)48a6b42e83SHeiko Carstens SYSCALL_DEFINE2(setreuid16, old_uid_t, ruid, old_uid_t, euid)
491da177e4SLinus Torvalds {
50e530dca5SDominik Brodowski 	return __sys_setreuid(low2highuid(ruid), low2highuid(euid));
511da177e4SLinus Torvalds }
521da177e4SLinus Torvalds 
SYSCALL_DEFINE1(setuid16,old_uid_t,uid)53a6b42e83SHeiko Carstens SYSCALL_DEFINE1(setuid16, old_uid_t, uid)
541da177e4SLinus Torvalds {
55e530dca5SDominik Brodowski 	return __sys_setuid(low2highuid(uid));
561da177e4SLinus Torvalds }
571da177e4SLinus Torvalds 
SYSCALL_DEFINE3(setresuid16,old_uid_t,ruid,old_uid_t,euid,old_uid_t,suid)58a6b42e83SHeiko Carstens SYSCALL_DEFINE3(setresuid16, old_uid_t, ruid, old_uid_t, euid, old_uid_t, suid)
591da177e4SLinus Torvalds {
60e530dca5SDominik Brodowski 	return __sys_setresuid(low2highuid(ruid), low2highuid(euid),
611da177e4SLinus Torvalds 				 low2highuid(suid));
621da177e4SLinus Torvalds }
631da177e4SLinus Torvalds 
SYSCALL_DEFINE3(getresuid16,old_uid_t __user *,ruidp,old_uid_t __user *,euidp,old_uid_t __user *,suidp)64a29c33f4SEric W. Biederman SYSCALL_DEFINE3(getresuid16, old_uid_t __user *, ruidp, old_uid_t __user *, euidp, old_uid_t __user *, suidp)
651da177e4SLinus Torvalds {
6686a264abSDavid Howells 	const struct cred *cred = current_cred();
671da177e4SLinus Torvalds 	int retval;
68a29c33f4SEric W. Biederman 	old_uid_t ruid, euid, suid;
691da177e4SLinus Torvalds 
70a29c33f4SEric W. Biederman 	ruid = high2lowuid(from_kuid_munged(cred->user_ns, cred->uid));
71a29c33f4SEric W. Biederman 	euid = high2lowuid(from_kuid_munged(cred->user_ns, cred->euid));
72a29c33f4SEric W. Biederman 	suid = high2lowuid(from_kuid_munged(cred->user_ns, cred->suid));
73a29c33f4SEric W. Biederman 
74a29c33f4SEric W. Biederman 	if (!(retval   = put_user(ruid, ruidp)) &&
75a29c33f4SEric W. Biederman 	    !(retval   = put_user(euid, euidp)))
76a29c33f4SEric W. Biederman 		retval = put_user(suid, suidp);
771da177e4SLinus Torvalds 
781da177e4SLinus Torvalds 	return retval;
791da177e4SLinus Torvalds }
801da177e4SLinus Torvalds 
SYSCALL_DEFINE3(setresgid16,old_gid_t,rgid,old_gid_t,egid,old_gid_t,sgid)81a6b42e83SHeiko Carstens SYSCALL_DEFINE3(setresgid16, old_gid_t, rgid, old_gid_t, egid, old_gid_t, sgid)
821da177e4SLinus Torvalds {
83e530dca5SDominik Brodowski 	return __sys_setresgid(low2highgid(rgid), low2highgid(egid),
841da177e4SLinus Torvalds 				 low2highgid(sgid));
851da177e4SLinus Torvalds }
861da177e4SLinus Torvalds 
SYSCALL_DEFINE3(getresgid16,old_gid_t __user *,rgidp,old_gid_t __user *,egidp,old_gid_t __user *,sgidp)87a29c33f4SEric W. Biederman SYSCALL_DEFINE3(getresgid16, old_gid_t __user *, rgidp, old_gid_t __user *, egidp, old_gid_t __user *, sgidp)
881da177e4SLinus Torvalds {
8986a264abSDavid Howells 	const struct cred *cred = current_cred();
901da177e4SLinus Torvalds 	int retval;
91a29c33f4SEric W. Biederman 	old_gid_t rgid, egid, sgid;
921da177e4SLinus Torvalds 
93a29c33f4SEric W. Biederman 	rgid = high2lowgid(from_kgid_munged(cred->user_ns, cred->gid));
94a29c33f4SEric W. Biederman 	egid = high2lowgid(from_kgid_munged(cred->user_ns, cred->egid));
95a29c33f4SEric W. Biederman 	sgid = high2lowgid(from_kgid_munged(cred->user_ns, cred->sgid));
96a29c33f4SEric W. Biederman 
97a29c33f4SEric W. Biederman 	if (!(retval   = put_user(rgid, rgidp)) &&
98a29c33f4SEric W. Biederman 	    !(retval   = put_user(egid, egidp)))
99a29c33f4SEric W. Biederman 		retval = put_user(sgid, sgidp);
1001da177e4SLinus Torvalds 
1011da177e4SLinus Torvalds 	return retval;
1021da177e4SLinus Torvalds }
1031da177e4SLinus Torvalds 
SYSCALL_DEFINE1(setfsuid16,old_uid_t,uid)104a6b42e83SHeiko Carstens SYSCALL_DEFINE1(setfsuid16, old_uid_t, uid)
1051da177e4SLinus Torvalds {
106e530dca5SDominik Brodowski 	return __sys_setfsuid(low2highuid(uid));
1071da177e4SLinus Torvalds }
1081da177e4SLinus Torvalds 
SYSCALL_DEFINE1(setfsgid16,old_gid_t,gid)109a6b42e83SHeiko Carstens SYSCALL_DEFINE1(setfsgid16, old_gid_t, gid)
1101da177e4SLinus Torvalds {
111e530dca5SDominik Brodowski 	return __sys_setfsgid(low2highgid(gid));
1121da177e4SLinus Torvalds }
1131da177e4SLinus Torvalds 
groups16_to_user(old_gid_t __user * grouplist,struct group_info * group_info)1141da177e4SLinus Torvalds static int groups16_to_user(old_gid_t __user *grouplist,
1151da177e4SLinus Torvalds     struct group_info *group_info)
1161da177e4SLinus Torvalds {
117ae2975bcSEric W. Biederman 	struct user_namespace *user_ns = current_user_ns();
1181da177e4SLinus Torvalds 	int i;
1191da177e4SLinus Torvalds 	old_gid_t group;
120ae2975bcSEric W. Biederman 	kgid_t kgid;
1211da177e4SLinus Torvalds 
1221da177e4SLinus Torvalds 	for (i = 0; i < group_info->ngroups; i++) {
12381243eacSAlexey Dobriyan 		kgid = group_info->gid[i];
124ae2975bcSEric W. Biederman 		group = high2lowgid(from_kgid_munged(user_ns, kgid));
1251da177e4SLinus Torvalds 		if (put_user(group, grouplist+i))
1261da177e4SLinus Torvalds 			return -EFAULT;
1271da177e4SLinus Torvalds 	}
1281da177e4SLinus Torvalds 
1291da177e4SLinus Torvalds 	return 0;
1301da177e4SLinus Torvalds }
1311da177e4SLinus Torvalds 
groups16_from_user(struct group_info * group_info,old_gid_t __user * grouplist)1321da177e4SLinus Torvalds static int groups16_from_user(struct group_info *group_info,
1331da177e4SLinus Torvalds     old_gid_t __user *grouplist)
1341da177e4SLinus Torvalds {
135ae2975bcSEric W. Biederman 	struct user_namespace *user_ns = current_user_ns();
1361da177e4SLinus Torvalds 	int i;
1371da177e4SLinus Torvalds 	old_gid_t group;
138ae2975bcSEric W. Biederman 	kgid_t kgid;
1391da177e4SLinus Torvalds 
1401da177e4SLinus Torvalds 	for (i = 0; i < group_info->ngroups; i++) {
1411da177e4SLinus Torvalds 		if (get_user(group, grouplist+i))
1421da177e4SLinus Torvalds 			return  -EFAULT;
143ae2975bcSEric W. Biederman 
144ae2975bcSEric W. Biederman 		kgid = make_kgid(user_ns, low2highgid(group));
145ae2975bcSEric W. Biederman 		if (!gid_valid(kgid))
146ae2975bcSEric W. Biederman 			return -EINVAL;
147ae2975bcSEric W. Biederman 
14881243eacSAlexey Dobriyan 		group_info->gid[i] = kgid;
1491da177e4SLinus Torvalds 	}
1501da177e4SLinus Torvalds 
1511da177e4SLinus Torvalds 	return 0;
1521da177e4SLinus Torvalds }
1531da177e4SLinus Torvalds 
SYSCALL_DEFINE2(getgroups16,int,gidsetsize,old_gid_t __user *,grouplist)154003d7ab4SHeiko Carstens SYSCALL_DEFINE2(getgroups16, int, gidsetsize, old_gid_t __user *, grouplist)
1551da177e4SLinus Torvalds {
15686a264abSDavid Howells 	const struct cred *cred = current_cred();
15786a264abSDavid Howells 	int i;
1581da177e4SLinus Torvalds 
1591da177e4SLinus Torvalds 	if (gidsetsize < 0)
1601da177e4SLinus Torvalds 		return -EINVAL;
1611da177e4SLinus Torvalds 
16286a264abSDavid Howells 	i = cred->group_info->ngroups;
1631da177e4SLinus Torvalds 	if (gidsetsize) {
1641da177e4SLinus Torvalds 		if (i > gidsetsize) {
1651da177e4SLinus Torvalds 			i = -EINVAL;
1661da177e4SLinus Torvalds 			goto out;
1671da177e4SLinus Torvalds 		}
16886a264abSDavid Howells 		if (groups16_to_user(grouplist, cred->group_info)) {
1691da177e4SLinus Torvalds 			i = -EFAULT;
1701da177e4SLinus Torvalds 			goto out;
1711da177e4SLinus Torvalds 		}
1721da177e4SLinus Torvalds 	}
1731da177e4SLinus Torvalds out:
1741da177e4SLinus Torvalds 	return i;
1751da177e4SLinus Torvalds }
1761da177e4SLinus Torvalds 
SYSCALL_DEFINE2(setgroups16,int,gidsetsize,old_gid_t __user *,grouplist)177003d7ab4SHeiko Carstens SYSCALL_DEFINE2(setgroups16, int, gidsetsize, old_gid_t __user *, grouplist)
1781da177e4SLinus Torvalds {
1791da177e4SLinus Torvalds 	struct group_info *group_info;
1801da177e4SLinus Torvalds 	int retval;
1811da177e4SLinus Torvalds 
1827ff4d90bSEric W. Biederman 	if (!may_setgroups())
1831da177e4SLinus Torvalds 		return -EPERM;
1841da177e4SLinus Torvalds 	if ((unsigned)gidsetsize > NGROUPS_MAX)
1851da177e4SLinus Torvalds 		return -EINVAL;
1861da177e4SLinus Torvalds 
1871da177e4SLinus Torvalds 	group_info = groups_alloc(gidsetsize);
1881da177e4SLinus Torvalds 	if (!group_info)
1891da177e4SLinus Torvalds 		return -ENOMEM;
1901da177e4SLinus Torvalds 	retval = groups16_from_user(group_info, grouplist);
1911da177e4SLinus Torvalds 	if (retval) {
1921da177e4SLinus Torvalds 		put_group_info(group_info);
1931da177e4SLinus Torvalds 		return retval;
1941da177e4SLinus Torvalds 	}
1951da177e4SLinus Torvalds 
196bdcf0a42SThiago Rafael Becker 	groups_sort(group_info);
1971da177e4SLinus Torvalds 	retval = set_current_groups(group_info);
1981da177e4SLinus Torvalds 	put_group_info(group_info);
1991da177e4SLinus Torvalds 
2001da177e4SLinus Torvalds 	return retval;
2011da177e4SLinus Torvalds }
2021da177e4SLinus Torvalds 
SYSCALL_DEFINE0(getuid16)203003d7ab4SHeiko Carstens SYSCALL_DEFINE0(getuid16)
2041da177e4SLinus Torvalds {
205a29c33f4SEric W. Biederman 	return high2lowuid(from_kuid_munged(current_user_ns(), current_uid()));
2061da177e4SLinus Torvalds }
2071da177e4SLinus Torvalds 
SYSCALL_DEFINE0(geteuid16)208003d7ab4SHeiko Carstens SYSCALL_DEFINE0(geteuid16)
2091da177e4SLinus Torvalds {
210a29c33f4SEric W. Biederman 	return high2lowuid(from_kuid_munged(current_user_ns(), current_euid()));
2111da177e4SLinus Torvalds }
2121da177e4SLinus Torvalds 
SYSCALL_DEFINE0(getgid16)213003d7ab4SHeiko Carstens SYSCALL_DEFINE0(getgid16)
2141da177e4SLinus Torvalds {
215a29c33f4SEric W. Biederman 	return high2lowgid(from_kgid_munged(current_user_ns(), current_gid()));
2161da177e4SLinus Torvalds }
2171da177e4SLinus Torvalds 
SYSCALL_DEFINE0(getegid16)218003d7ab4SHeiko Carstens SYSCALL_DEFINE0(getegid16)
2191da177e4SLinus Torvalds {
220a29c33f4SEric W. Biederman 	return high2lowgid(from_kgid_munged(current_user_ns(), current_egid()));
2211da177e4SLinus Torvalds }
222