Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0
2 : /*
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>
8 : #include <linux/mman.h>
9 : #include <linux/notifier.h>
10 : #include <linux/reboot.h>
11 : #include <linux/prctl.h>
12 : #include <linux/capability.h>
13 : #include <linux/init.h>
14 : #include <linux/highuid.h>
15 : #include <linux/security.h>
16 : #include <linux/cred.h>
17 : #include <linux/syscalls.h>
18 :
19 : #include <linux/uaccess.h>
20 :
21 : #include "uid16.h"
22 :
23 0 : SYSCALL_DEFINE3(chown16, const char __user *, filename, old_uid_t, user, old_gid_t, group)
24 : {
25 0 : return ksys_chown(filename, low2highuid(user), low2highgid(group));
26 : }
27 :
28 0 : SYSCALL_DEFINE3(lchown16, const char __user *, filename, old_uid_t, user, old_gid_t, group)
29 : {
30 0 : return ksys_lchown(filename, low2highuid(user), low2highgid(group));
31 : }
32 :
33 0 : SYSCALL_DEFINE3(fchown16, unsigned int, fd, old_uid_t, user, old_gid_t, group)
34 : {
35 0 : return ksys_fchown(fd, low2highuid(user), low2highgid(group));
36 : }
37 :
38 0 : SYSCALL_DEFINE2(setregid16, old_gid_t, rgid, old_gid_t, egid)
39 : {
40 0 : return __sys_setregid(low2highgid(rgid), low2highgid(egid));
41 : }
42 :
43 0 : SYSCALL_DEFINE1(setgid16, old_gid_t, gid)
44 : {
45 0 : return __sys_setgid(low2highgid(gid));
46 : }
47 :
48 0 : SYSCALL_DEFINE2(setreuid16, old_uid_t, ruid, old_uid_t, euid)
49 : {
50 0 : return __sys_setreuid(low2highuid(ruid), low2highuid(euid));
51 : }
52 :
53 0 : SYSCALL_DEFINE1(setuid16, old_uid_t, uid)
54 : {
55 0 : return __sys_setuid(low2highuid(uid));
56 : }
57 :
58 0 : SYSCALL_DEFINE3(setresuid16, old_uid_t, ruid, old_uid_t, euid, old_uid_t, suid)
59 : {
60 0 : return __sys_setresuid(low2highuid(ruid), low2highuid(euid),
61 : low2highuid(suid));
62 : }
63 :
64 0 : SYSCALL_DEFINE3(getresuid16, old_uid_t __user *, ruidp, old_uid_t __user *, euidp, old_uid_t __user *, suidp)
65 : {
66 0 : const struct cred *cred = current_cred();
67 : int retval;
68 : old_uid_t ruid, euid, suid;
69 :
70 0 : ruid = high2lowuid(from_kuid_munged(cred->user_ns, cred->uid));
71 0 : euid = high2lowuid(from_kuid_munged(cred->user_ns, cred->euid));
72 0 : suid = high2lowuid(from_kuid_munged(cred->user_ns, cred->suid));
73 :
74 0 : if (!(retval = put_user(ruid, ruidp)) &&
75 0 : !(retval = put_user(euid, euidp)))
76 0 : retval = put_user(suid, suidp);
77 :
78 0 : return retval;
79 : }
80 :
81 0 : SYSCALL_DEFINE3(setresgid16, old_gid_t, rgid, old_gid_t, egid, old_gid_t, sgid)
82 : {
83 0 : return __sys_setresgid(low2highgid(rgid), low2highgid(egid),
84 : low2highgid(sgid));
85 : }
86 :
87 0 : SYSCALL_DEFINE3(getresgid16, old_gid_t __user *, rgidp, old_gid_t __user *, egidp, old_gid_t __user *, sgidp)
88 : {
89 0 : const struct cred *cred = current_cred();
90 : int retval;
91 : old_gid_t rgid, egid, sgid;
92 :
93 0 : rgid = high2lowgid(from_kgid_munged(cred->user_ns, cred->gid));
94 0 : egid = high2lowgid(from_kgid_munged(cred->user_ns, cred->egid));
95 0 : sgid = high2lowgid(from_kgid_munged(cred->user_ns, cred->sgid));
96 :
97 0 : if (!(retval = put_user(rgid, rgidp)) &&
98 0 : !(retval = put_user(egid, egidp)))
99 0 : retval = put_user(sgid, sgidp);
100 :
101 0 : return retval;
102 : }
103 :
104 0 : SYSCALL_DEFINE1(setfsuid16, old_uid_t, uid)
105 : {
106 0 : return __sys_setfsuid(low2highuid(uid));
107 : }
108 :
109 0 : SYSCALL_DEFINE1(setfsgid16, old_gid_t, gid)
110 : {
111 0 : return __sys_setfsgid(low2highgid(gid));
112 : }
113 :
114 0 : static int groups16_to_user(old_gid_t __user *grouplist,
115 : struct group_info *group_info)
116 : {
117 0 : struct user_namespace *user_ns = current_user_ns();
118 : int i;
119 : old_gid_t group;
120 : kgid_t kgid;
121 :
122 0 : for (i = 0; i < group_info->ngroups; i++) {
123 0 : kgid = group_info->gid[i];
124 0 : group = high2lowgid(from_kgid_munged(user_ns, kgid));
125 0 : if (put_user(group, grouplist+i))
126 : return -EFAULT;
127 : }
128 :
129 : return 0;
130 : }
131 :
132 0 : static int groups16_from_user(struct group_info *group_info,
133 : old_gid_t __user *grouplist)
134 : {
135 0 : struct user_namespace *user_ns = current_user_ns();
136 : int i;
137 : old_gid_t group;
138 : kgid_t kgid;
139 :
140 0 : for (i = 0; i < group_info->ngroups; i++) {
141 0 : if (get_user(group, grouplist+i))
142 : return -EFAULT;
143 :
144 0 : kgid = make_kgid(user_ns, low2highgid(group));
145 0 : if (!gid_valid(kgid))
146 : return -EINVAL;
147 :
148 0 : group_info->gid[i] = kgid;
149 : }
150 :
151 : return 0;
152 : }
153 :
154 0 : SYSCALL_DEFINE2(getgroups16, int, gidsetsize, old_gid_t __user *, grouplist)
155 : {
156 0 : const struct cred *cred = current_cred();
157 : int i;
158 :
159 0 : if (gidsetsize < 0)
160 : return -EINVAL;
161 :
162 0 : i = cred->group_info->ngroups;
163 0 : if (gidsetsize) {
164 0 : if (i > gidsetsize) {
165 : i = -EINVAL;
166 : goto out;
167 : }
168 0 : if (groups16_to_user(grouplist, cred->group_info)) {
169 0 : i = -EFAULT;
170 0 : goto out;
171 : }
172 : }
173 : out:
174 0 : return i;
175 : }
176 :
177 0 : SYSCALL_DEFINE2(setgroups16, int, gidsetsize, old_gid_t __user *, grouplist)
178 : {
179 : struct group_info *group_info;
180 : int retval;
181 :
182 0 : if (!may_setgroups())
183 : return -EPERM;
184 0 : if ((unsigned)gidsetsize > NGROUPS_MAX)
185 : return -EINVAL;
186 :
187 0 : group_info = groups_alloc(gidsetsize);
188 0 : if (!group_info)
189 : return -ENOMEM;
190 0 : retval = groups16_from_user(group_info, grouplist);
191 0 : if (retval) {
192 0 : put_group_info(group_info);
193 0 : return retval;
194 : }
195 :
196 0 : groups_sort(group_info);
197 0 : retval = set_current_groups(group_info);
198 0 : put_group_info(group_info);
199 :
200 0 : return retval;
201 : }
202 :
203 0 : SYSCALL_DEFINE0(getuid16)
204 : {
205 0 : return high2lowuid(from_kuid_munged(current_user_ns(), current_uid()));
206 : }
207 :
208 0 : SYSCALL_DEFINE0(geteuid16)
209 : {
210 0 : return high2lowuid(from_kuid_munged(current_user_ns(), current_euid()));
211 : }
212 :
213 0 : SYSCALL_DEFINE0(getgid16)
214 : {
215 0 : return high2lowgid(from_kgid_munged(current_user_ns(), current_gid()));
216 : }
217 :
218 0 : SYSCALL_DEFINE0(getegid16)
219 : {
220 0 : return high2lowgid(from_kgid_munged(current_user_ns(), current_egid()));
221 : }
|