1 // SPDX-License-Identifier: GPL-2.0 << 2 /* 1 /* 3 * Wrapper functions for 16bit uid back c 2 * Wrapper functions for 16bit uid back compatibility. All nicely tied 4 * together in the faint hope we can take 3 * together in the faint hope we can take the out in five years time. 5 */ 4 */ 6 5 7 #include <linux/mm.h> 6 #include <linux/mm.h> 8 #include <linux/mman.h> 7 #include <linux/mman.h> 9 #include <linux/notifier.h> 8 #include <linux/notifier.h> 10 #include <linux/reboot.h> 9 #include <linux/reboot.h> 11 #include <linux/prctl.h> 10 #include <linux/prctl.h> 12 #include <linux/capability.h> 11 #include <linux/capability.h> 13 #include <linux/init.h> 12 #include <linux/init.h> 14 #include <linux/highuid.h> 13 #include <linux/highuid.h> 15 #include <linux/security.h> 14 #include <linux/security.h> 16 #include <linux/cred.h> 15 #include <linux/cred.h> 17 #include <linux/syscalls.h> 16 #include <linux/syscalls.h> 18 17 19 #include <linux/uaccess.h> 18 #include <linux/uaccess.h> 20 19 21 #include "uid16.h" << 22 << 23 SYSCALL_DEFINE3(chown16, const char __user *, 20 SYSCALL_DEFINE3(chown16, const char __user *, filename, old_uid_t, user, old_gid_t, group) 24 { 21 { 25 return ksys_chown(filename, low2highui !! 22 return sys_chown(filename, low2highuid(user), low2highgid(group)); 26 } 23 } 27 24 28 SYSCALL_DEFINE3(lchown16, const char __user *, 25 SYSCALL_DEFINE3(lchown16, const char __user *, filename, old_uid_t, user, old_gid_t, group) 29 { 26 { 30 return ksys_lchown(filename, low2highu !! 27 return sys_lchown(filename, low2highuid(user), low2highgid(group)); 31 } 28 } 32 29 33 SYSCALL_DEFINE3(fchown16, unsigned int, fd, ol 30 SYSCALL_DEFINE3(fchown16, unsigned int, fd, old_uid_t, user, old_gid_t, group) 34 { 31 { 35 return ksys_fchown(fd, low2highuid(use !! 32 return sys_fchown(fd, low2highuid(user), low2highgid(group)); 36 } 33 } 37 34 38 SYSCALL_DEFINE2(setregid16, old_gid_t, rgid, o 35 SYSCALL_DEFINE2(setregid16, old_gid_t, rgid, old_gid_t, egid) 39 { 36 { 40 return __sys_setregid(low2highgid(rgid !! 37 return sys_setregid(low2highgid(rgid), low2highgid(egid)); 41 } 38 } 42 39 43 SYSCALL_DEFINE1(setgid16, old_gid_t, gid) 40 SYSCALL_DEFINE1(setgid16, old_gid_t, gid) 44 { 41 { 45 return __sys_setgid(low2highgid(gid)); !! 42 return sys_setgid(low2highgid(gid)); 46 } 43 } 47 44 48 SYSCALL_DEFINE2(setreuid16, old_uid_t, ruid, o 45 SYSCALL_DEFINE2(setreuid16, old_uid_t, ruid, old_uid_t, euid) 49 { 46 { 50 return __sys_setreuid(low2highuid(ruid !! 47 return sys_setreuid(low2highuid(ruid), low2highuid(euid)); 51 } 48 } 52 49 53 SYSCALL_DEFINE1(setuid16, old_uid_t, uid) 50 SYSCALL_DEFINE1(setuid16, old_uid_t, uid) 54 { 51 { 55 return __sys_setuid(low2highuid(uid)); !! 52 return sys_setuid(low2highuid(uid)); 56 } 53 } 57 54 58 SYSCALL_DEFINE3(setresuid16, old_uid_t, ruid, 55 SYSCALL_DEFINE3(setresuid16, old_uid_t, ruid, old_uid_t, euid, old_uid_t, suid) 59 { 56 { 60 return __sys_setresuid(low2highuid(rui !! 57 return sys_setresuid(low2highuid(ruid), low2highuid(euid), 61 low2highuid(s 58 low2highuid(suid)); 62 } 59 } 63 60 64 SYSCALL_DEFINE3(getresuid16, old_uid_t __user 61 SYSCALL_DEFINE3(getresuid16, old_uid_t __user *, ruidp, old_uid_t __user *, euidp, old_uid_t __user *, suidp) 65 { 62 { 66 const struct cred *cred = current_cred 63 const struct cred *cred = current_cred(); 67 int retval; 64 int retval; 68 old_uid_t ruid, euid, suid; 65 old_uid_t ruid, euid, suid; 69 66 70 ruid = high2lowuid(from_kuid_munged(cr 67 ruid = high2lowuid(from_kuid_munged(cred->user_ns, cred->uid)); 71 euid = high2lowuid(from_kuid_munged(cr 68 euid = high2lowuid(from_kuid_munged(cred->user_ns, cred->euid)); 72 suid = high2lowuid(from_kuid_munged(cr 69 suid = high2lowuid(from_kuid_munged(cred->user_ns, cred->suid)); 73 70 74 if (!(retval = put_user(ruid, ruidp) 71 if (!(retval = put_user(ruid, ruidp)) && 75 !(retval = put_user(euid, euidp) 72 !(retval = put_user(euid, euidp))) 76 retval = put_user(suid, suidp) 73 retval = put_user(suid, suidp); 77 74 78 return retval; 75 return retval; 79 } 76 } 80 77 81 SYSCALL_DEFINE3(setresgid16, old_gid_t, rgid, 78 SYSCALL_DEFINE3(setresgid16, old_gid_t, rgid, old_gid_t, egid, old_gid_t, sgid) 82 { 79 { 83 return __sys_setresgid(low2highgid(rgi !! 80 return sys_setresgid(low2highgid(rgid), low2highgid(egid), 84 low2highgid(s 81 low2highgid(sgid)); 85 } 82 } 86 83 >> 84 87 SYSCALL_DEFINE3(getresgid16, old_gid_t __user 85 SYSCALL_DEFINE3(getresgid16, old_gid_t __user *, rgidp, old_gid_t __user *, egidp, old_gid_t __user *, sgidp) 88 { 86 { 89 const struct cred *cred = current_cred 87 const struct cred *cred = current_cred(); 90 int retval; 88 int retval; 91 old_gid_t rgid, egid, sgid; 89 old_gid_t rgid, egid, sgid; 92 90 93 rgid = high2lowgid(from_kgid_munged(cr 91 rgid = high2lowgid(from_kgid_munged(cred->user_ns, cred->gid)); 94 egid = high2lowgid(from_kgid_munged(cr 92 egid = high2lowgid(from_kgid_munged(cred->user_ns, cred->egid)); 95 sgid = high2lowgid(from_kgid_munged(cr 93 sgid = high2lowgid(from_kgid_munged(cred->user_ns, cred->sgid)); 96 94 97 if (!(retval = put_user(rgid, rgidp) 95 if (!(retval = put_user(rgid, rgidp)) && 98 !(retval = put_user(egid, egidp) 96 !(retval = put_user(egid, egidp))) 99 retval = put_user(sgid, sgidp) 97 retval = put_user(sgid, sgidp); 100 98 101 return retval; 99 return retval; 102 } 100 } 103 101 104 SYSCALL_DEFINE1(setfsuid16, old_uid_t, uid) 102 SYSCALL_DEFINE1(setfsuid16, old_uid_t, uid) 105 { 103 { 106 return __sys_setfsuid(low2highuid(uid) !! 104 return sys_setfsuid(low2highuid(uid)); 107 } 105 } 108 106 109 SYSCALL_DEFINE1(setfsgid16, old_gid_t, gid) 107 SYSCALL_DEFINE1(setfsgid16, old_gid_t, gid) 110 { 108 { 111 return __sys_setfsgid(low2highgid(gid) !! 109 return sys_setfsgid(low2highgid(gid)); 112 } 110 } 113 111 114 static int groups16_to_user(old_gid_t __user * 112 static int groups16_to_user(old_gid_t __user *grouplist, 115 struct group_info *group_info) 113 struct group_info *group_info) 116 { 114 { 117 struct user_namespace *user_ns = curre 115 struct user_namespace *user_ns = current_user_ns(); 118 int i; 116 int i; 119 old_gid_t group; 117 old_gid_t group; 120 kgid_t kgid; 118 kgid_t kgid; 121 119 122 for (i = 0; i < group_info->ngroups; i 120 for (i = 0; i < group_info->ngroups; i++) { 123 kgid = group_info->gid[i]; 121 kgid = group_info->gid[i]; 124 group = high2lowgid(from_kgid_ 122 group = high2lowgid(from_kgid_munged(user_ns, kgid)); 125 if (put_user(group, grouplist+ 123 if (put_user(group, grouplist+i)) 126 return -EFAULT; 124 return -EFAULT; 127 } 125 } 128 126 129 return 0; 127 return 0; 130 } 128 } 131 129 132 static int groups16_from_user(struct group_inf 130 static int groups16_from_user(struct group_info *group_info, 133 old_gid_t __user *grouplist) 131 old_gid_t __user *grouplist) 134 { 132 { 135 struct user_namespace *user_ns = curre 133 struct user_namespace *user_ns = current_user_ns(); 136 int i; 134 int i; 137 old_gid_t group; 135 old_gid_t group; 138 kgid_t kgid; 136 kgid_t kgid; 139 137 140 for (i = 0; i < group_info->ngroups; i 138 for (i = 0; i < group_info->ngroups; i++) { 141 if (get_user(group, grouplist+ 139 if (get_user(group, grouplist+i)) 142 return -EFAULT; 140 return -EFAULT; 143 141 144 kgid = make_kgid(user_ns, low2 142 kgid = make_kgid(user_ns, low2highgid(group)); 145 if (!gid_valid(kgid)) 143 if (!gid_valid(kgid)) 146 return -EINVAL; 144 return -EINVAL; 147 145 148 group_info->gid[i] = kgid; 146 group_info->gid[i] = kgid; 149 } 147 } 150 148 151 return 0; 149 return 0; 152 } 150 } 153 151 154 SYSCALL_DEFINE2(getgroups16, int, gidsetsize, 152 SYSCALL_DEFINE2(getgroups16, int, gidsetsize, old_gid_t __user *, grouplist) 155 { 153 { 156 const struct cred *cred = current_cred 154 const struct cred *cred = current_cred(); 157 int i; 155 int i; 158 156 159 if (gidsetsize < 0) 157 if (gidsetsize < 0) 160 return -EINVAL; 158 return -EINVAL; 161 159 162 i = cred->group_info->ngroups; 160 i = cred->group_info->ngroups; 163 if (gidsetsize) { 161 if (gidsetsize) { 164 if (i > gidsetsize) { 162 if (i > gidsetsize) { 165 i = -EINVAL; 163 i = -EINVAL; 166 goto out; 164 goto out; 167 } 165 } 168 if (groups16_to_user(grouplist 166 if (groups16_to_user(grouplist, cred->group_info)) { 169 i = -EFAULT; 167 i = -EFAULT; 170 goto out; 168 goto out; 171 } 169 } 172 } 170 } 173 out: 171 out: 174 return i; 172 return i; 175 } 173 } 176 174 177 SYSCALL_DEFINE2(setgroups16, int, gidsetsize, 175 SYSCALL_DEFINE2(setgroups16, int, gidsetsize, old_gid_t __user *, grouplist) 178 { 176 { 179 struct group_info *group_info; 177 struct group_info *group_info; 180 int retval; 178 int retval; 181 179 182 if (!may_setgroups()) 180 if (!may_setgroups()) 183 return -EPERM; 181 return -EPERM; 184 if ((unsigned)gidsetsize > NGROUPS_MAX 182 if ((unsigned)gidsetsize > NGROUPS_MAX) 185 return -EINVAL; 183 return -EINVAL; 186 184 187 group_info = groups_alloc(gidsetsize); 185 group_info = groups_alloc(gidsetsize); 188 if (!group_info) 186 if (!group_info) 189 return -ENOMEM; 187 return -ENOMEM; 190 retval = groups16_from_user(group_info 188 retval = groups16_from_user(group_info, grouplist); 191 if (retval) { 189 if (retval) { 192 put_group_info(group_info); 190 put_group_info(group_info); 193 return retval; 191 return retval; 194 } 192 } 195 193 196 groups_sort(group_info); << 197 retval = set_current_groups(group_info 194 retval = set_current_groups(group_info); 198 put_group_info(group_info); 195 put_group_info(group_info); 199 196 200 return retval; 197 return retval; 201 } 198 } 202 199 203 SYSCALL_DEFINE0(getuid16) 200 SYSCALL_DEFINE0(getuid16) 204 { 201 { 205 return high2lowuid(from_kuid_munged(cu 202 return high2lowuid(from_kuid_munged(current_user_ns(), current_uid())); 206 } 203 } 207 204 208 SYSCALL_DEFINE0(geteuid16) 205 SYSCALL_DEFINE0(geteuid16) 209 { 206 { 210 return high2lowuid(from_kuid_munged(cu 207 return high2lowuid(from_kuid_munged(current_user_ns(), current_euid())); 211 } 208 } 212 209 213 SYSCALL_DEFINE0(getgid16) 210 SYSCALL_DEFINE0(getgid16) 214 { 211 { 215 return high2lowgid(from_kgid_munged(cu 212 return high2lowgid(from_kgid_munged(current_user_ns(), current_gid())); 216 } 213 } 217 214 218 SYSCALL_DEFINE0(getegid16) 215 SYSCALL_DEFINE0(getegid16) 219 { 216 { 220 return high2lowgid(from_kgid_munged(cu 217 return high2lowgid(from_kgid_munged(current_user_ns(), current_egid())); 221 } 218 } 222 219
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.