Skip to content

Commit b612e5d

Browse files
author
Christian Brauner
committed
clone3: add CLONE_CLEAR_SIGHAND
Reset all signal handlers of the child not set to SIG_IGN to SIG_DFL. Mutually exclusive with CLONE_SIGHAND to not disturb other thread's signal handler. In the spirit of closer cooperation between glibc developers and kernel developers (cf. [2]) this patchset came out of a discussion on the glibc mailing list for improving posix_spawn() (cf. [1], [3], [4]). Kernel support for this feature has been explicitly requested by glibc and I see no reason not to help them with this. The child helper process on Linux posix_spawn must ensure that no signal handlers are enabled, so the signal disposition must be either SIG_DFL or SIG_IGN. However, it requires a sigprocmask to obtain the current signal mask and at least _NSIG sigaction calls to reset the signal handlers for each posix_spawn call or complex state tracking that might lead to data corruption in glibc. Adding this flags lets glibc avoid these problems. [1]: https://www.sourceware.org/ml/libc-alpha/2019-10/msg00149.html [3]: https://www.sourceware.org/ml/libc-alpha/2019-10/msg00158.html [4]: https://www.sourceware.org/ml/libc-alpha/2019-10/msg00160.html [2]: https://lwn.net/Articles/799331/ '[...] by asking for better cooperation with the C-library projects in general. They should be copied on patches containing ABI changes, for example. I noted that there are often times where C-library developers wish the kernel community had done things differently; how could those be avoided in the future? Members of the audience suggested that more glibc developers should perhaps join the linux-api list. The other suggestion was to "copy Florian on everything".' Cc: Florian Weimer <[email protected]> Cc: [email protected] Cc: [email protected] Signed-off-by: Christian Brauner <[email protected]> Reviewed-by: Oleg Nesterov <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 1e1d0f0 commit b612e5d

File tree

2 files changed

+14
-5
lines changed

2 files changed

+14
-5
lines changed

include/uapi/linux/sched.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
#define CLONE_NEWNET 0x40000000 /* New network namespace */
3434
#define CLONE_IO 0x80000000 /* Clone io context */
3535

36+
/* Flags for the clone3() syscall. */
37+
#define CLONE_CLEAR_SIGHAND 0x100000000ULL /* Clear any signal handler and reset to SIG_DFL. */
38+
3639
#ifndef __ASSEMBLY__
3740
/**
3841
* struct clone_args - arguments for the clone3 syscall

kernel/fork.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1517,6 +1517,11 @@ static int copy_sighand(unsigned long clone_flags, struct task_struct *tsk)
15171517
spin_lock_irq(&current->sighand->siglock);
15181518
memcpy(sig->action, current->sighand->action, sizeof(sig->action));
15191519
spin_unlock_irq(&current->sighand->siglock);
1520+
1521+
/* Reset all signal handler not set to SIG_IGN to SIG_DFL. */
1522+
if (clone_flags & CLONE_CLEAR_SIGHAND)
1523+
flush_signal_handlers(tsk, 0);
1524+
15201525
return 0;
15211526
}
15221527

@@ -2619,11 +2624,8 @@ noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs,
26192624

26202625
static bool clone3_args_valid(const struct kernel_clone_args *kargs)
26212626
{
2622-
/*
2623-
* All lower bits of the flag word are taken.
2624-
* Verify that no other unknown flags are passed along.
2625-
*/
2626-
if (kargs->flags & ~CLONE_LEGACY_FLAGS)
2627+
/* Verify that no unknown flags are passed along. */
2628+
if (kargs->flags & ~(CLONE_LEGACY_FLAGS | CLONE_CLEAR_SIGHAND))
26272629
return false;
26282630

26292631
/*
@@ -2633,6 +2635,10 @@ static bool clone3_args_valid(const struct kernel_clone_args *kargs)
26332635
if (kargs->flags & (CLONE_DETACHED | CSIGNAL))
26342636
return false;
26352637

2638+
if ((kargs->flags & (CLONE_SIGHAND | CLONE_CLEAR_SIGHAND)) ==
2639+
(CLONE_SIGHAND | CLONE_CLEAR_SIGHAND))
2640+
return false;
2641+
26362642
if ((kargs->flags & (CLONE_THREAD | CLONE_PARENT)) &&
26372643
kargs->exit_signal)
26382644
return false;

0 commit comments

Comments
 (0)