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