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/utsname.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/syscalls.h> 17 18 #include <asm/uaccess.h> 19 20 asmlinkage long sys_chown16(const char __user * filename, old_uid_t user, old_gid_t group) 21 { 22 long ret = sys_chown(filename, low2highuid(user), low2highgid(group)); 23 /* avoid REGPARM breakage on x86: */ 24 asmlinkage_protect(3, ret, filename, user, group); 25 return ret; 26 } 27 28 asmlinkage long sys_lchown16(const char __user * filename, old_uid_t user, old_gid_t group) 29 { 30 long ret = sys_lchown(filename, low2highuid(user), low2highgid(group)); 31 /* avoid REGPARM breakage on x86: */ 32 asmlinkage_protect(3, ret, filename, user, group); 33 return ret; 34 } 35 36 asmlinkage long sys_fchown16(unsigned int fd, old_uid_t user, old_gid_t group) 37 { 38 long ret = sys_fchown(fd, low2highuid(user), low2highgid(group)); 39 /* avoid REGPARM breakage on x86: */ 40 asmlinkage_protect(3, ret, fd, user, group); 41 return ret; 42 } 43 44 asmlinkage long sys_setregid16(old_gid_t rgid, old_gid_t egid) 45 { 46 long ret = sys_setregid(low2highgid(rgid), low2highgid(egid)); 47 /* avoid REGPARM breakage on x86: */ 48 asmlinkage_protect(2, ret, rgid, egid); 49 return ret; 50 } 51 52 asmlinkage long sys_setgid16(old_gid_t gid) 53 { 54 long ret = sys_setgid(low2highgid(gid)); 55 /* avoid REGPARM breakage on x86: */ 56 asmlinkage_protect(1, ret, gid); 57 return ret; 58 } 59 60 asmlinkage long sys_setreuid16(old_uid_t ruid, old_uid_t euid) 61 { 62 long ret = sys_setreuid(low2highuid(ruid), low2highuid(euid)); 63 /* avoid REGPARM breakage on x86: */ 64 asmlinkage_protect(2, ret, ruid, euid); 65 return ret; 66 } 67 68 asmlinkage long sys_setuid16(old_uid_t uid) 69 { 70 long ret = sys_setuid(low2highuid(uid)); 71 /* avoid REGPARM breakage on x86: */ 72 asmlinkage_protect(1, ret, uid); 73 return ret; 74 } 75 76 asmlinkage long sys_setresuid16(old_uid_t ruid, old_uid_t euid, old_uid_t suid) 77 { 78 long ret = sys_setresuid(low2highuid(ruid), low2highuid(euid), 79 low2highuid(suid)); 80 /* avoid REGPARM breakage on x86: */ 81 asmlinkage_protect(3, ret, ruid, euid, suid); 82 return ret; 83 } 84 85 asmlinkage long sys_getresuid16(old_uid_t __user *ruid, old_uid_t __user *euid, old_uid_t __user *suid) 86 { 87 int retval; 88 89 if (!(retval = put_user(high2lowuid(current->uid), ruid)) && 90 !(retval = put_user(high2lowuid(current->euid), euid))) 91 retval = put_user(high2lowuid(current->suid), suid); 92 93 return retval; 94 } 95 96 asmlinkage long sys_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 asmlinkage long sys_getresgid16(old_gid_t __user *rgid, old_gid_t __user *egid, old_gid_t __user *sgid) 106 { 107 int retval; 108 109 if (!(retval = put_user(high2lowgid(current->gid), rgid)) && 110 !(retval = put_user(high2lowgid(current->egid), egid))) 111 retval = put_user(high2lowgid(current->sgid), sgid); 112 113 return retval; 114 } 115 116 asmlinkage long sys_setfsuid16(old_uid_t uid) 117 { 118 long ret = sys_setfsuid(low2highuid(uid)); 119 /* avoid REGPARM breakage on x86: */ 120 asmlinkage_protect(1, ret, uid); 121 return ret; 122 } 123 124 asmlinkage long sys_setfsgid16(old_gid_t gid) 125 { 126 long ret = sys_setfsgid(low2highgid(gid)); 127 /* avoid REGPARM breakage on x86: */ 128 asmlinkage_protect(1, ret, gid); 129 return ret; 130 } 131 132 static int groups16_to_user(old_gid_t __user *grouplist, 133 struct group_info *group_info) 134 { 135 int i; 136 old_gid_t group; 137 138 for (i = 0; i < group_info->ngroups; i++) { 139 group = high2lowgid(GROUP_AT(group_info, i)); 140 if (put_user(group, grouplist+i)) 141 return -EFAULT; 142 } 143 144 return 0; 145 } 146 147 static int groups16_from_user(struct group_info *group_info, 148 old_gid_t __user *grouplist) 149 { 150 int i; 151 old_gid_t group; 152 153 for (i = 0; i < group_info->ngroups; i++) { 154 if (get_user(group, grouplist+i)) 155 return -EFAULT; 156 GROUP_AT(group_info, i) = low2highgid(group); 157 } 158 159 return 0; 160 } 161 162 asmlinkage long sys_getgroups16(int gidsetsize, old_gid_t __user *grouplist) 163 { 164 int i = 0; 165 166 if (gidsetsize < 0) 167 return -EINVAL; 168 169 get_group_info(current->group_info); 170 i = current->group_info->ngroups; 171 if (gidsetsize) { 172 if (i > gidsetsize) { 173 i = -EINVAL; 174 goto out; 175 } 176 if (groups16_to_user(grouplist, current->group_info)) { 177 i = -EFAULT; 178 goto out; 179 } 180 } 181 out: 182 put_group_info(current->group_info); 183 return i; 184 } 185 186 asmlinkage long sys_setgroups16(int gidsetsize, old_gid_t __user *grouplist) 187 { 188 struct group_info *group_info; 189 int retval; 190 191 if (!capable(CAP_SETGID)) 192 return -EPERM; 193 if ((unsigned)gidsetsize > NGROUPS_MAX) 194 return -EINVAL; 195 196 group_info = groups_alloc(gidsetsize); 197 if (!group_info) 198 return -ENOMEM; 199 retval = groups16_from_user(group_info, grouplist); 200 if (retval) { 201 put_group_info(group_info); 202 return retval; 203 } 204 205 retval = set_current_groups(group_info); 206 put_group_info(group_info); 207 208 return retval; 209 } 210 211 asmlinkage long sys_getuid16(void) 212 { 213 return high2lowuid(current->uid); 214 } 215 216 asmlinkage long sys_geteuid16(void) 217 { 218 return high2lowuid(current->euid); 219 } 220 221 asmlinkage long sys_getgid16(void) 222 { 223 return high2lowgid(current->gid); 224 } 225 226 asmlinkage long sys_getegid16(void) 227 { 228 return high2lowgid(current->egid); 229 } 230