diff options
Diffstat (limited to 'kernel/signal.c')
-rw-r--r-- | kernel/signal.c | 45 |
1 files changed, 36 insertions, 9 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index e5f8aea78ffe..7fe874d12fae 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -10,7 +10,6 @@ | |||
10 | * to allow signals to be sent reliably. | 10 | * to allow signals to be sent reliably. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/config.h> | ||
14 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
15 | #include <linux/module.h> | 14 | #include <linux/module.h> |
16 | #include <linux/smp_lock.h> | 15 | #include <linux/smp_lock.h> |
@@ -23,12 +22,12 @@ | |||
23 | #include <linux/syscalls.h> | 22 | #include <linux/syscalls.h> |
24 | #include <linux/ptrace.h> | 23 | #include <linux/ptrace.h> |
25 | #include <linux/signal.h> | 24 | #include <linux/signal.h> |
26 | #include <linux/audit.h> | ||
27 | #include <linux/capability.h> | 25 | #include <linux/capability.h> |
28 | #include <asm/param.h> | 26 | #include <asm/param.h> |
29 | #include <asm/uaccess.h> | 27 | #include <asm/uaccess.h> |
30 | #include <asm/unistd.h> | 28 | #include <asm/unistd.h> |
31 | #include <asm/siginfo.h> | 29 | #include <asm/siginfo.h> |
30 | #include "audit.h" /* audit_signal_info() */ | ||
32 | 31 | ||
33 | /* | 32 | /* |
34 | * SLAB caches for signal bits. | 33 | * SLAB caches for signal bits. |
@@ -584,7 +583,7 @@ static int check_kill_permission(int sig, struct siginfo *info, | |||
584 | && !capable(CAP_KILL)) | 583 | && !capable(CAP_KILL)) |
585 | return error; | 584 | return error; |
586 | 585 | ||
587 | error = security_task_kill(t, info, sig); | 586 | error = security_task_kill(t, info, sig, 0); |
588 | if (!error) | 587 | if (!error) |
589 | audit_signal_info(sig, t); /* Let audit system see the signal */ | 588 | audit_signal_info(sig, t); /* Let audit system see the signal */ |
590 | return error; | 589 | return error; |
@@ -1107,7 +1106,7 @@ kill_proc_info(int sig, struct siginfo *info, pid_t pid) | |||
1107 | 1106 | ||
1108 | /* like kill_proc_info(), but doesn't use uid/euid of "current" */ | 1107 | /* like kill_proc_info(), but doesn't use uid/euid of "current" */ |
1109 | int kill_proc_info_as_uid(int sig, struct siginfo *info, pid_t pid, | 1108 | int kill_proc_info_as_uid(int sig, struct siginfo *info, pid_t pid, |
1110 | uid_t uid, uid_t euid) | 1109 | uid_t uid, uid_t euid, u32 secid) |
1111 | { | 1110 | { |
1112 | int ret = -EINVAL; | 1111 | int ret = -EINVAL; |
1113 | struct task_struct *p; | 1112 | struct task_struct *p; |
@@ -1127,6 +1126,9 @@ int kill_proc_info_as_uid(int sig, struct siginfo *info, pid_t pid, | |||
1127 | ret = -EPERM; | 1126 | ret = -EPERM; |
1128 | goto out_unlock; | 1127 | goto out_unlock; |
1129 | } | 1128 | } |
1129 | ret = security_task_kill(p, info, sig, secid); | ||
1130 | if (ret) | ||
1131 | goto out_unlock; | ||
1130 | if (sig && p->sighand) { | 1132 | if (sig && p->sighand) { |
1131 | unsigned long flags; | 1133 | unsigned long flags; |
1132 | spin_lock_irqsave(&p->sighand->siglock, flags); | 1134 | spin_lock_irqsave(&p->sighand->siglock, flags); |
@@ -1531,6 +1533,35 @@ static void do_notify_parent_cldstop(struct task_struct *tsk, int why) | |||
1531 | spin_unlock_irqrestore(&sighand->siglock, flags); | 1533 | spin_unlock_irqrestore(&sighand->siglock, flags); |
1532 | } | 1534 | } |
1533 | 1535 | ||
1536 | static inline int may_ptrace_stop(void) | ||
1537 | { | ||
1538 | if (!likely(current->ptrace & PT_PTRACED)) | ||
1539 | return 0; | ||
1540 | |||
1541 | if (unlikely(current->parent == current->real_parent && | ||
1542 | (current->ptrace & PT_ATTACHED))) | ||
1543 | return 0; | ||
1544 | |||
1545 | if (unlikely(current->signal == current->parent->signal) && | ||
1546 | unlikely(current->signal->flags & SIGNAL_GROUP_EXIT)) | ||
1547 | return 0; | ||
1548 | |||
1549 | /* | ||
1550 | * Are we in the middle of do_coredump? | ||
1551 | * If so and our tracer is also part of the coredump stopping | ||
1552 | * is a deadlock situation, and pointless because our tracer | ||
1553 | * is dead so don't allow us to stop. | ||
1554 | * If SIGKILL was already sent before the caller unlocked | ||
1555 | * ->siglock we must see ->core_waiters != 0. Otherwise it | ||
1556 | * is safe to enter schedule(). | ||
1557 | */ | ||
1558 | if (unlikely(current->mm->core_waiters) && | ||
1559 | unlikely(current->mm == current->parent->mm)) | ||
1560 | return 0; | ||
1561 | |||
1562 | return 1; | ||
1563 | } | ||
1564 | |||
1534 | /* | 1565 | /* |
1535 | * This must be called with current->sighand->siglock held. | 1566 | * This must be called with current->sighand->siglock held. |
1536 | * | 1567 | * |
@@ -1559,11 +1590,7 @@ static void ptrace_stop(int exit_code, int nostop_code, siginfo_t *info) | |||
1559 | spin_unlock_irq(¤t->sighand->siglock); | 1590 | spin_unlock_irq(¤t->sighand->siglock); |
1560 | try_to_freeze(); | 1591 | try_to_freeze(); |
1561 | read_lock(&tasklist_lock); | 1592 | read_lock(&tasklist_lock); |
1562 | if (likely(current->ptrace & PT_PTRACED) && | 1593 | if (may_ptrace_stop()) { |
1563 | likely(current->parent != current->real_parent || | ||
1564 | !(current->ptrace & PT_ATTACHED)) && | ||
1565 | (likely(current->parent->signal != current->signal) || | ||
1566 | !unlikely(current->signal->flags & SIGNAL_GROUP_EXIT))) { | ||
1567 | do_notify_parent_cldstop(current, CLD_TRAPPED); | 1594 | do_notify_parent_cldstop(current, CLD_TRAPPED); |
1568 | read_unlock(&tasklist_lock); | 1595 | read_unlock(&tasklist_lock); |
1569 | schedule(); | 1596 | schedule(); |