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