diff mbox

[v2,3/3] selftests/powerpc: Add TM signal with invalid stack test

Message ID 1447992934-18905-4-git-send-email-mikey@neuling.org (mailing list archive)
State Accepted
Headers show

Commit Message

Michael Neuling Nov. 20, 2015, 4:15 a.m. UTC
Test the kernels signal generation code to ensure it can handle an
invalid stack pointer when transactional.

Signed-off-by: Michael Neuling <mikey@neuling.org>
---
 tools/testing/selftests/powerpc/tm/.gitignore      |  1 +
 tools/testing/selftests/powerpc/tm/Makefile        |  2 +-
 .../testing/selftests/powerpc/tm/tm-signal-stack.c | 73 ++++++++++++++++++++++
 3 files changed, 75 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/powerpc/tm/tm-signal-stack.c

Comments

Anshuman Khandual Nov. 23, 2015, 11:32 a.m. UTC | #1
On 11/20/2015 09:45 AM, Michael Neuling wrote:
> Test the kernels signal generation code to ensure it can handle an
> invalid stack pointer when transactional.
> 
> Signed-off-by: Michael Neuling <mikey@neuling.org>

Tested-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
Michael Ellerman Dec. 15, 2015, 11:27 a.m. UTC | #2
On Fri, 2015-20-11 at 04:15:34 UTC, Michael Neuling wrote:
> Test the kernels signal generation code to ensure it can handle an
> invalid stack pointer when transactional.
> 
> Signed-off-by: Michael Neuling <mikey@neuling.org>
> Tested-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>

Applied to powerpc next, thanks.

https://git.kernel.org/powerpc/c/a26f415bf71640f0141e5e94

cheers
diff mbox

Patch

diff --git a/tools/testing/selftests/powerpc/tm/.gitignore b/tools/testing/selftests/powerpc/tm/.gitignore
index 61c318f..e666821 100644
--- a/tools/testing/selftests/powerpc/tm/.gitignore
+++ b/tools/testing/selftests/powerpc/tm/.gitignore
@@ -1,3 +1,4 @@ 
 tm-resched-dscr
 tm-syscall
 tm-signal-msr-resv
+tm-signal-stack
diff --git a/tools/testing/selftests/powerpc/tm/Makefile b/tools/testing/selftests/powerpc/tm/Makefile
index 0c28db7..0e45c7e 100644
--- a/tools/testing/selftests/powerpc/tm/Makefile
+++ b/tools/testing/selftests/powerpc/tm/Makefile
@@ -1,4 +1,4 @@ 
-TEST_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv
+TEST_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack
 
 all: $(TEST_PROGS)
 
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-stack.c b/tools/testing/selftests/powerpc/tm/tm-signal-stack.c
new file mode 100644
index 0000000..62f2a5f
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-signal-stack.c
@@ -0,0 +1,73 @@ 
+/*
+ * Copyright 2015, Michael Neuling, IBM Corp.
+ * Licensed under GPLv2.
+ *
+ * Test the kernel's signal delievery code to ensure that we don't
+ * trelaim twice in the kernel signal delivery code.  This can happen
+ * if we trigger a signal when in a transaction and the stack pointer
+ * is bogus.
+ *
+ * This test case registers a SEGV handler, sets the stack pointer
+ * (r1) to NULL, starts a transaction and then generates a SEGV.  The
+ * SEGV should be handled but we exit here as the stack pointer is
+ * invalid and hance we can't sigreturn.  We only need to check that
+ * this flow doesn't crash the kernel.
+ */
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+
+#include "utils.h"
+
+void signal_segv(int signum)
+{
+	/* This should never actually run since stack is foobar */
+	exit(1);
+}
+
+int tm_signal_stack()
+{
+	int pid;
+
+	pid = fork();
+	if (pid < 0)
+		exit(1);
+
+	if (pid) { /* Parent */
+		/*
+		 * It's likely the whole machine will crash here so if
+		 * the child ever exits, we are good.
+		 */
+		wait(NULL);
+		return 0;
+	}
+
+	/*
+	 * The flow here is:
+	 * 1) register a signal handler (so signal delievery occurs)
+	 * 2) make stack pointer (r1) = NULL
+	 * 3) start transaction
+	 * 4) cause segv
+	 */
+	if (signal(SIGSEGV, signal_segv) == SIG_ERR)
+		exit(1);
+	asm volatile("li 1, 0 ;"		/* stack ptr == NULL */
+		     "1:"
+		     ".long 0x7C00051D ;"	/* tbegin */
+		     "beq 1b ;"			/* retry forever */
+		     ".long 0x7C0005DD ; ;"	/* tsuspend */
+		     "ld 2, 0(1) ;"		/* trigger segv" */
+		     : : : "memory");
+
+	/* This should never get here due to above segv */
+	return 1;
+}
+
+int main(void)
+{
+	return test_harness(tm_signal_stack, "tm_signal_stack");
+}