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