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