Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
uid16.c
Go to the documentation of this file.
1 /*
2  * Wrapper functions for 16bit uid back compatibility. All nicely tied
3  * together in the faint hope we can take the out in five years time.
4  */
5 
6 #include <linux/mm.h>
7 #include <linux/mman.h>
8 #include <linux/notifier.h>
9 #include <linux/reboot.h>
10 #include <linux/prctl.h>
11 #include <linux/capability.h>
12 #include <linux/init.h>
13 #include <linux/highuid.h>
14 #include <linux/security.h>
15 #include <linux/syscalls.h>
16 
17 #include <asm/uaccess.h>
18 
19 SYSCALL_DEFINE3(chown16, const char __user *, filename, old_uid_t, user, old_gid_t, group)
20 {
22  /* avoid REGPARM breakage on x86: */
24  return ret;
25 }
26 
27 SYSCALL_DEFINE3(lchown16, const char __user *, filename, old_uid_t, user, old_gid_t, group)
28 {
30  /* avoid REGPARM breakage on x86: */
32  return ret;
33 }
34 
35 SYSCALL_DEFINE3(fchown16, unsigned int, fd, old_uid_t, user, old_gid_t, group)
36 {
38  /* avoid REGPARM breakage on x86: */
39  asmlinkage_protect(3, ret, fd, user, group);
40  return ret;
41 }
42 
43 SYSCALL_DEFINE2(setregid16, old_gid_t, rgid, old_gid_t, egid)
44 {
46  /* avoid REGPARM breakage on x86: */
47  asmlinkage_protect(2, ret, rgid, egid);
48  return ret;
49 }
50 
51 SYSCALL_DEFINE1(setgid16, old_gid_t, gid)
52 {
53  long ret = sys_setgid(low2highgid(gid));
54  /* avoid REGPARM breakage on x86: */
55  asmlinkage_protect(1, ret, gid);
56  return ret;
57 }
58 
59 SYSCALL_DEFINE2(setreuid16, old_uid_t, ruid, old_uid_t, euid)
60 {
61  long ret = sys_setreuid(low2highuid(ruid), low2highuid(euid));
62  /* avoid REGPARM breakage on x86: */
63  asmlinkage_protect(2, ret, ruid, euid);
64  return ret;
65 }
66 
67 SYSCALL_DEFINE1(setuid16, old_uid_t, uid)
68 {
69  long ret = sys_setuid(low2highuid(uid));
70  /* avoid REGPARM breakage on x86: */
71  asmlinkage_protect(1, ret, uid);
72  return ret;
73 }
74 
75 SYSCALL_DEFINE3(setresuid16, old_uid_t, ruid, old_uid_t, euid, old_uid_t, suid)
76 {
77  long ret = sys_setresuid(low2highuid(ruid), low2highuid(euid),
78  low2highuid(suid));
79  /* avoid REGPARM breakage on x86: */
80  asmlinkage_protect(3, ret, ruid, euid, suid);
81  return ret;
82 }
83 
84 SYSCALL_DEFINE3(getresuid16, old_uid_t __user *, ruidp, old_uid_t __user *, euidp, old_uid_t __user *, suidp)
85 {
86  const struct cred *cred = current_cred();
87  int retval;
88  old_uid_t ruid, euid, suid;
89 
90  ruid = high2lowuid(from_kuid_munged(cred->user_ns, cred->uid));
91  euid = high2lowuid(from_kuid_munged(cred->user_ns, cred->euid));
92  suid = high2lowuid(from_kuid_munged(cred->user_ns, cred->suid));
93 
94  if (!(retval = put_user(ruid, ruidp)) &&
95  !(retval = put_user(euid, euidp)))
96  retval = put_user(suid, suidp);
97 
98  return retval;
99 }
100 
101 SYSCALL_DEFINE3(setresgid16, old_gid_t, rgid, old_gid_t, egid, old_gid_t, sgid)
102 {
104  low2highgid(sgid));
105  /* avoid REGPARM breakage on x86: */
106  asmlinkage_protect(3, ret, rgid, egid, sgid);
107  return ret;
108 }
109 
110 
111 SYSCALL_DEFINE3(getresgid16, old_gid_t __user *, rgidp, old_gid_t __user *, egidp, old_gid_t __user *, sgidp)
112 {
113  const struct cred *cred = current_cred();
114  int retval;
115  old_gid_t rgid, egid, sgid;
116 
117  rgid = high2lowgid(from_kgid_munged(cred->user_ns, cred->gid));
118  egid = high2lowgid(from_kgid_munged(cred->user_ns, cred->egid));
119  sgid = high2lowgid(from_kgid_munged(cred->user_ns, cred->sgid));
120 
121  if (!(retval = put_user(rgid, rgidp)) &&
122  !(retval = put_user(egid, egidp)))
123  retval = put_user(sgid, sgidp);
124 
125  return retval;
126 }
127 
128 SYSCALL_DEFINE1(setfsuid16, old_uid_t, uid)
129 {
130  long ret = sys_setfsuid(low2highuid(uid));
131  /* avoid REGPARM breakage on x86: */
132  asmlinkage_protect(1, ret, uid);
133  return ret;
134 }
135 
136 SYSCALL_DEFINE1(setfsgid16, old_gid_t, gid)
137 {
138  long ret = sys_setfsgid(low2highgid(gid));
139  /* avoid REGPARM breakage on x86: */
140  asmlinkage_protect(1, ret, gid);
141  return ret;
142 }
143 
144 static int groups16_to_user(old_gid_t __user *grouplist,
145  struct group_info *group_info)
146 {
147  struct user_namespace *user_ns = current_user_ns();
148  int i;
149  old_gid_t group;
150  kgid_t kgid;
151 
152  for (i = 0; i < group_info->ngroups; i++) {
153  kgid = GROUP_AT(group_info, i);
154  group = high2lowgid(from_kgid_munged(user_ns, kgid));
155  if (put_user(group, grouplist+i))
156  return -EFAULT;
157  }
158 
159  return 0;
160 }
161 
162 static int groups16_from_user(struct group_info *group_info,
163  old_gid_t __user *grouplist)
164 {
165  struct user_namespace *user_ns = current_user_ns();
166  int i;
167  old_gid_t group;
168  kgid_t kgid;
169 
170  for (i = 0; i < group_info->ngroups; i++) {
171  if (get_user(group, grouplist+i))
172  return -EFAULT;
173 
174  kgid = make_kgid(user_ns, low2highgid(group));
175  if (!gid_valid(kgid))
176  return -EINVAL;
177 
178  GROUP_AT(group_info, i) = kgid;
179  }
180 
181  return 0;
182 }
183 
184 SYSCALL_DEFINE2(getgroups16, int, gidsetsize, old_gid_t __user *, grouplist)
185 {
186  const struct cred *cred = current_cred();
187  int i;
188 
189  if (gidsetsize < 0)
190  return -EINVAL;
191 
192  i = cred->group_info->ngroups;
193  if (gidsetsize) {
194  if (i > gidsetsize) {
195  i = -EINVAL;
196  goto out;
197  }
198  if (groups16_to_user(grouplist, cred->group_info)) {
199  i = -EFAULT;
200  goto out;
201  }
202  }
203 out:
204  return i;
205 }
206 
207 SYSCALL_DEFINE2(setgroups16, int, gidsetsize, old_gid_t __user *, grouplist)
208 {
209  struct group_info *group_info;
210  int retval;
211 
213  return -EPERM;
214  if ((unsigned)gidsetsize > NGROUPS_MAX)
215  return -EINVAL;
216 
217  group_info = groups_alloc(gidsetsize);
218  if (!group_info)
219  return -ENOMEM;
220  retval = groups16_from_user(group_info, grouplist);
221  if (retval) {
222  put_group_info(group_info);
223  return retval;
224  }
225 
226  retval = set_current_groups(group_info);
227  put_group_info(group_info);
228 
229  return retval;
230 }
231 
233 {
235 }
236 
237 SYSCALL_DEFINE0(geteuid16)
238 {
240 }
241 
243 {
245 }
246 
247 SYSCALL_DEFINE0(getegid16)
248 {
250 }