Branch data 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 : : 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 : : }
|