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