From 8063eb8fe64148efdc1d0c8d73eee38ff92b9b57 Mon Sep 17 00:00:00 2001 From: Andrei Vagin Date: Thu, 20 May 2021 19:32:53 +0300 Subject: [PATCH] parasite: don't block SIGTRAP This is the workaround for #1429. The parasite code contains instructions that trigger SIGTRAP to stop at certain points. In such cases, the kernel sends a force SIGTRAP that can't be ignore and if it is blocked, the kernel resets its signal handler to a default one and unblocks it. It means that if we want to save the origin signal handle Signed-off-by: Andrei Vagin --- compel/include/uapi/ksigset.h | 6 ++++++ compel/src/lib/infect.c | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/compel/include/uapi/ksigset.h b/compel/include/uapi/ksigset.h index f6b124bf3..8b5d95804 100644 --- a/compel/include/uapi/ksigset.h +++ b/compel/include/uapi/ksigset.h @@ -22,4 +22,10 @@ static inline void ksigaddset(k_rtsigset_t *set, int _sig) int sig = _sig - 1; set->sig[sig / _NSIG_BPW] |= 1UL << (sig % _NSIG_BPW); } + +static inline void ksigdelset(k_rtsigset_t *set, int _sig) +{ + int sig = _sig - 1; + set->sig[sig / _NSIG_BPW] |= ~(1UL << (sig % _NSIG_BPW)); +} #endif diff --git a/compel/src/lib/infect.c b/compel/src/lib/infect.c index 1bb07ace5..a15b99ad6 100644 --- a/compel/src/lib/infect.c +++ b/compel/src/lib/infect.c @@ -281,6 +281,19 @@ try_again: if (ss->seccomp_mode != SECCOMP_MODE_DISABLED && ptrace_suspend_seccomp(pid) < 0) goto err; + /* + * FIXME(issues/1429): parasite code contains instructions that trigger + * SIGTRAP to stop at certain points. In such cases, the kernel sends a + * force SIGTRAP that can't be ignored and if it is blocked, the kernel + * resets its signal handler to a default one and unblocks it. It means + * that if we want to save the origin signal handler, we need to run a + * parasite code with the unblocked SIGTRAP. + */ + if ((ss->sigpnd | ss->shdpnd) & (1 << (SIGTRAP - 1))) { + pr_err("Can't dump the %d thread with a pending SIGTRAP.\n", pid); + goto err; + } + nr_sigstop = 0; if (ss->sigpnd & (1 << (SIGSTOP - 1))) nr_sigstop++; @@ -447,6 +460,11 @@ static int parasite_run(pid_t pid, int cmd, unsigned long ip, void *stack, k_rtsigset_t block; ksigfillset(&block); + /* + * FIXME(issues/1429): SIGTRAP can't be blocked, otherwice its hanlder + * will be reseted to the default one. + */ + ksigdelset(&block, SIGTRAP); if (ptrace(PTRACE_SETSIGMASK, pid, sizeof(k_rtsigset_t), &block)) { pr_perror("Can't block signals for %d", pid); goto err_sig;