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 *, ruid, old_uid_t __user *, euid, old_uid_t __user *, suid)
  85{
  86        const struct cred *cred = current_cred();
  87        int retval;
  88
  89        if (!(retval   = put_user(high2lowuid(cred->uid),  ruid)) &&
  90            !(retval   = put_user(high2lowuid(cred->euid), euid)))
  91                retval = put_user(high2lowuid(cred->suid), suid);
  92
  93        return retval;
  94}
  95
  96SYSCALL_DEFINE3(setresgid16, old_gid_t, rgid, old_gid_t, egid, old_gid_t, sgid)
  97{
  98        long ret = sys_setresgid(low2highgid(rgid), low2highgid(egid),
  99                                 low2highgid(sgid));
 100        /* avoid REGPARM breakage on x86: */
 101        asmlinkage_protect(3, ret, rgid, egid, sgid);
 102        return ret;
 103}
 104
 105
 106SYSCALL_DEFINE3(getresgid16, old_gid_t __user *, rgid, old_gid_t __user *, egid, old_gid_t __user *, sgid)
 107{
 108        const struct cred *cred = current_cred();
 109        int retval;
 110
 111        if (!(retval   = put_user(high2lowgid(cred->gid),  rgid)) &&
 112            !(retval   = put_user(high2lowgid(cred->egid), egid)))
 113                retval = put_user(high2lowgid(cred->sgid), sgid);
 114
 115        return retval;
 116}
 117
 118SYSCALL_DEFINE1(setfsuid16, old_uid_t, uid)
 119{
 120        long ret = sys_setfsuid(low2highuid(uid));
 121        /* avoid REGPARM breakage on x86: */
 122        asmlinkage_protect(1, ret, uid);
 123        return ret;
 124}
 125
 126SYSCALL_DEFINE1(setfsgid16, old_gid_t, gid)
 127{
 128        long ret = sys_setfsgid(low2highgid(gid));
 129        /* avoid REGPARM breakage on x86: */
 130        asmlinkage_protect(1, ret, gid);
 131        return ret;
 132}
 133
 134static int groups16_to_user(old_gid_t __user *grouplist,
 135    struct group_info *group_info)
 136{
 137        int i;
 138        old_gid_t group;
 139
 140        for (i = 0; i < group_info->ngroups; i++) {
 141                group = high2lowgid(GROUP_AT(group_info, i));
 142                if (put_user(group, grouplist+i))
 143                        return -EFAULT;
 144        }
 145
 146        return 0;
 147}
 148
 149static int groups16_from_user(struct group_info *group_info,
 150    old_gid_t __user *grouplist)
 151{
 152        int i;
 153        old_gid_t group;
 154
 155        for (i = 0; i < group_info->ngroups; i++) {
 156                if (get_user(group, grouplist+i))
 157                        return  -EFAULT;
 158                GROUP_AT(group_info, i) = low2highgid(group);
 159        }
 160
 161        return 0;
 162}
 163
 164SYSCALL_DEFINE2(getgroups16, int, gidsetsize, old_gid_t __user *, grouplist)
 165{
 166        const struct cred *cred = current_cred();
 167        int i;
 168
 169        if (gidsetsize < 0)
 170                return -EINVAL;
 171
 172        i = cred->group_info->ngroups;
 173        if (gidsetsize) {
 174                if (i > gidsetsize) {
 175                        i = -EINVAL;
 176                        goto out;
 177                }
 178                if (groups16_to_user(grouplist, cred->group_info)) {
 179                        i = -EFAULT;
 180                        goto out;
 181                }
 182        }
 183out:
 184        return i;
 185}
 186
 187SYSCALL_DEFINE2(setgroups16, int, gidsetsize, old_gid_t __user *, grouplist)
 188{
 189        struct group_info *group_info;
 190        int retval;
 191
 192        if (!capable(CAP_SETGID))
 193                return -EPERM;
 194        if ((unsigned)gidsetsize > NGROUPS_MAX)
 195                return -EINVAL;
 196
 197        group_info = groups_alloc(gidsetsize);
 198        if (!group_info)
 199                return -ENOMEM;
 200        retval = groups16_from_user(group_info, grouplist);
 201        if (retval) {
 202                put_group_info(group_info);
 203                return retval;
 204        }
 205
 206        retval = set_current_groups(group_info);
 207        put_group_info(group_info);
 208
 209        return retval;
 210}
 211
 212SYSCALL_DEFINE0(getuid16)
 213{
 214        return high2lowuid(current_uid());
 215}
 216
 217SYSCALL_DEFINE0(geteuid16)
 218{
 219        return high2lowuid(current_euid());
 220}
 221
 222SYSCALL_DEFINE0(getgid16)
 223{
 224        return high2lowgid(current_gid());
 225}
 226
 227SYSCALL_DEFINE0(getegid16)
 228{
 229        return high2lowgid(current_egid());
 230}
 231