CRED: Wrap task credential accesses in the core kernel
David Howells [Thu, 13 Nov 2008 23:39:12 +0000 (10:39 +1100)]
Wrap access to task credentials so that they can be separated more easily from
the task_struct during the introduction of COW creds.

Change most current->(|e|s|fs)[ug]id to current_(|e|s|fs)[ug]id().

Change some task->e?[ug]id to task_e?[ug]id().  In some places it makes more
sense to use RCU directly rather than a convenient wrapper; these will be
addressed by later patches.

Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: James Morris <jmorris@namei.org>
Acked-by: Serge Hallyn <serue@us.ibm.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: linux-audit@redhat.com
Cc: containers@lists.linux-foundation.org
Cc: linux-mm@kvack.org
Signed-off-by: James Morris <jmorris@namei.org>

15 files changed:
kernel/acct.c
kernel/auditsc.c
kernel/cgroup.c
kernel/futex.c
kernel/futex_compat.c
kernel/ptrace.c
kernel/sched.c
kernel/signal.c
kernel/sys.c
kernel/sysctl.c
kernel/timer.c
kernel/user_namespace.c
mm/mempolicy.c
mm/migrate.c
mm/shmem.c

index f6006a6..d57b7cb 100644 (file)
@@ -530,15 +530,14 @@ static void do_acct_process(struct bsd_acct_struct *acct,
        do_div(elapsed, AHZ);
        ac.ac_btime = get_seconds() - elapsed;
        /* we really need to bite the bullet and change layout */
-       ac.ac_uid = current->uid;
-       ac.ac_gid = current->gid;
+       current_uid_gid(&ac.ac_uid, &ac.ac_gid);
 #if ACCT_VERSION==2
        ac.ac_ahz = AHZ;
 #endif
 #if ACCT_VERSION==1 || ACCT_VERSION==2
        /* backward-compatible 16 bit fields */
-       ac.ac_uid16 = current->uid;
-       ac.ac_gid16 = current->gid;
+       ac.ac_uid16 = ac.ac_uid;
+       ac.ac_gid16 = ac.ac_gid;
 #endif
 #if ACCT_VERSION==3
        ac.ac_pid = task_tgid_nr_ns(current, ns);
index cef3423..9c7e47a 100644 (file)
@@ -2628,7 +2628,8 @@ void audit_core_dumps(long signr)
 {
        struct audit_buffer *ab;
        u32 sid;
-       uid_t auid = audit_get_loginuid(current);
+       uid_t auid = audit_get_loginuid(current), uid;
+       gid_t gid;
        unsigned int sessionid = audit_get_sessionid(current);
 
        if (!audit_enabled)
@@ -2638,8 +2639,9 @@ void audit_core_dumps(long signr)
                return;
 
        ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND);
+       current_uid_gid(&uid, &gid);
        audit_log_format(ab, "auid=%u uid=%u gid=%u ses=%u",
-                       auid, current->uid, current->gid, sessionid);
+                        auid, uid, gid, sessionid);
        security_task_getsecid(current, &sid);
        if (sid) {
                char *ctx = NULL;
index 35eebd5..78f9b31 100644 (file)
@@ -571,8 +571,8 @@ static struct inode *cgroup_new_inode(mode_t mode, struct super_block *sb)
 
        if (inode) {
                inode->i_mode = mode;
-               inode->i_uid = current->fsuid;
-               inode->i_gid = current->fsgid;
+               inode->i_uid = current_fsuid();
+               inode->i_gid = current_fsgid();
                inode->i_blocks = 0;
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
                inode->i_mapping->backing_dev_info = &cgroup_backing_dev_info;
@@ -1279,6 +1279,7 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
 static int attach_task_by_pid(struct cgroup *cgrp, u64 pid)
 {
        struct task_struct *tsk;
+       uid_t euid;
        int ret;
 
        if (pid) {
@@ -1291,8 +1292,8 @@ static int attach_task_by_pid(struct cgroup *cgrp, u64 pid)
                get_task_struct(tsk);
                rcu_read_unlock();
 
-               if ((current->euid) && (current->euid != tsk->uid)
-                   && (current->euid != tsk->suid)) {
+               euid = current_euid();
+               if (euid && euid != tsk->uid && euid != tsk->suid) {
                        put_task_struct(tsk);
                        return -EACCES;
                }
index 8af1002..e069621 100644 (file)
@@ -439,10 +439,11 @@ static void free_pi_state(struct futex_pi_state *pi_state)
 static struct task_struct * futex_find_get_task(pid_t pid)
 {
        struct task_struct *p;
+       uid_t euid = current_euid();
 
        rcu_read_lock();
        p = find_task_by_vpid(pid);
-       if (!p || ((current->euid != p->euid) && (current->euid != p->uid)))
+       if (!p || (euid != p->euid && euid != p->uid))
                p = ERR_PTR(-ESRCH);
        else
                get_task_struct(p);
@@ -1829,6 +1830,7 @@ sys_get_robust_list(int pid, struct robust_list_head __user * __user *head_ptr,
 {
        struct robust_list_head __user *head;
        unsigned long ret;
+       uid_t euid = current_euid();
 
        if (!futex_cmpxchg_enabled)
                return -ENOSYS;
@@ -1844,8 +1846,8 @@ sys_get_robust_list(int pid, struct robust_list_head __user * __user *head_ptr,
                if (!p)
                        goto err_unlock;
                ret = -EPERM;
-               if ((current->euid != p->euid) && (current->euid != p->uid) &&
-                               !capable(CAP_SYS_PTRACE))
+               if (euid != p->euid && euid != p->uid &&
+                   !capable(CAP_SYS_PTRACE))
                        goto err_unlock;
                head = p->robust_list;
                rcu_read_unlock();
index 04ac3a9..3254d4e 100644 (file)
@@ -135,6 +135,7 @@ compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr,
 {
        struct compat_robust_list_head __user *head;
        unsigned long ret;
+       uid_t euid = current_euid();
 
        if (!futex_cmpxchg_enabled)
                return -ENOSYS;
@@ -150,7 +151,7 @@ compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr,
                if (!p)
                        goto err_unlock;
                ret = -EPERM;
-               if ((current->euid != p->euid) && (current->euid != p->uid) &&
+               if (euid != p->euid && euid != p->uid &&
                                !capable(CAP_SYS_PTRACE))
                        goto err_unlock;
                head = p->compat_robust_list;
index 1e68e4c..937f6b5 100644 (file)
@@ -123,16 +123,19 @@ int __ptrace_may_access(struct task_struct *task, unsigned int mode)
         * because setting up the necessary parent/child relationship
         * or halting the specified task is impossible.
         */
+       uid_t uid;
+       gid_t gid;
        int dumpable = 0;
        /* Don't let security modules deny introspection */
        if (task == current)
                return 0;
-       if (((current->uid != task->euid) ||
-            (current->uid != task->suid) ||
-            (current->uid != task->uid) ||
-            (current->gid != task->egid) ||
-            (current->gid != task->sgid) ||
-            (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
+       current_uid_gid(&uid, &gid);
+       if ((uid != task->euid ||
+            uid != task->suid ||
+            uid != task->uid  ||
+            gid != task->egid ||
+            gid != task->sgid ||
+            gid != task->gid) && !capable(CAP_SYS_PTRACE))
                return -EPERM;
        smp_rmb();
        if (task->mm)
index e8819bc..c3b8b1f 100644 (file)
@@ -5128,6 +5128,7 @@ static int __sched_setscheduler(struct task_struct *p, int policy,
        unsigned long flags;
        const struct sched_class *prev_class = p->sched_class;
        struct rq *rq;
+       uid_t euid;
 
        /* may grab non-irq protected spin_locks */
        BUG_ON(in_interrupt());
@@ -5180,8 +5181,9 @@ recheck:
                        return -EPERM;
 
                /* can't change other user's priorities */
-               if ((current->euid != p->euid) &&
-                   (current->euid != p->uid))
+               euid = current_euid();
+               if (euid != p->euid &&
+                   euid != p->uid)
                        return -EPERM;
        }
 
@@ -5392,6 +5394,7 @@ long sched_setaffinity(pid_t pid, const cpumask_t *in_mask)
        cpumask_t cpus_allowed;
        cpumask_t new_mask = *in_mask;
        struct task_struct *p;
+       uid_t euid;
        int retval;
 
        get_online_cpus();
@@ -5412,9 +5415,9 @@ long sched_setaffinity(pid_t pid, const cpumask_t *in_mask)
        get_task_struct(p);
        read_unlock(&tasklist_lock);
 
+       euid = current_euid();
        retval = -EPERM;
-       if ((current->euid != p->euid) && (current->euid != p->uid) &&
-                       !capable(CAP_SYS_NICE))
+       if (euid != p->euid && euid != p->uid && !capable(CAP_SYS_NICE))
                goto out_unlock;
 
        retval = security_task_setscheduler(p, 0, NULL);
index 4530fc6..167b535 100644 (file)
@@ -567,6 +567,7 @@ static int check_kill_permission(int sig, struct siginfo *info,
                                 struct task_struct *t)
 {
        struct pid *sid;
+       uid_t uid, euid;
        int error;
 
        if (!valid_signal(sig))
@@ -579,8 +580,10 @@ static int check_kill_permission(int sig, struct siginfo *info,
        if (error)
                return error;
 
-       if ((current->euid ^ t->suid) && (current->euid ^ t->uid) &&
-           (current->uid  ^ t->suid) && (current->uid  ^ t->uid) &&
+       uid = current_uid();
+       euid = current_euid();
+       if ((euid ^ t->suid) && (euid ^ t->uid) &&
+           (uid  ^ t->suid) && (uid  ^ t->uid) &&
            !capable(CAP_KILL)) {
                switch (sig) {
                case SIGCONT:
@@ -844,7 +847,7 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t,
                        q->info.si_errno = 0;
                        q->info.si_code = SI_USER;
                        q->info.si_pid = task_pid_vnr(current);
-                       q->info.si_uid = current->uid;
+                       q->info.si_uid = current_uid();
                        break;
                case (unsigned long) SEND_SIG_PRIV:
                        q->info.si_signo = sig;
@@ -1598,7 +1601,7 @@ void ptrace_notify(int exit_code)
        info.si_signo = SIGTRAP;
        info.si_code = exit_code;
        info.si_pid = task_pid_vnr(current);
-       info.si_uid = current->uid;
+       info.si_uid = current_uid();
 
        /* Let the debugger run.  */
        spin_lock_irq(&current->sighand->siglock);
@@ -2211,7 +2214,7 @@ sys_kill(pid_t pid, int sig)
        info.si_errno = 0;
        info.si_code = SI_USER;
        info.si_pid = task_tgid_vnr(current);
-       info.si_uid = current->uid;
+       info.si_uid = current_uid();
 
        return kill_something_info(sig, &info, pid);
 }
@@ -2228,7 +2231,7 @@ static int do_tkill(pid_t tgid, pid_t pid, int sig)
        info.si_errno = 0;
        info.si_code = SI_TKILL;
        info.si_pid = task_tgid_vnr(current);
-       info.si_uid = current->uid;
+       info.si_uid = current_uid();
 
        rcu_read_lock();
        p = find_task_by_vpid(pid);
index 31deba8..ed5c29c 100644 (file)
@@ -114,10 +114,10 @@ void (*pm_power_off_prepare)(void);
 
 static int set_one_prio(struct task_struct *p, int niceval, int error)
 {
+       uid_t euid = current_euid();
        int no_nice;
 
-       if (p->uid != current->euid &&
-               p->euid != current->euid && !capable(CAP_SYS_NICE)) {
+       if (p->uid != euid && p->euid != euid && !capable(CAP_SYS_NICE)) {
                error = -EPERM;
                goto out;
        }
@@ -176,16 +176,16 @@ asmlinkage long sys_setpriority(int which, int who, int niceval)
                case PRIO_USER:
                        user = current->user;
                        if (!who)
-                               who = current->uid;
+                               who = current_uid();
                        else
-                               if ((who != current->uid) && !(user = find_user(who)))
+                               if (who != current_uid() && !(user = find_user(who)))
                                        goto out_unlock;        /* No processes for this user */
 
                        do_each_thread(g, p)
                                if (p->uid == who)
                                        error = set_one_prio(p, niceval, error);
                        while_each_thread(g, p);
-                       if (who != current->uid)
+                       if (who != current_uid())
                                free_uid(user);         /* For find_user() */
                        break;
        }
@@ -238,9 +238,9 @@ asmlinkage long sys_getpriority(int which, int who)
                case PRIO_USER:
                        user = current->user;
                        if (!who)
-                               who = current->uid;
+                               who = current_uid();
                        else
-                               if ((who != current->uid) && !(user = find_user(who)))
+                               if (who != current_uid() && !(user = find_user(who)))
                                        goto out_unlock;        /* No processes for this user */
 
                        do_each_thread(g, p)
@@ -250,7 +250,7 @@ asmlinkage long sys_getpriority(int which, int who)
                                                retval = niceval;
                                }
                        while_each_thread(g, p);
-                       if (who != current->uid)
+                       if (who != current_uid())
                                free_uid(user);         /* for find_user() */
                        break;
        }
index 9d048fa..5110313 100644 (file)
@@ -1641,7 +1641,7 @@ out:
 
 static int test_perm(int mode, int op)
 {
-       if (!current->euid)
+       if (!current_euid())
                mode >>= 6;
        else if (in_egroup_p(0))
                mode >>= 3;
index 56becf3..b54e464 100644 (file)
@@ -1123,25 +1123,25 @@ asmlinkage long sys_getppid(void)
 asmlinkage long sys_getuid(void)
 {
        /* Only we change this so SMP safe */
-       return current->uid;
+       return current_uid();
 }
 
 asmlinkage long sys_geteuid(void)
 {
        /* Only we change this so SMP safe */
-       return current->euid;
+       return current_euid();
 }
 
 asmlinkage long sys_getgid(void)
 {
        /* Only we change this so SMP safe */
-       return current->gid;
+       return current_gid();
 }
 
 asmlinkage long sys_getegid(void)
 {
        /* Only we change this so SMP safe */
-       return  current->egid;
+       return  current_egid();
 }
 
 #endif
index 532858f..f82730a 100644 (file)
@@ -38,7 +38,7 @@ static struct user_namespace *clone_user_ns(struct user_namespace *old_ns)
        }
 
        /* Reset current->user with a new one */
-       new_user = alloc_uid(ns, current->uid);
+       new_user = alloc_uid(ns, current_uid());
        if (!new_user) {
                free_uid(ns->root_user);
                kfree(ns);
index 36f4257..07a9647 100644 (file)
@@ -1115,6 +1115,7 @@ asmlinkage long sys_migrate_pages(pid_t pid, unsigned long maxnode,
        nodemask_t old;
        nodemask_t new;
        nodemask_t task_nodes;
+       uid_t uid, euid;
        int err;
 
        err = get_nodes(&old, old_nodes, maxnode);
@@ -1144,8 +1145,10 @@ asmlinkage long sys_migrate_pages(pid_t pid, unsigned long maxnode,
         * capabilities, superuser privileges or the same
         * userid as the target process.
         */
-       if ((current->euid != task->suid) && (current->euid != task->uid) &&
-           (current->uid != task->suid) && (current->uid != task->uid) &&
+       uid = current_uid();
+       euid = current_euid();
+       if (euid != task->suid && euid != task->uid &&
+           uid  != task->suid && uid  != task->uid &&
            !capable(CAP_SYS_NICE)) {
                err = -EPERM;
                goto out;
index 6602941..6263c24 100644 (file)
@@ -1048,6 +1048,7 @@ asmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages,
        struct task_struct *task;
        struct mm_struct *mm;
        int err;
+       uid_t uid, euid;
 
        /* Check flags */
        if (flags & ~(MPOL_MF_MOVE|MPOL_MF_MOVE_ALL))
@@ -1075,8 +1076,10 @@ asmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages,
         * capabilities, superuser privileges or the same
         * userid as the target process.
         */
-       if ((current->euid != task->suid) && (current->euid != task->uid) &&
-           (current->uid != task->suid) && (current->uid != task->uid) &&
+       uid = current_uid();
+       euid = current_euid();
+       if (euid != task->suid && euid != task->uid &&
+           uid  != task->suid && uid  != task->uid &&
            !capable(CAP_SYS_NICE)) {
                err = -EPERM;
                goto out;
index 0ed0752..f1b0d48 100644 (file)
@@ -1513,8 +1513,8 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
        inode = new_inode(sb);
        if (inode) {
                inode->i_mode = mode;
-               inode->i_uid = current->fsuid;
-               inode->i_gid = current->fsgid;
+               inode->i_uid = current_fsuid();
+               inode->i_gid = current_fsgid();
                inode->i_blocks = 0;
                inode->i_mapping->backing_dev_info = &shmem_backing_dev_info;
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
@@ -2278,8 +2278,8 @@ static int shmem_fill_super(struct super_block *sb,
        sbinfo->max_blocks = 0;
        sbinfo->max_inodes = 0;
        sbinfo->mode = S_IRWXUGO | S_ISVTX;
-       sbinfo->uid = current->fsuid;
-       sbinfo->gid = current->fsgid;
+       sbinfo->uid = current_fsuid();
+       sbinfo->gid = current_fsgid();
        sbinfo->mpol = NULL;
        sb->s_fs_info = sbinfo;