Back to home page

LXR

 
 

    


0001 /*
0002  *  Wrapper functions for 16bit uid back compatibility. All nicely tied
0003  *  together in the faint hope we can take the out in five years time.
0004  */
0005 
0006 #include <linux/mm.h>
0007 #include <linux/mman.h>
0008 #include <linux/notifier.h>
0009 #include <linux/reboot.h>
0010 #include <linux/prctl.h>
0011 #include <linux/capability.h>
0012 #include <linux/init.h>
0013 #include <linux/highuid.h>
0014 #include <linux/security.h>
0015 #include <linux/syscalls.h>
0016 
0017 #include <linux/uaccess.h>
0018 
0019 SYSCALL_DEFINE3(chown16, const char __user *, filename, old_uid_t, user, old_gid_t, group)
0020 {
0021     return sys_chown(filename, low2highuid(user), low2highgid(group));
0022 }
0023 
0024 SYSCALL_DEFINE3(lchown16, const char __user *, filename, old_uid_t, user, old_gid_t, group)
0025 {
0026     return sys_lchown(filename, low2highuid(user), low2highgid(group));
0027 }
0028 
0029 SYSCALL_DEFINE3(fchown16, unsigned int, fd, old_uid_t, user, old_gid_t, group)
0030 {
0031     return sys_fchown(fd, low2highuid(user), low2highgid(group));
0032 }
0033 
0034 SYSCALL_DEFINE2(setregid16, old_gid_t, rgid, old_gid_t, egid)
0035 {
0036     return sys_setregid(low2highgid(rgid), low2highgid(egid));
0037 }
0038 
0039 SYSCALL_DEFINE1(setgid16, old_gid_t, gid)
0040 {
0041     return sys_setgid(low2highgid(gid));
0042 }
0043 
0044 SYSCALL_DEFINE2(setreuid16, old_uid_t, ruid, old_uid_t, euid)
0045 {
0046     return sys_setreuid(low2highuid(ruid), low2highuid(euid));
0047 }
0048 
0049 SYSCALL_DEFINE1(setuid16, old_uid_t, uid)
0050 {
0051     return sys_setuid(low2highuid(uid));
0052 }
0053 
0054 SYSCALL_DEFINE3(setresuid16, old_uid_t, ruid, old_uid_t, euid, old_uid_t, suid)
0055 {
0056     return sys_setresuid(low2highuid(ruid), low2highuid(euid),
0057                  low2highuid(suid));
0058 }
0059 
0060 SYSCALL_DEFINE3(getresuid16, old_uid_t __user *, ruidp, old_uid_t __user *, euidp, old_uid_t __user *, suidp)
0061 {
0062     const struct cred *cred = current_cred();
0063     int retval;
0064     old_uid_t ruid, euid, suid;
0065 
0066     ruid = high2lowuid(from_kuid_munged(cred->user_ns, cred->uid));
0067     euid = high2lowuid(from_kuid_munged(cred->user_ns, cred->euid));
0068     suid = high2lowuid(from_kuid_munged(cred->user_ns, cred->suid));
0069 
0070     if (!(retval   = put_user(ruid, ruidp)) &&
0071         !(retval   = put_user(euid, euidp)))
0072         retval = put_user(suid, suidp);
0073 
0074     return retval;
0075 }
0076 
0077 SYSCALL_DEFINE3(setresgid16, old_gid_t, rgid, old_gid_t, egid, old_gid_t, sgid)
0078 {
0079     return sys_setresgid(low2highgid(rgid), low2highgid(egid),
0080                  low2highgid(sgid));
0081 }
0082 
0083 
0084 SYSCALL_DEFINE3(getresgid16, old_gid_t __user *, rgidp, old_gid_t __user *, egidp, old_gid_t __user *, sgidp)
0085 {
0086     const struct cred *cred = current_cred();
0087     int retval;
0088     old_gid_t rgid, egid, sgid;
0089 
0090     rgid = high2lowgid(from_kgid_munged(cred->user_ns, cred->gid));
0091     egid = high2lowgid(from_kgid_munged(cred->user_ns, cred->egid));
0092     sgid = high2lowgid(from_kgid_munged(cred->user_ns, cred->sgid));
0093 
0094     if (!(retval   = put_user(rgid, rgidp)) &&
0095         !(retval   = put_user(egid, egidp)))
0096         retval = put_user(sgid, sgidp);
0097 
0098     return retval;
0099 }
0100 
0101 SYSCALL_DEFINE1(setfsuid16, old_uid_t, uid)
0102 {
0103     return sys_setfsuid(low2highuid(uid));
0104 }
0105 
0106 SYSCALL_DEFINE1(setfsgid16, old_gid_t, gid)
0107 {
0108     return sys_setfsgid(low2highgid(gid));
0109 }
0110 
0111 static int groups16_to_user(old_gid_t __user *grouplist,
0112     struct group_info *group_info)
0113 {
0114     struct user_namespace *user_ns = current_user_ns();
0115     int i;
0116     old_gid_t group;
0117     kgid_t kgid;
0118 
0119     for (i = 0; i < group_info->ngroups; i++) {
0120         kgid = group_info->gid[i];
0121         group = high2lowgid(from_kgid_munged(user_ns, kgid));
0122         if (put_user(group, grouplist+i))
0123             return -EFAULT;
0124     }
0125 
0126     return 0;
0127 }
0128 
0129 static int groups16_from_user(struct group_info *group_info,
0130     old_gid_t __user *grouplist)
0131 {
0132     struct user_namespace *user_ns = current_user_ns();
0133     int i;
0134     old_gid_t group;
0135     kgid_t kgid;
0136 
0137     for (i = 0; i < group_info->ngroups; i++) {
0138         if (get_user(group, grouplist+i))
0139             return  -EFAULT;
0140 
0141         kgid = make_kgid(user_ns, low2highgid(group));
0142         if (!gid_valid(kgid))
0143             return -EINVAL;
0144 
0145         group_info->gid[i] = kgid;
0146     }
0147 
0148     return 0;
0149 }
0150 
0151 SYSCALL_DEFINE2(getgroups16, int, gidsetsize, old_gid_t __user *, grouplist)
0152 {
0153     const struct cred *cred = current_cred();
0154     int i;
0155 
0156     if (gidsetsize < 0)
0157         return -EINVAL;
0158 
0159     i = cred->group_info->ngroups;
0160     if (gidsetsize) {
0161         if (i > gidsetsize) {
0162             i = -EINVAL;
0163             goto out;
0164         }
0165         if (groups16_to_user(grouplist, cred->group_info)) {
0166             i = -EFAULT;
0167             goto out;
0168         }
0169     }
0170 out:
0171     return i;
0172 }
0173 
0174 SYSCALL_DEFINE2(setgroups16, int, gidsetsize, old_gid_t __user *, grouplist)
0175 {
0176     struct group_info *group_info;
0177     int retval;
0178 
0179     if (!may_setgroups())
0180         return -EPERM;
0181     if ((unsigned)gidsetsize > NGROUPS_MAX)
0182         return -EINVAL;
0183 
0184     group_info = groups_alloc(gidsetsize);
0185     if (!group_info)
0186         return -ENOMEM;
0187     retval = groups16_from_user(group_info, grouplist);
0188     if (retval) {
0189         put_group_info(group_info);
0190         return retval;
0191     }
0192 
0193     retval = set_current_groups(group_info);
0194     put_group_info(group_info);
0195 
0196     return retval;
0197 }
0198 
0199 SYSCALL_DEFINE0(getuid16)
0200 {
0201     return high2lowuid(from_kuid_munged(current_user_ns(), current_uid()));
0202 }
0203 
0204 SYSCALL_DEFINE0(geteuid16)
0205 {
0206     return high2lowuid(from_kuid_munged(current_user_ns(), current_euid()));
0207 }
0208 
0209 SYSCALL_DEFINE0(getgid16)
0210 {
0211     return high2lowgid(from_kgid_munged(current_user_ns(), current_gid()));
0212 }
0213 
0214 SYSCALL_DEFINE0(getegid16)
0215 {
0216     return high2lowgid(from_kgid_munged(current_user_ns(), current_egid()));
0217 }