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