blob: af6925d8599b9b2aba17bb26e05792e2250a8f89 [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001// SPDX-License-Identifier: GPL-2.0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/*
3 * Wrapper functions for 16bit uid back compatibility. All nicely tied
4 * together in the faint hope we can take the out in five years time.
5 */
6
7#include <linux/mm.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -07008#include <linux/mman.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -07009#include <linux/notifier.h>
10#include <linux/reboot.h>
11#include <linux/prctl.h>
Randy.Dunlapc59ede72006-01-11 12:17:46 -080012#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070013#include <linux/init.h>
14#include <linux/highuid.h>
15#include <linux/security.h>
Ingo Molnar5b825c32017-02-02 17:54:15 +010016#include <linux/cred.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070017#include <linux/syscalls.h>
18
Linus Torvalds7c0f6ba2016-12-24 11:46:01 -080019#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070020
Dominik Brodowskie530dca2018-03-19 18:09:27 +010021#include "uid16.h"
22
Heiko Carstensca013e92009-01-14 14:14:19 +010023SYSCALL_DEFINE3(chown16, const char __user *, filename, old_uid_t, user, old_gid_t, group)
Linus Torvalds1da177e2005-04-16 15:20:36 -070024{
Dominik Brodowski55731b32018-03-11 11:34:55 +010025 return ksys_chown(filename, low2highuid(user), low2highgid(group));
Linus Torvalds1da177e2005-04-16 15:20:36 -070026}
27
Heiko Carstensca013e92009-01-14 14:14:19 +010028SYSCALL_DEFINE3(lchown16, const char __user *, filename, old_uid_t, user, old_gid_t, group)
Linus Torvalds1da177e2005-04-16 15:20:36 -070029{
Dominik Brodowski55731b32018-03-11 11:34:55 +010030 return ksys_lchown(filename, low2highuid(user), low2highgid(group));
Linus Torvalds1da177e2005-04-16 15:20:36 -070031}
32
Heiko Carstensca013e92009-01-14 14:14:19 +010033SYSCALL_DEFINE3(fchown16, unsigned int, fd, old_uid_t, user, old_gid_t, group)
Linus Torvalds1da177e2005-04-16 15:20:36 -070034{
Dominik Brodowski55731b32018-03-11 11:34:55 +010035 return ksys_fchown(fd, low2highuid(user), low2highgid(group));
Linus Torvalds1da177e2005-04-16 15:20:36 -070036}
37
Heiko Carstensa6b42e82009-01-14 14:14:20 +010038SYSCALL_DEFINE2(setregid16, old_gid_t, rgid, old_gid_t, egid)
Linus Torvalds1da177e2005-04-16 15:20:36 -070039{
Dominik Brodowskie530dca2018-03-19 18:09:27 +010040 return __sys_setregid(low2highgid(rgid), low2highgid(egid));
Linus Torvalds1da177e2005-04-16 15:20:36 -070041}
42
Heiko Carstensa6b42e82009-01-14 14:14:20 +010043SYSCALL_DEFINE1(setgid16, old_gid_t, gid)
Linus Torvalds1da177e2005-04-16 15:20:36 -070044{
Dominik Brodowskie530dca2018-03-19 18:09:27 +010045 return __sys_setgid(low2highgid(gid));
Linus Torvalds1da177e2005-04-16 15:20:36 -070046}
47
Heiko Carstensa6b42e82009-01-14 14:14:20 +010048SYSCALL_DEFINE2(setreuid16, old_uid_t, ruid, old_uid_t, euid)
Linus Torvalds1da177e2005-04-16 15:20:36 -070049{
Dominik Brodowskie530dca2018-03-19 18:09:27 +010050 return __sys_setreuid(low2highuid(ruid), low2highuid(euid));
Linus Torvalds1da177e2005-04-16 15:20:36 -070051}
52
Heiko Carstensa6b42e82009-01-14 14:14:20 +010053SYSCALL_DEFINE1(setuid16, old_uid_t, uid)
Linus Torvalds1da177e2005-04-16 15:20:36 -070054{
Dominik Brodowskie530dca2018-03-19 18:09:27 +010055 return __sys_setuid(low2highuid(uid));
Linus Torvalds1da177e2005-04-16 15:20:36 -070056}
57
Heiko Carstensa6b42e82009-01-14 14:14:20 +010058SYSCALL_DEFINE3(setresuid16, old_uid_t, ruid, old_uid_t, euid, old_uid_t, suid)
Linus Torvalds1da177e2005-04-16 15:20:36 -070059{
Dominik Brodowskie530dca2018-03-19 18:09:27 +010060 return __sys_setresuid(low2highuid(ruid), low2highuid(euid),
OGAWA Hirofumi5a7b46b2006-04-20 06:41:39 +090061 low2highuid(suid));
Linus Torvalds1da177e2005-04-16 15:20:36 -070062}
63
Eric W. Biedermana29c33f2012-02-07 18:51:01 -080064SYSCALL_DEFINE3(getresuid16, old_uid_t __user *, ruidp, old_uid_t __user *, euidp, old_uid_t __user *, suidp)
Linus Torvalds1da177e2005-04-16 15:20:36 -070065{
David Howells86a264a2008-11-14 10:39:18 +110066 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -070067 int retval;
Eric W. Biedermana29c33f2012-02-07 18:51:01 -080068 old_uid_t ruid, euid, suid;
Linus Torvalds1da177e2005-04-16 15:20:36 -070069
Eric W. Biedermana29c33f2012-02-07 18:51:01 -080070 ruid = high2lowuid(from_kuid_munged(cred->user_ns, cred->uid));
71 euid = high2lowuid(from_kuid_munged(cred->user_ns, cred->euid));
72 suid = high2lowuid(from_kuid_munged(cred->user_ns, cred->suid));
73
74 if (!(retval = put_user(ruid, ruidp)) &&
75 !(retval = put_user(euid, euidp)))
76 retval = put_user(suid, suidp);
Linus Torvalds1da177e2005-04-16 15:20:36 -070077
78 return retval;
79}
80
Heiko Carstensa6b42e82009-01-14 14:14:20 +010081SYSCALL_DEFINE3(setresgid16, old_gid_t, rgid, old_gid_t, egid, old_gid_t, sgid)
Linus Torvalds1da177e2005-04-16 15:20:36 -070082{
Dominik Brodowskie530dca2018-03-19 18:09:27 +010083 return __sys_setresgid(low2highgid(rgid), low2highgid(egid),
OGAWA Hirofumi5a7b46b2006-04-20 06:41:39 +090084 low2highgid(sgid));
Linus Torvalds1da177e2005-04-16 15:20:36 -070085}
86
Eric W. Biedermana29c33f2012-02-07 18:51:01 -080087SYSCALL_DEFINE3(getresgid16, old_gid_t __user *, rgidp, old_gid_t __user *, egidp, old_gid_t __user *, sgidp)
Linus Torvalds1da177e2005-04-16 15:20:36 -070088{
David Howells86a264a2008-11-14 10:39:18 +110089 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -070090 int retval;
Eric W. Biedermana29c33f2012-02-07 18:51:01 -080091 old_gid_t rgid, egid, sgid;
Linus Torvalds1da177e2005-04-16 15:20:36 -070092
Eric W. Biedermana29c33f2012-02-07 18:51:01 -080093 rgid = high2lowgid(from_kgid_munged(cred->user_ns, cred->gid));
94 egid = high2lowgid(from_kgid_munged(cred->user_ns, cred->egid));
95 sgid = high2lowgid(from_kgid_munged(cred->user_ns, cred->sgid));
96
97 if (!(retval = put_user(rgid, rgidp)) &&
98 !(retval = put_user(egid, egidp)))
99 retval = put_user(sgid, sgidp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100
101 return retval;
102}
103
Heiko Carstensa6b42e82009-01-14 14:14:20 +0100104SYSCALL_DEFINE1(setfsuid16, old_uid_t, uid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105{
Dominik Brodowskie530dca2018-03-19 18:09:27 +0100106 return __sys_setfsuid(low2highuid(uid));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107}
108
Heiko Carstensa6b42e82009-01-14 14:14:20 +0100109SYSCALL_DEFINE1(setfsgid16, old_gid_t, gid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110{
Dominik Brodowskie530dca2018-03-19 18:09:27 +0100111 return __sys_setfsgid(low2highgid(gid));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112}
113
114static int groups16_to_user(old_gid_t __user *grouplist,
115 struct group_info *group_info)
116{
Eric W. Biedermanae2975b2011-11-14 15:56:38 -0800117 struct user_namespace *user_ns = current_user_ns();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 int i;
119 old_gid_t group;
Eric W. Biedermanae2975b2011-11-14 15:56:38 -0800120 kgid_t kgid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121
122 for (i = 0; i < group_info->ngroups; i++) {
Alexey Dobriyan81243ea2016-10-07 17:03:12 -0700123 kgid = group_info->gid[i];
Eric W. Biedermanae2975b2011-11-14 15:56:38 -0800124 group = high2lowgid(from_kgid_munged(user_ns, kgid));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 if (put_user(group, grouplist+i))
126 return -EFAULT;
127 }
128
129 return 0;
130}
131
132static int groups16_from_user(struct group_info *group_info,
133 old_gid_t __user *grouplist)
134{
Eric W. Biedermanae2975b2011-11-14 15:56:38 -0800135 struct user_namespace *user_ns = current_user_ns();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136 int i;
137 old_gid_t group;
Eric W. Biedermanae2975b2011-11-14 15:56:38 -0800138 kgid_t kgid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139
140 for (i = 0; i < group_info->ngroups; i++) {
141 if (get_user(group, grouplist+i))
142 return -EFAULT;
Eric W. Biedermanae2975b2011-11-14 15:56:38 -0800143
144 kgid = make_kgid(user_ns, low2highgid(group));
145 if (!gid_valid(kgid))
146 return -EINVAL;
147
Alexey Dobriyan81243ea2016-10-07 17:03:12 -0700148 group_info->gid[i] = kgid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149 }
150
151 return 0;
152}
153
Heiko Carstens003d7ab2009-01-14 14:14:21 +0100154SYSCALL_DEFINE2(getgroups16, int, gidsetsize, old_gid_t __user *, grouplist)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155{
David Howells86a264a2008-11-14 10:39:18 +1100156 const struct cred *cred = current_cred();
157 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158
159 if (gidsetsize < 0)
160 return -EINVAL;
161
David Howells86a264a2008-11-14 10:39:18 +1100162 i = cred->group_info->ngroups;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163 if (gidsetsize) {
164 if (i > gidsetsize) {
165 i = -EINVAL;
166 goto out;
167 }
David Howells86a264a2008-11-14 10:39:18 +1100168 if (groups16_to_user(grouplist, cred->group_info)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169 i = -EFAULT;
170 goto out;
171 }
172 }
173out:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174 return i;
175}
176
Heiko Carstens003d7ab2009-01-14 14:14:21 +0100177SYSCALL_DEFINE2(setgroups16, int, gidsetsize, old_gid_t __user *, grouplist)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178{
179 struct group_info *group_info;
180 int retval;
181
Eric W. Biederman7ff4d902014-12-05 17:19:27 -0600182 if (!may_setgroups())
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183 return -EPERM;
184 if ((unsigned)gidsetsize > NGROUPS_MAX)
185 return -EINVAL;
186
187 group_info = groups_alloc(gidsetsize);
188 if (!group_info)
189 return -ENOMEM;
190 retval = groups16_from_user(group_info, grouplist);
191 if (retval) {
192 put_group_info(group_info);
193 return retval;
194 }
195
Thiago Rafael Beckerbdcf0a42017-12-14 15:33:12 -0800196 groups_sort(group_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 retval = set_current_groups(group_info);
198 put_group_info(group_info);
199
200 return retval;
201}
202
Heiko Carstens003d7ab2009-01-14 14:14:21 +0100203SYSCALL_DEFINE0(getuid16)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204{
Eric W. Biedermana29c33f2012-02-07 18:51:01 -0800205 return high2lowuid(from_kuid_munged(current_user_ns(), current_uid()));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206}
207
Heiko Carstens003d7ab2009-01-14 14:14:21 +0100208SYSCALL_DEFINE0(geteuid16)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209{
Eric W. Biedermana29c33f2012-02-07 18:51:01 -0800210 return high2lowuid(from_kuid_munged(current_user_ns(), current_euid()));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211}
212
Heiko Carstens003d7ab2009-01-14 14:14:21 +0100213SYSCALL_DEFINE0(getgid16)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214{
Eric W. Biedermana29c33f2012-02-07 18:51:01 -0800215 return high2lowgid(from_kgid_munged(current_user_ns(), current_gid()));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216}
217
Heiko Carstens003d7ab2009-01-14 14:14:21 +0100218SYSCALL_DEFINE0(getegid16)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219{
Eric W. Biedermana29c33f2012-02-07 18:51:01 -0800220 return high2lowgid(from_kgid_munged(current_user_ns(), current_egid()));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221}