Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

signal: Implement force_fatal_sig

Add a simple helper force_fatal_sig that causes a signal to be
delivered to a process as if the signal handler was set to SIG_DFL.

Reimplement force_sigsegv based upon this new helper. This fixes
force_sigsegv so that when it forces the default signal handler
to be used the code now forces the signal to be unblocked as well.

Reusing the tested logic in force_sig_info_to_task that was built for
force_sig_seccomp this makes the implementation trivial.

This is interesting both because it makes force_sigsegv simpler and
because there are a couple of buggy places in the kernel that call
do_exit(SIGILL) or do_exit(SIGSYS) because there is no straight
forward way today for those places to simply force the exit of a
process with the chosen signal. Creating force_fatal_sig allows
those places to be implemented with normal signal exits.

Link: https://lkml.kernel.org/r/20211020174406.17889-13-ebiederm@xmission.com
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>

+18 -9
+1
include/linux/sched/signal.h
··· 338 338 extern __must_check bool do_notify_parent(struct task_struct *, int); 339 339 extern void __wake_up_parent(struct task_struct *p, struct task_struct *parent); 340 340 extern void force_sig(int); 341 + extern void force_fatal_sig(int); 341 342 extern int send_sig(int, struct task_struct *, int); 342 343 extern int zap_other_threads(struct task_struct *p); 343 344 extern struct sigqueue *sigqueue_alloc(void);
+17 -9
kernel/signal.c
··· 1662 1662 } 1663 1663 EXPORT_SYMBOL(force_sig); 1664 1664 1665 + void force_fatal_sig(int sig) 1666 + { 1667 + struct kernel_siginfo info; 1668 + 1669 + clear_siginfo(&info); 1670 + info.si_signo = sig; 1671 + info.si_errno = 0; 1672 + info.si_code = SI_KERNEL; 1673 + info.si_pid = 0; 1674 + info.si_uid = 0; 1675 + force_sig_info_to_task(&info, current, true); 1676 + } 1677 + 1665 1678 /* 1666 1679 * When things go south during signal handling, we 1667 1680 * will force a SIGSEGV. And if the signal that caused ··· 1683 1670 */ 1684 1671 void force_sigsegv(int sig) 1685 1672 { 1686 - struct task_struct *p = current; 1687 - 1688 - if (sig == SIGSEGV) { 1689 - unsigned long flags; 1690 - spin_lock_irqsave(&p->sighand->siglock, flags); 1691 - p->sighand->action[sig - 1].sa.sa_handler = SIG_DFL; 1692 - spin_unlock_irqrestore(&p->sighand->siglock, flags); 1693 - } 1694 - force_sig(SIGSEGV); 1673 + if (sig == SIGSEGV) 1674 + force_fatal_sig(SIGSEGV); 1675 + else 1676 + force_sig(SIGSEGV); 1695 1677 } 1696 1678 1697 1679 int force_sig_fault_to_task(int sig, int code, void __user *addr