From patchwork Tue Oct 8 13:44:17 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 34872 Received: (qmail 77412 invoked by alias); 8 Oct 2019 13:44:26 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 77393 invoked by uid 89); 8 Oct 2019 13:44:26 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3 autolearn=ham version=3.3.1 spammy=disturb, exclusive, HContent-Transfer-Encoding:8bit X-HELO: youngberry.canonical.com From: Christian Brauner To: Florian Weimer , Adhemerval Zanella , libc-alpha@sourceware.org Cc: Christian Brauner Subject: [PATCH] [GLIBC RFC] clone3: add CLONE3_RESET_SIGHAND Date: Tue, 8 Oct 2019 15:44:17 +0200 Message-Id: <20191008134417.16113-1-christian.brauner@ubuntu.com> MIME-Version: 1.0 Reset all signal handlers of the child not set to SIG_IGN to SIG_DFL. Mutually exclusive with CLONE_SIGHAND to not disturb other threads signal handler. Questions for glibc before going to send this for review on lkml: - Is it sufficient for glibc to get EINVAL when CLONE3_RESET_SIGNALS is passed to determine kernel support for it? - Do you really want to have only those signals set to SIG_DFL which are not SIG_IGN or do you want to enforce _all_ signals are set to SIG_DFL even if they are SIG_IGN? Signed-off-by: Christian Brauner --- include/uapi/linux/sched.h | 3 +++ kernel/fork.c | 8 +++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/sched.h b/include/uapi/linux/sched.h index 99335e1f4a27..e3bc43efbbba 100644 --- a/include/uapi/linux/sched.h +++ b/include/uapi/linux/sched.h @@ -33,6 +33,9 @@ #define CLONE_NEWNET 0x40000000 /* New network namespace */ #define CLONE_IO 0x80000000 /* Clone io context */ +/* Flags for the clone3() syscall */ +#define CLONE3_RESET_SIGHAND 0x100000000ULL /* Reset any signal handler which is not SIG_IGN or SIG_DFL to SIG_DFL. */ + #ifndef __ASSEMBLY__ /** * struct clone_args - arguments for the clone3 syscall diff --git a/kernel/fork.c b/kernel/fork.c index 1f6c45f6a734..3bced4a2931e 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1516,6 +1516,9 @@ static int copy_sighand(unsigned long clone_flags, struct task_struct *tsk) refcount_set(&sig->count, 1); spin_lock_irq(¤t->sighand->siglock); memcpy(sig->action, current->sighand->action, sizeof(sig->action)); + /* Reset all signal handler not set to SIG_IGN to SIG_DFL. */ + if (clone_flags & CLONE3_RESET_SIGHAND) + flush_signal_handlers(tsk, 0); spin_unlock_irq(¤t->sighand->siglock); return 0; } @@ -2567,7 +2570,7 @@ static bool clone3_args_valid(const struct kernel_clone_args *kargs) * All lower bits of the flag word are taken. * Verify that no other unknown flags are passed along. */ - if (kargs->flags & ~CLONE_LEGACY_FLAGS) + if (kargs->flags & ~(CLONE_LEGACY_FLAGS | CLONE3_RESET_SIGNALS)) return false; /* @@ -2577,6 +2580,9 @@ static bool clone3_args_valid(const struct kernel_clone_args *kargs) if (kargs->flags & (CLONE_DETACHED | CSIGNAL)) return false; + if (kargs->flags & (CLONE_SIGHAND | CLONE3_RESET_SIGHAND)) + return false; + if ((kargs->flags & (CLONE_THREAD | CLONE_PARENT)) && kargs->exit_signal) return false;