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