All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V2 1/5] selftests/powerpc: Add exec() test to check for spr sanitisation
@ 2016-04-04 23:59 Cyril Bur
  2016-04-04 23:59 ` [PATCH V2 2/5] selftests/powerpc: Add fork() test to check for spr being preserved Cyril Bur
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Cyril Bur @ 2016-04-04 23:59 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: mikey

Signed-off-by: Cyril Bur <cyrilbur@gmail.com>
---
 tools/testing/selftests/powerpc/syscalls/Makefile  |  3 +-
 .../testing/selftests/powerpc/syscalls/spr_exec.c  | 78 ++++++++++++++++++++++
 2 files changed, 80 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/powerpc/syscalls/spr_exec.c

diff --git a/tools/testing/selftests/powerpc/syscalls/Makefile b/tools/testing/selftests/powerpc/syscalls/Makefile
index b35c794..291ba45 100644
--- a/tools/testing/selftests/powerpc/syscalls/Makefile
+++ b/tools/testing/selftests/powerpc/syscalls/Makefile
@@ -1,10 +1,11 @@
-TEST_PROGS := ipc_unmuxed
+TEST_PROGS := ipc_unmuxed spr_exec
 
 CFLAGS += -I../../../../../usr/include
 
 all: $(TEST_PROGS)
 
 $(TEST_PROGS): ../harness.c
+spr_exec: ../utils.c
 
 include ../../lib.mk
 
diff --git a/tools/testing/selftests/powerpc/syscalls/spr_exec.c b/tools/testing/selftests/powerpc/syscalls/spr_exec.c
new file mode 100644
index 0000000..5ecd6ca
--- /dev/null
+++ b/tools/testing/selftests/powerpc/syscalls/spr_exec.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2016, Cyril Bur, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * This test checks that the TAR (an SPR) is correctly sanitised across
+ * execve()
+ */
+#include <asm/cputable.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/auxv.h>
+#include <unistd.h>
+
+#include "utils.h"
+
+static char *name;
+static int count;
+
+static int exec_spr(void)
+{
+	unsigned long tar;
+	char buffer[10];
+	char *args[3];
+
+	asm __volatile__(
+			"mfspr %[tar], 815"
+			: [tar] "=r" (tar)
+			);
+	/* Read TAR */
+	FAIL_IF(tar != 0);
+
+	tar = 1;
+	asm __volatile__(
+			"mtspr 815, %[tar]"
+			:
+			: [tar] "r" (tar)
+			);
+
+	FAIL_IF(sprintf(buffer, "%d", count + 1) == -1);
+	args[0] = name;
+	args[1] = buffer;
+	args[2] = NULL;
+	FAIL_IF(execve(name, args, NULL) == -1);
+
+	return 0;
+}
+
+static int exec_spr_check(void)
+{
+	unsigned long tar;
+
+	asm __volatile__(
+			"mfspr %[tar], 815;"
+			: [tar] "=r" (tar)
+			);
+	/* Read TAR */
+	FAIL_IF(tar != 0);
+
+	return 0;
+}
+
+int main(int argc, char *argv[])
+{
+	SKIP_IF(!have_hwcap2(PPC_FEATURE2_TAR));
+	name = argv[0];
+	/* Do this a few times to be sure isn't a false negative */
+	if (argc == 1 || atoi(argv[1]) < 10) {
+		if (argc > 1)
+			count = atoi(argv[1]);
+		return test_harness(exec_spr, "spr_exec");
+	} else {
+		return test_harness(exec_spr_check, "spr_exec_check");
+	}
+}
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH V2 2/5] selftests/powerpc: Add fork() test to check for spr being preserved
  2016-04-04 23:59 [PATCH V2 1/5] selftests/powerpc: Add exec() test to check for spr sanitisation Cyril Bur
@ 2016-04-04 23:59 ` Cyril Bur
  2016-04-04 23:59 ` [PATCH V2 3/5] powerpc: Fix SPR leak across exec() syscalls Cyril Bur
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Cyril Bur @ 2016-04-04 23:59 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: mikey

Signed-off-by: Cyril Bur <cyrilbur@gmail.com>
---
 tools/testing/selftests/powerpc/syscalls/Makefile  |  3 +-
 .../testing/selftests/powerpc/syscalls/spr_fork.c  | 78 ++++++++++++++++++++++
 2 files changed, 80 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/powerpc/syscalls/spr_fork.c

diff --git a/tools/testing/selftests/powerpc/syscalls/Makefile b/tools/testing/selftests/powerpc/syscalls/Makefile
index 291ba45..55969f3 100644
--- a/tools/testing/selftests/powerpc/syscalls/Makefile
+++ b/tools/testing/selftests/powerpc/syscalls/Makefile
@@ -1,4 +1,4 @@
-TEST_PROGS := ipc_unmuxed spr_exec
+TEST_PROGS := ipc_unmuxed spr_exec spr_fork
 
 CFLAGS += -I../../../../../usr/include
 
@@ -6,6 +6,7 @@ all: $(TEST_PROGS)
 
 $(TEST_PROGS): ../harness.c
 spr_exec: ../utils.c
+spr_fork: ../utils.c
 
 include ../../lib.mk
 
diff --git a/tools/testing/selftests/powerpc/syscalls/spr_fork.c b/tools/testing/selftests/powerpc/syscalls/spr_fork.c
new file mode 100644
index 0000000..1a351a6
--- /dev/null
+++ b/tools/testing/selftests/powerpc/syscalls/spr_fork.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2016, Cyril Bur, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * This test checks that the TAR register (an SPR) is correctly preserved
+ * across a fork()
+ */
+#include <asm/cputable.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/auxv.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "utils.h"
+
+static int fork_spr(void)
+{
+	int child_ret;
+	unsigned long tar;
+	pid_t pid;
+	int i;
+
+
+	/* Do it a few times as there is a chance that one might luckily pass */
+	i = 0;
+	while (i < 10) {
+		/* What are the odds... */
+		tar = 0x123456;
+		asm __volatile__(
+				"mtspr 815, %[tar]"
+				:
+				: [tar] "r" (tar)
+				);
+
+		pid = fork();
+		FAIL_IF(pid == -1);
+		asm __volatile__(
+				"mfspr %[tar], 815"
+				: [tar] "=r" (tar)
+				);
+
+		FAIL_IF(tar != 0x123456);
+
+		if (pid == 0)
+			exit(0);
+
+		FAIL_IF(waitpid(pid, &child_ret, 0) == -1);
+
+		/* Child haddn't exited ? */
+		FAIL_IF(!WIFEXITED(child_ret));
+
+		/* Child detected a bad tar */
+		FAIL_IF(WEXITSTATUS(child_ret));
+
+		/* Reset it */
+		tar = 0;
+		asm __volatile__(
+				"mtspr 815, %[tar]"
+				:
+				: [tar] "r" (tar)
+				);
+
+		i++;
+	}
+
+	return 0;
+}
+
+int main(int argc, char *argv[])
+{
+	SKIP_IF(!have_hwcap2(PPC_FEATURE2_TAR));
+	return test_harness(fork_spr, "spr_fork");
+}
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH V2 3/5] powerpc: Fix SPR leak across exec() syscalls
  2016-04-04 23:59 [PATCH V2 1/5] selftests/powerpc: Add exec() test to check for spr sanitisation Cyril Bur
  2016-04-04 23:59 ` [PATCH V2 2/5] selftests/powerpc: Add fork() test to check for spr being preserved Cyril Bur
@ 2016-04-04 23:59 ` Cyril Bur
  2016-04-04 23:59 ` [PATCH V2 4/5] powerpc: Move flush_all_to_thread() below save_sprs() Cyril Bur
  2016-04-04 23:59 ` [PATCH V2 5/5] powerpc: Preserve the SPR values across fork() syscalls Cyril Bur
  3 siblings, 0 replies; 5+ messages in thread
From: Cyril Bur @ 2016-04-04 23:59 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: mikey

Currently start_thread() doesn't sanitise TAR nor the VRSAVE.

The TAR SPR can be set and branched to, not sanitising it presents an
information leak to the new executable.

The VRSAVE SPR can be used by both application and operating system. The
PowerISA states (in a programming note) that an application could use VRSAVE as a
hint to the operating system as to which vector registers are being used and
therefore which ones to save and restore. Linux doesn't care and simply
saves/restores all vector registers, however, it should also be sanitising
VRSAVE as applications are free to do with it what they wish.

Other SPR registers such as the Performance registers used by perf (and are
managed entirely by perf) as well as the Event Based Branch (EBB) registers are
left alone by design as these fall into the same category as leaving file
descriptors open across exec(), it is up the parent thread to sanitise what it
deems necessary.

Signed-off-by: Cyril Bur <cyrilbur@gmail.com>
---
 arch/powerpc/kernel/process.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index d7a9df5..56444a6 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -1577,6 +1577,8 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
 	current->thread.vr_state.vscr.u[3] = 0x00010000; /* Java mode disabled */
 	current->thread.vr_save_area = NULL;
 	current->thread.vrsave = 0;
+	if (cpu_has_feature(CPU_FTR_ALTIVEC))
+		mtspr(SPRN_VRSAVE, 0);
 	current->thread.used_vr = 0;
 #endif /* CONFIG_ALTIVEC */
 #ifdef CONFIG_SPE
@@ -1592,6 +1594,18 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
 	current->thread.tm_texasr = 0;
 	current->thread.tm_tfiar = 0;
 #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
+#ifdef CONFIG_PPC_BOOK3S_64
+	/*
+	 * Zero out the SPRs.
+	 * Don't touch the ones use by perf, it controls them.
+	 * Don't touch the EBB regs. This falls into the same category of
+	 *   responsibly as open file descriptors across exec(), the parent should
+	 *   sanitise if it feels it would be a problem
+	 */
+	current->thread.tar = 0;
+	if (cpu_has_feature(CPU_FTR_ARCH_206))
+		mtspr(SPRN_TAR, 0);
+#endif /* CONFIG_PPC_BOOK3S_64 */
 }
 EXPORT_SYMBOL(start_thread);
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH V2 4/5] powerpc: Move flush_all_to_thread() below save_sprs()
  2016-04-04 23:59 [PATCH V2 1/5] selftests/powerpc: Add exec() test to check for spr sanitisation Cyril Bur
  2016-04-04 23:59 ` [PATCH V2 2/5] selftests/powerpc: Add fork() test to check for spr being preserved Cyril Bur
  2016-04-04 23:59 ` [PATCH V2 3/5] powerpc: Fix SPR leak across exec() syscalls Cyril Bur
@ 2016-04-04 23:59 ` Cyril Bur
  2016-04-04 23:59 ` [PATCH V2 5/5] powerpc: Preserve the SPR values across fork() syscalls Cyril Bur
  3 siblings, 0 replies; 5+ messages in thread
From: Cyril Bur @ 2016-04-04 23:59 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: mikey

Signed-off-by: Cyril Bur <cyrilbur@gmail.com>
---
 arch/powerpc/kernel/process.c | 34 +++++++++++++++++-----------------
 1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 56444a6..7625976 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -511,23 +511,6 @@ void save_all(struct task_struct *tsk)
 	msr_check_and_clear(msr_all_available);
 }
 
-void flush_all_to_thread(struct task_struct *tsk)
-{
-	if (tsk->thread.regs) {
-		preempt_disable();
-		BUG_ON(tsk != current);
-		save_all(tsk);
-
-#ifdef CONFIG_SPE
-		if (tsk->thread.regs->msr & MSR_SPE)
-			tsk->thread.spefscr = mfspr(SPRN_SPEFSCR);
-#endif
-
-		preempt_enable();
-	}
-}
-EXPORT_SYMBOL(flush_all_to_thread);
-
 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
 void do_send_trap(struct pt_regs *regs, unsigned long address,
 		  unsigned long error_code, int signal_code, int breakpt)
@@ -1047,6 +1030,23 @@ static inline void restore_sprs(struct thread_struct *old_thread,
 #endif
 }
 
+void flush_all_to_thread(struct task_struct *tsk)
+{
+	if (tsk->thread.regs) {
+		preempt_disable();
+		BUG_ON(tsk != current);
+		save_all(tsk);
+
+#ifdef CONFIG_SPE
+		if (tsk->thread.regs->msr & MSR_SPE)
+			tsk->thread.spefscr = mfspr(SPRN_SPEFSCR);
+#endif
+
+		preempt_enable();
+	}
+}
+EXPORT_SYMBOL(flush_all_to_thread);
+
 struct task_struct *__switch_to(struct task_struct *prev,
 	struct task_struct *new)
 {
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH V2 5/5] powerpc: Preserve the SPR values across fork() syscalls
  2016-04-04 23:59 [PATCH V2 1/5] selftests/powerpc: Add exec() test to check for spr sanitisation Cyril Bur
                   ` (2 preceding siblings ...)
  2016-04-04 23:59 ` [PATCH V2 4/5] powerpc: Move flush_all_to_thread() below save_sprs() Cyril Bur
@ 2016-04-04 23:59 ` Cyril Bur
  3 siblings, 0 replies; 5+ messages in thread
From: Cyril Bur @ 2016-04-04 23:59 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: mikey

Currently copy_thread() doesn't flush SPRs to the parent thread struct.
Currently this only affects the TAR register as perf takes care of some of the
others and the remaining ones are all Event Based Branch (EBB) registers which
are cleared across fork().

Signed-off-by: Cyril Bur <cyrilbur@gmail.com>
---
 arch/powerpc/kernel/process.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 7625976..892c76d 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -1037,6 +1037,8 @@ void flush_all_to_thread(struct task_struct *tsk)
 		BUG_ON(tsk != current);
 		save_all(tsk);
 
+		save_sprs(&tsk->thread);
+
 #ifdef CONFIG_SPE
 		if (tsk->thread.regs->msr & MSR_SPE)
 			tsk->thread.spefscr = mfspr(SPRN_SPEFSCR);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2016-04-05  0:01 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-04-04 23:59 [PATCH V2 1/5] selftests/powerpc: Add exec() test to check for spr sanitisation Cyril Bur
2016-04-04 23:59 ` [PATCH V2 2/5] selftests/powerpc: Add fork() test to check for spr being preserved Cyril Bur
2016-04-04 23:59 ` [PATCH V2 3/5] powerpc: Fix SPR leak across exec() syscalls Cyril Bur
2016-04-04 23:59 ` [PATCH V2 4/5] powerpc: Move flush_all_to_thread() below save_sprs() Cyril Bur
2016-04-04 23:59 ` [PATCH V2 5/5] powerpc: Preserve the SPR values across fork() syscalls Cyril Bur

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.