Skip to content

Commit e572410

Browse files
committed
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
2 parents 86fb9c5 + 9a95f78 commit e572410

File tree

5 files changed

+25
-3
lines changed

5 files changed

+25
-3
lines changed

fs/coredump.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ static int zap_process(struct task_struct *start, int exit_code)
354354
struct task_struct *t;
355355
int nr = 0;
356356

357-
/* ignore all signals except SIGKILL, see prepare_signal() */
357+
/* Allow SIGKILL, see prepare_signal() */
358358
start->signal->flags = SIGNAL_GROUP_EXIT;
359359
start->signal->group_exit_code = exit_code;
360360
start->signal->group_stop_count = 0;

include/linux/sched/signal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ struct signal_struct {
9494
refcount_t sigcnt;
9595
atomic_t live;
9696
int nr_threads;
97+
int quick_threads;
9798
struct list_head thread_head;
9899

99100
wait_queue_head_t wait_chldexit; /* for wait4() */

kernel/exit.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -733,11 +733,29 @@ static void check_stack_usage(void)
733733
static inline void check_stack_usage(void) {}
734734
#endif
735735

736+
static void synchronize_group_exit(struct task_struct *tsk, long code)
737+
{
738+
struct sighand_struct *sighand = tsk->sighand;
739+
struct signal_struct *signal = tsk->signal;
740+
741+
spin_lock_irq(&sighand->siglock);
742+
signal->quick_threads--;
743+
if ((signal->quick_threads == 0) &&
744+
!(signal->flags & SIGNAL_GROUP_EXIT)) {
745+
signal->flags = SIGNAL_GROUP_EXIT;
746+
signal->group_exit_code = code;
747+
signal->group_stop_count = 0;
748+
}
749+
spin_unlock_irq(&sighand->siglock);
750+
}
751+
736752
void __noreturn do_exit(long code)
737753
{
738754
struct task_struct *tsk = current;
739755
int group_dead;
740756

757+
synchronize_group_exit(tsk, code);
758+
741759
WARN_ON(tsk->plug);
742760

743761
kcov_task_exit(tsk);
@@ -905,7 +923,7 @@ do_group_exit(int exit_code)
905923
exit_code = sig->group_exit_code;
906924
else if (sig->group_exec_task)
907925
exit_code = 0;
908-
else if (!thread_group_empty(current)) {
926+
else {
909927
struct sighand_struct *const sighand = current->sighand;
910928

911929
spin_lock_irq(&sighand->siglock);

kernel/fork.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1693,6 +1693,7 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
16931693
return -ENOMEM;
16941694

16951695
sig->nr_threads = 1;
1696+
sig->quick_threads = 1;
16961697
atomic_set(&sig->live, 1);
16971698
refcount_set(&sig->sigcnt, 1);
16981699

@@ -2460,6 +2461,7 @@ static __latent_entropy struct task_struct *copy_process(
24602461
__this_cpu_inc(process_counts);
24612462
} else {
24622463
current->signal->nr_threads++;
2464+
current->signal->quick_threads++;
24632465
atomic_inc(&current->signal->live);
24642466
refcount_inc(&current->signal->sigcnt);
24652467
task_join_group_stop(p);

kernel/signal.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -913,8 +913,9 @@ static bool prepare_signal(int sig, struct task_struct *p, bool force)
913913
if (signal->core_state)
914914
return sig == SIGKILL;
915915
/*
916-
* The process is in the middle of dying, nothing to do.
916+
* The process is in the middle of dying, drop the signal.
917917
*/
918+
return false;
918919
} else if (sig_kernel_stop(sig)) {
919920
/*
920921
* This is a stop signal. Remove SIGCONT from all queues.

0 commit comments

Comments
 (0)