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 long ret = sys_chown(filename, low2highuid(user), low2highgid(group)); 22 /* avoid REGPARM breakage on x86: */ 23 asmlinkage_protect(3, ret, filename, user, group); 24 return ret; 25} 26 27SYSCALL_DEFINE3(lchown16, const char __user *, filename, old_uid_t, user, old_gid_t, group) 28{ 29 long ret = sys_lchown(filename, low2highuid(user), low2highgid(group)); 30 /* avoid REGPARM breakage on x86: */ 31 asmlinkage_protect(3, ret, filename, user, group); 32 return ret; 33} 34 35SYSCALL_DEFINE3(fchown16, unsigned int, fd, old_uid_t, user, old_gid_t, group) 36{ 37 long ret = sys_fchown(fd, low2highuid(user), low2highgid(group)); 38 /* avoid REGPARM breakage on x86: */ 39 asmlinkage_protect(3, ret, fd, user, group); 40 return ret; 41} 42 43SYSCALL_DEFINE2(setregid16, old_gid_t, rgid, old_gid_t, egid) 44{ 45 long ret = sys_setregid(low2highgid(rgid), low2highgid(egid)); 46 /* avoid REGPARM breakage on x86: */ 47 asmlinkage_protect(2, ret, rgid, egid); 48 return ret; 49} 50 51SYSCALL_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 59SYSCALL_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 67SYSCALL_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 75SYSCALL_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 84SYSCALL_DEFINE3(getresuid16, old_uid_t __user *, ruid, old_uid_t __user *, euid, old_uid_t __user *, suid) 85{ 86 const struct cred *cred = current_cred(); 87 int retval; 88 89 if (!(retval = put_user(high2lowuid(cred->uid), ruid)) && 90 !(retval = put_user(high2lowuid(cred->euid), euid))) 91 retval = put_user(high2lowuid(cred->suid), suid); 92 93 return retval; 94} 95 96SYSCALL_DEFINE3(setresgid16, old_gid_t, rgid, old_gid_t, egid, old_gid_t, sgid) 97{ 98 long ret = sys_setresgid(low2highgid(rgid), low2highgid(egid), 99 low2highgid(sgid)); 100 /* avoid REGPARM breakage on x86: */ 101 asmlinkage_protect(3, ret, rgid, egid, sgid); 102 return ret; 103} 104 105 106SYSCALL_DEFINE3(getresgid16, old_gid_t __user *, rgid, old_gid_t __user *, egid, old_gid_t __user *, sgid) 107{ 108 const struct cred *cred = current_cred(); 109 int retval; 110 111 if (!(retval = put_user(high2lowgid(cred->gid), rgid)) && 112 !(retval = put_user(high2lowgid(cred->egid), egid))) 113 retval = put_user(high2lowgid(cred->sgid), sgid); 114 115 return retval; 116} 117 118SYSCALL_DEFINE1(setfsuid16, old_uid_t, uid) 119{ 120 long ret = sys_setfsuid(low2highuid(uid)); 121 /* avoid REGPARM breakage on x86: */ 122 asmlinkage_protect(1, ret, uid); 123 return ret; 124} 125 126SYSCALL_DEFINE1(setfsgid16, old_gid_t, gid) 127{ 128 long ret = sys_setfsgid(low2highgid(gid)); 129 /* avoid REGPARM breakage on x86: */ 130 asmlinkage_protect(1, ret, gid); 131 return ret; 132} 133 134static int groups16_to_user(old_gid_t __user *grouplist, 135 struct group_info *group_info) 136{ 137 int i; 138 old_gid_t group; 139 140 for (i = 0; i < group_info->ngroups; i++) { 141 group = high2lowgid(GROUP_AT(group_info, i)); 142 if (put_user(group, grouplist+i)) 143 return -EFAULT; 144 } 145 146 return 0; 147} 148 149static int groups16_from_user(struct group_info *group_info, 150 old_gid_t __user *grouplist) 151{ 152 int i; 153 old_gid_t group; 154 155 for (i = 0; i < group_info->ngroups; i++) { 156 if (get_user(group, grouplist+i)) 157 return -EFAULT; 158 GROUP_AT(group_info, i) = low2highgid(group); 159 } 160 161 return 0; 162} 163 164SYSCALL_DEFINE2(getgroups16, int, gidsetsize, old_gid_t __user *, grouplist) 165{ 166 const struct cred *cred = current_cred(); 167 int i; 168 169 if (gidsetsize < 0) 170 return -EINVAL; 171 172 i = cred->group_info->ngroups; 173 if (gidsetsize) { 174 if (i > gidsetsize) { 175 i = -EINVAL; 176 goto out; 177 } 178 if (groups16_to_user(grouplist, cred->group_info)) { 179 i = -EFAULT; 180 goto out; 181 } 182 } 183out: 184 return i; 185} 186 187SYSCALL_DEFINE2(setgroups16, int, gidsetsize, old_gid_t __user *, grouplist) 188{ 189 struct group_info *group_info; 190 int retval; 191 192 if (!capable(CAP_SETGID)) 193 return -EPERM; 194 if ((unsigned)gidsetsize > NGROUPS_MAX) 195 return -EINVAL; 196 197 group_info = groups_alloc(gidsetsize); 198 if (!group_info) 199 return -ENOMEM; 200 retval = groups16_from_user(group_info, grouplist); 201 if (retval) { 202 put_group_info(group_info); 203 return retval; 204 } 205 206 retval = set_current_groups(group_info); 207 put_group_info(group_info); 208 209 return retval; 210} 211 212SYSCALL_DEFINE0(getuid16) 213{ 214 return high2lowuid(current_uid()); 215} 216 217SYSCALL_DEFINE0(geteuid16) 218{ 219 return high2lowuid(current_euid()); 220} 221 222SYSCALL_DEFINE0(getgid16) 223{ 224 return high2lowgid(current_gid()); 225} 226 227SYSCALL_DEFINE0(getegid16) 228{ 229 return high2lowgid(current_egid()); 230} 231