]> Pileus Git - ~andy/linux/blobdiff - kernel/ptrace.c
Merge branch 'tracing-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[~andy/linux] / kernel / ptrace.c
index 100a71cfdabac3200d87e2ac7037847dee28a27e..29dc700e198cb71f3854aa632078f5d3d529c1a0 100644 (file)
@@ -127,6 +127,8 @@ int ptrace_check_attach(struct task_struct *child, int kill)
 
 int __ptrace_may_access(struct task_struct *task, unsigned int mode)
 {
+       const struct cred *cred = current_cred(), *tcred;
+
        /* May we inspect the given task?
         * This check is used both for attaching with ptrace
         * and for allowing access to sensitive information in /proc.
@@ -139,13 +141,19 @@ int __ptrace_may_access(struct task_struct *task, unsigned int mode)
        /* 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))
+       rcu_read_lock();
+       tcred = __task_cred(task);
+       if ((cred->uid != tcred->euid ||
+            cred->uid != tcred->suid ||
+            cred->uid != tcred->uid  ||
+            cred->gid != tcred->egid ||
+            cred->gid != tcred->sgid ||
+            cred->gid != tcred->gid) &&
+           !capable(CAP_SYS_PTRACE)) {
+               rcu_read_unlock();
                return -EPERM;
+       }
+       rcu_read_unlock();
        smp_rmb();
        if (task->mm)
                dumpable = get_dumpable(task->mm);
@@ -175,6 +183,14 @@ int ptrace_attach(struct task_struct *task)
        if (same_thread_group(task, current))
                goto out;
 
+       /* Protect exec's credential calculations against our interference;
+        * SUID, SGID and LSM creds get determined differently under ptrace.
+        */
+       retval = mutex_lock_interruptible(&current->cred_exec_mutex);
+       if (retval  < 0)
+               goto out;
+
+       retval = -EPERM;
 repeat:
        /*
         * Nasty, nasty.
@@ -214,6 +230,7 @@ repeat:
 bad:
        write_unlock_irqrestore(&tasklist_lock, flags);
        task_unlock(task);
+       mutex_unlock(&current->cred_exec_mutex);
 out:
        return retval;
 }