ptrace: ensure JOBCTL_STOP_SIGMASK is not zero after detach
[pandora-kernel.git] / kernel / signal.c
index 291c970..2065515 100644 (file)
@@ -11,7 +11,7 @@
  */
 
 #include <linux/slab.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/fs.h>
@@ -1344,13 +1344,24 @@ int kill_proc_info(int sig, struct siginfo *info, pid_t pid)
        return error;
 }
 
+static int kill_as_cred_perm(const struct cred *cred,
+                            struct task_struct *target)
+{
+       const struct cred *pcred = __task_cred(target);
+       if (cred->user_ns != pcred->user_ns)
+               return 0;
+       if (cred->euid != pcred->suid && cred->euid != pcred->uid &&
+           cred->uid  != pcred->suid && cred->uid  != pcred->uid)
+               return 0;
+       return 1;
+}
+
 /* like kill_pid_info(), but doesn't use uid/euid of "current" */
-int kill_pid_info_as_uid(int sig, struct siginfo *info, struct pid *pid,
-                     uid_t uid, uid_t euid, u32 secid)
+int kill_pid_info_as_cred(int sig, struct siginfo *info, struct pid *pid,
+                        const struct cred *cred, u32 secid)
 {
        int ret = -EINVAL;
        struct task_struct *p;
-       const struct cred *pcred;
        unsigned long flags;
 
        if (!valid_signal(sig))
@@ -1362,10 +1373,7 @@ int kill_pid_info_as_uid(int sig, struct siginfo *info, struct pid *pid,
                ret = -ESRCH;
                goto out_unlock;
        }
-       pcred = __task_cred(p);
-       if (si_fromuser(info) &&
-           euid != pcred->suid && euid != pcred->uid &&
-           uid  != pcred->suid && uid  != pcred->uid) {
+       if (si_fromuser(info) && !kill_as_cred_perm(cred, p)) {
                ret = -EPERM;
                goto out_unlock;
        }
@@ -1384,7 +1392,7 @@ out_unlock:
        rcu_read_unlock();
        return ret;
 }
-EXPORT_SYMBOL_GPL(kill_pid_info_as_uid);
+EXPORT_SYMBOL_GPL(kill_pid_info_as_cred);
 
 /*
  * kill_something_info() interprets pid in interesting ways just like kill(2).
@@ -1986,8 +1994,6 @@ static bool do_signal_stop(int signr)
                 */
                if (!(sig->flags & SIGNAL_STOP_STOPPED))
                        sig->group_exit_code = signr;
-               else
-                       WARN_ON_ONCE(!current->ptrace);
 
                sig->group_stop_count = 0;