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 19 SYSCALL_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 24 SYSCALL_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 29 SYSCALL_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 34 SYSCALL_DEFINE2(setregid16, old_gid_t, rgid, old_gid_t, egid) 35 { 36 return sys_setregid(low2highgid(rgid), low2highgid(egid)); 37 } 38 39 SYSCALL_DEFINE1(setgid16, old_gid_t, gid) 40 { 41 return sys_setgid(low2highgid(gid)); 42 } 43 44 SYSCALL_DEFINE2(setreuid16, old_uid_t, ruid, old_uid_t, euid) 45 { 46 return sys_setreuid(low2highuid(ruid), low2highuid(euid)); 47 } 48 49 SYSCALL_DEFINE1(setuid16, old_uid_t, uid) 50 { 51 return sys_setuid(low2highuid(uid)); 52 } 53 54 SYSCALL_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 60 SYSCALL_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 77 SYSCALL_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 84 SYSCALL_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 101 SYSCALL_DEFINE1(setfsuid16, old_uid_t, uid) 102 { 103 return sys_setfsuid(low2highuid(uid)); 104 } 105 106 SYSCALL_DEFINE1(setfsgid16, old_gid_t, gid) 107 { 108 return sys_setfsgid(low2highgid(gid)); 109 } 110 111 static 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 129 static 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 151 SYSCALL_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 } 170 out: 171 return i; 172 } 173 174 SYSCALL_DEFINE2(setgroups16, int, gidsetsize, old_gid_t __user *, grouplist) 175 { 176 struct group_info *group_info; 177 int retval; 178 179 if (!ns_capable(current_user_ns(), CAP_SETGID)) 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 199 SYSCALL_DEFINE0(getuid16) 200 { 201 return high2lowuid(from_kuid_munged(current_user_ns(), current_uid())); 202 } 203 204 SYSCALL_DEFINE0(geteuid16) 205 { 206 return high2lowuid(from_kuid_munged(current_user_ns(), current_euid())); 207 } 208 209 SYSCALL_DEFINE0(getgid16) 210 { 211 return high2lowgid(from_kgid_munged(current_user_ns(), current_gid())); 212 } 213 214 SYSCALL_DEFINE0(getegid16) 215 { 216 return high2lowgid(from_kgid_munged(current_user_ns(), current_egid())); 217 } 218