mirror of
https://github.com/torvalds/linux.git
synced 2026-06-01 19:13:47 +02:00
ptrace: Stop supporting SIGKILL for PTRACE_EVENT_EXIT
Recently I had a conversation where it was pointed out to me that
SIGKILL sent to a tracee stropped in PTRACE_EVENT_EXIT is quite
difficult for a tracer to handle.
Keeping SIGKILL working after the process has been killed is pain
from an implementation point of view.
So since the debuggers don't want this behavior let's see if we can
remove this wart for the userspace API
If a regression is detected it should only need to be the last change
that is the reverted. The other two are just general cleanups that
make the last patch simpler.
Eric W. Biederman (3):
signal: Ensure SIGNAL_GROUP_EXIT gets set in do_group_exit
signal: Guarantee that SIGNAL_GROUP_EXIT is set on process exit
signal: Drop signals received after a fatal signal has been processed
fs/coredump.c | 2 +-
include/linux/sched/signal.h | 1 +
kernel/exit.c | 20 +++++++++++++++++++-
kernel/fork.c | 2 ++
kernel/signal.c | 3 ++-
5 files changed, 25 insertions(+), 3 deletions(-)
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEgjlraLDcwBA2B+6cC/v6Eiajj0AFAmM7U40ACgkQC/v6Eiaj
j0B7eRAAst6EW4nkxiDBN/PRo43Kz7tkYCZGLAq73vZAaKkyTFSwghT85cZwTsuc
px/iDPWZpSGdIeHhdt1giJeuFG0FuoMR9prQVx3z/fM6KLXEJb86OtW1c1uW00Bh
TkhVPQiF/9bc+Eb/nRKF61NA4sP0OXwO1+t/zBL4clekO9vFLP1DpRBE9OrNlHq2
NlDqoPqq6SsKYG8f+J2LJKKzRWLICvHCtz4uUt6O11Wt/PH2TZYdYnXf/2vvZyzS
SOs8kQjw4QPSptcNH/LIZz0WNHagn1uU/2/T106LOgPgcr515T4MhqOK+Wp95BjA
0RrhsfdMD+7HArqLmt9VKgKO9Gs+T/M6jQZgpUyzlw3qPorKUGu4s9UnUgS7l4uz
oNV9no1Ei2fQ+YR6RBR74579a45FWkqRBsaia59KFCzZxRsQz8VB1cqcIgl9dFUA
f81qt9FiX8duVYZIcoT79BvV1bQ3LGwyygrH+X3sDTQSdN/aeZ24JdGP2MNtYO/c
jWN/mMVHc1xOsYmACVGETWhZf0Y7lGGBYSIJ92jT2HxIuEiqmFE4kngRjKcYgL/G
1/o9z8VntMq5t+ZcQY5WfK/WpSeSPXa6TsP80PEm/hvdMwZLEO4IzCR+gPJB6oJS
KPQ3EZfRCB2Jb1qBmcpbleA/RBA0iJUZtBvtIPI7QmMTR+VRdhc=
=gX4y
-----END PGP SIGNATURE-----
Merge tag 'signal-for-v5.20' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace
Pull ptrace update from Eric Biederman:
"ptrace: Stop supporting SIGKILL for PTRACE_EVENT_EXIT
Recently I had a conversation where it was pointed out to me that
SIGKILL sent to a tracee stropped in PTRACE_EVENT_EXIT is quite
difficult for a tracer to handle.
Keeping SIGKILL working after the process has been killed is pain from
an implementation point of view.
So since the debuggers don't want this behavior let's see if we can
remove this wart for the userspace API
If a regression is detected it should only need to be the last change
that is the reverted. The other two are just general cleanups that
make the last patch simpler"
* tag 'signal-for-v5.20' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace:
signal: Drop signals received after a fatal signal has been processed
signal: Guarantee that SIGNAL_GROUP_EXIT is set on process exit
signal: Ensure SIGNAL_GROUP_EXIT gets set in do_group_exit
This commit is contained in:
commit
e572410e47
|
|
@ -354,7 +354,7 @@ static int zap_process(struct task_struct *start, int exit_code)
|
|||
struct task_struct *t;
|
||||
int nr = 0;
|
||||
|
||||
/* ignore all signals except SIGKILL, see prepare_signal() */
|
||||
/* Allow SIGKILL, see prepare_signal() */
|
||||
start->signal->flags = SIGNAL_GROUP_EXIT;
|
||||
start->signal->group_exit_code = exit_code;
|
||||
start->signal->group_stop_count = 0;
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ struct signal_struct {
|
|||
refcount_t sigcnt;
|
||||
atomic_t live;
|
||||
int nr_threads;
|
||||
int quick_threads;
|
||||
struct list_head thread_head;
|
||||
|
||||
wait_queue_head_t wait_chldexit; /* for wait4() */
|
||||
|
|
|
|||
|
|
@ -733,11 +733,29 @@ static void check_stack_usage(void)
|
|||
static inline void check_stack_usage(void) {}
|
||||
#endif
|
||||
|
||||
static void synchronize_group_exit(struct task_struct *tsk, long code)
|
||||
{
|
||||
struct sighand_struct *sighand = tsk->sighand;
|
||||
struct signal_struct *signal = tsk->signal;
|
||||
|
||||
spin_lock_irq(&sighand->siglock);
|
||||
signal->quick_threads--;
|
||||
if ((signal->quick_threads == 0) &&
|
||||
!(signal->flags & SIGNAL_GROUP_EXIT)) {
|
||||
signal->flags = SIGNAL_GROUP_EXIT;
|
||||
signal->group_exit_code = code;
|
||||
signal->group_stop_count = 0;
|
||||
}
|
||||
spin_unlock_irq(&sighand->siglock);
|
||||
}
|
||||
|
||||
void __noreturn do_exit(long code)
|
||||
{
|
||||
struct task_struct *tsk = current;
|
||||
int group_dead;
|
||||
|
||||
synchronize_group_exit(tsk, code);
|
||||
|
||||
WARN_ON(tsk->plug);
|
||||
|
||||
kcov_task_exit(tsk);
|
||||
|
|
@ -905,7 +923,7 @@ do_group_exit(int exit_code)
|
|||
exit_code = sig->group_exit_code;
|
||||
else if (sig->group_exec_task)
|
||||
exit_code = 0;
|
||||
else if (!thread_group_empty(current)) {
|
||||
else {
|
||||
struct sighand_struct *const sighand = current->sighand;
|
||||
|
||||
spin_lock_irq(&sighand->siglock);
|
||||
|
|
|
|||
|
|
@ -1693,6 +1693,7 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
|
|||
return -ENOMEM;
|
||||
|
||||
sig->nr_threads = 1;
|
||||
sig->quick_threads = 1;
|
||||
atomic_set(&sig->live, 1);
|
||||
refcount_set(&sig->sigcnt, 1);
|
||||
|
||||
|
|
@ -2460,6 +2461,7 @@ static __latent_entropy struct task_struct *copy_process(
|
|||
__this_cpu_inc(process_counts);
|
||||
} else {
|
||||
current->signal->nr_threads++;
|
||||
current->signal->quick_threads++;
|
||||
atomic_inc(¤t->signal->live);
|
||||
refcount_inc(¤t->signal->sigcnt);
|
||||
task_join_group_stop(p);
|
||||
|
|
|
|||
|
|
@ -913,8 +913,9 @@ static bool prepare_signal(int sig, struct task_struct *p, bool force)
|
|||
if (signal->core_state)
|
||||
return sig == SIGKILL;
|
||||
/*
|
||||
* The process is in the middle of dying, nothing to do.
|
||||
* The process is in the middle of dying, drop the signal.
|
||||
*/
|
||||
return false;
|
||||
} else if (sig_kernel_stop(sig)) {
|
||||
/*
|
||||
* This is a stop signal. Remove SIGCONT from all queues.
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user