public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Dev Jain <dev.jain@arm.com>
To: shuah@kernel.org, oleg@redhat.com, stsp2@yandex.ru
Cc: mingo@kernel.org, tglx@linutronix.de, mark.rutland@arm.com,
	ryan.roberts@arm.com, broonie@kernel.org, suzuki.poulose@arm.com,
	Anshuman.Khandual@arm.com, DeepakKumar.Mishra@arm.com,
	AneeshKumar.KizhakeVeetil@arm.com,
	linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org,
	Dev Jain <dev.jain@arm.com>
Subject: [PATCH 2/2] selftests: Add a test mangling with uc_sigmask
Date: Fri,  7 Jun 2024 17:53:19 +0530	[thread overview]
Message-ID: <20240607122319.768640-3-dev.jain@arm.com> (raw)
In-Reply-To: <20240607122319.768640-1-dev.jain@arm.com>

This test asserts the relation between blocked signal, delivered signal,
and ucontext. The ucontext is mangled with, by adding a signal mask to
it; on return from the handler, the thread must block the corresponding
signal.

Signed-off-by: Dev Jain <dev.jain@arm.com>
---
 tools/testing/selftests/signal/.gitignore     |   1 +
 tools/testing/selftests/signal/Makefile       |   1 +
 .../selftests/signal/mangle_uc_sigmask.c      | 141 ++++++++++++++++++
 3 files changed, 143 insertions(+)
 create mode 100644 tools/testing/selftests/signal/mangle_uc_sigmask.c

diff --git a/tools/testing/selftests/signal/.gitignore b/tools/testing/selftests/signal/.gitignore
index 98a7bbc4f325..ccba56247942 100644
--- a/tools/testing/selftests/signal/.gitignore
+++ b/tools/testing/selftests/signal/.gitignore
@@ -1,2 +1,3 @@
 # SPDX-License-Identifier: GPL-2.0-only
 sigaltstack
+mangle_uc_sigmask
diff --git a/tools/testing/selftests/signal/Makefile b/tools/testing/selftests/signal/Makefile
index dd6be992fd81..4ebf6ac2e303 100644
--- a/tools/testing/selftests/signal/Makefile
+++ b/tools/testing/selftests/signal/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 CFLAGS = -Wall
 TEST_GEN_PROGS = sigaltstack
+TEST_GEN_PROGS += mangle_uc_sigmask
 
 include ../lib.mk
 
diff --git a/tools/testing/selftests/signal/mangle_uc_sigmask.c b/tools/testing/selftests/signal/mangle_uc_sigmask.c
new file mode 100644
index 000000000000..0803aeb248a0
--- /dev/null
+++ b/tools/testing/selftests/signal/mangle_uc_sigmask.c
@@ -0,0 +1,141 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2024 ARM Ltd.
+ *
+ * Author: Dev Jain <dev.jain@arm.com>
+ *
+ * Test describing a clear distinction between signal states - delivered and
+ * blocked, and their relation with ucontext.
+ */
+
+#include <signal.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ucontext.h>
+#include <assert.h>
+
+#include "../kselftest.h"
+
+void handler_verify_ucontext(int signo, siginfo_t *info, void *uc)
+{
+	int ret;
+
+	/* Kernel dumps ucontext with USR2 blocked */
+	ret = sigismember(&(((ucontext_t *)uc)->uc_sigmask), SIGUSR2);
+	ksft_test_result(ret == 1, "USR2 in ucontext\n");
+
+	raise(SIGUSR2);
+}
+
+void handler_segv(int signo, siginfo_t *info, void *uc)
+{
+	/*
+	 * Three cases possible:
+	 * 1. Program already terminated due to segmentation fault.
+	 * 2. SEGV was blocked even after returning from handler_usr.
+	 * 3. SEGV was delivered on returning from handler_usr.
+	 * The last option must happen.
+	 */
+	ksft_test_result_pass("SEGV delivered\n");
+}
+
+static int cnt;
+
+void handler_usr(int signo, siginfo_t *info, void *uc)
+{
+	int ret;
+
+	/*
+	 * Break out of infinite recursion caused by raise(SIGUSR1) invoked
+	 * from inside the handler
+	 */
+	++cnt;
+	if (cnt > 1)
+		return;
+
+	ksft_print_msg("In handler_usr\n");
+
+	/* SEGV blocked during handler execution, delivered on return */
+	raise(SIGPIPE);
+	ksft_print_msg("SEGV bypassed successfully\n");
+
+	/*
+	 * Signal responsible for handler invocation is blocked by default;
+	 * delivered on return, leading to an infinite recursion
+	 */
+	raise(SIGUSR1);
+	ksft_test_result(cnt == 1,
+			 "USR1 is blocked, cannot invoke handler again\n");
+
+	/* SIGPIPE has been blocked in sa_mask, but ucontext is invariant */
+	ret = sigismember(&(((ucontext_t *)uc)->uc_sigmask), SIGPIPE);
+	ksft_test_result(ret == 0, "USR1 not in ucontext\n");
+
+	/* SIGUSR1 has been blocked, but ucontext is invariant */
+	ret = sigismember(&(((ucontext_t *)uc)->uc_sigmask), SIGUSR1);
+	ksft_test_result(ret == 0, "SEGV not in ucontext\n");
+
+	/*
+	 * Mangle ucontext; this will be copied back into &current->blocked
+	 * on return from the handler.
+	 */
+	if (sigaddset(&((ucontext_t *)uc)->uc_sigmask, SIGUSR2))
+		ksft_exit_fail_perror("Cannot add into uc_sigmask");
+}
+
+int main(int argc, char *argv[])
+{
+	struct sigaction act, act2;
+	sigset_t *set, *oldset;
+
+	ksft_print_header();
+	ksft_set_plan(6);
+
+	act.sa_flags = SA_SIGINFO;
+	act.sa_sigaction = &handler_usr;
+
+	/* add SEGV to blocked mask */
+	if (sigemptyset(&act.sa_mask) || sigaddset(&act.sa_mask, SIGPIPE)
+	    || (sigismember(&act.sa_mask, SIGPIPE) != 1))
+		ksft_exit_fail_msg("Cannot add SEGV to blocked mask\n");
+
+	if (sigaction(SIGUSR1, &act, NULL))
+		ksft_exit_fail_perror("Cannot install handler");
+
+	act2.sa_flags = SA_SIGINFO;
+	act2.sa_sigaction = &handler_segv;
+
+	if (sigaction(SIGPIPE, &act2, NULL))
+		ksft_exit_fail_perror("Cannot install handler");
+
+	/* invoke handler */
+	raise(SIGUSR1);
+
+	/* Mangled ucontext implies USR2 is blocked for current thread */
+	raise(SIGUSR2);
+	ksft_print_msg("USR2 bypassed successfully\n");
+
+	act.sa_sigaction = &handler_verify_ucontext;
+	if (sigaction(SIGUSR1, &act, NULL))
+		ksft_exit_fail_perror("Cannot install handler");
+
+	raise(SIGUSR1);
+
+	ksft_print_msg("USR2 still blocked on return from handler\n");
+
+	/* Confirm USR2 blockage by sigprocmask() too */
+	set = malloc(sizeof(sigset_t *));
+	oldset = malloc(sizeof(sigset_t *));
+
+	if (sigemptyset(set))
+		ksft_exit_fail_perror("Cannot empty set");
+
+	if (sigprocmask(SIG_BLOCK, set, oldset))
+		ksft_exit_fail_perror("sigprocmask()");
+
+	ksft_test_result(sigismember(oldset, SIGUSR2) == 1,
+			 "USR2 present in &current->blocked\n");
+
+	ksft_finished();
+}
-- 
2.34.1


  parent reply	other threads:[~2024-06-07 12:24 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-06-07 12:23 [PATCH 0/2] Add test to distinguish between thread's signal mask and ucontext_t Dev Jain
2024-06-07 12:23 ` [PATCH 1/2] selftests: Rename sigaltstack to generic signal Dev Jain
2024-06-07 12:45   ` Mark Brown
2024-06-07 12:23 ` Dev Jain [this message]
2024-06-07 13:12   ` [PATCH 2/2] selftests: Add a test mangling with uc_sigmask Mark Brown
2024-06-07 13:23     ` Dev Jain
2024-06-07 13:42       ` Mark Brown
2024-06-07 14:26         ` Dev Jain

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240607122319.768640-3-dev.jain@arm.com \
    --to=dev.jain@arm.com \
    --cc=AneeshKumar.KizhakeVeetil@arm.com \
    --cc=Anshuman.Khandual@arm.com \
    --cc=DeepakKumar.Mishra@arm.com \
    --cc=broonie@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=mingo@kernel.org \
    --cc=oleg@redhat.com \
    --cc=ryan.roberts@arm.com \
    --cc=shuah@kernel.org \
    --cc=stsp2@yandex.ru \
    --cc=suzuki.poulose@arm.com \
    --cc=tglx@linutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox