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