All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] SIGFPE/SIGTRAP sending updates
@ 2016-03-04  1:41 ` Maciej W. Rozycki
  0 siblings, 0 replies; 6+ messages in thread
From: Maciej W. Rozycki @ 2016-03-04  1:41 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: Pedro Alves, Luis Machado, linux-mips

Hi,

 This was meant to be a single SIGTRAP ABI correction patch for debugger 
support, but in the course of implementation I discovered information 
leaks in signal passing from trap handlers, affecting code to be written, 
so these are fixed first in this patch pair.

  Maciej

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

* [PATCH 0/2] SIGFPE/SIGTRAP sending updates
@ 2016-03-04  1:41 ` Maciej W. Rozycki
  0 siblings, 0 replies; 6+ messages in thread
From: Maciej W. Rozycki @ 2016-03-04  1:41 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: Pedro Alves, Luis Machado, linux-mips

Hi,

 This was meant to be a single SIGTRAP ABI correction patch for debugger 
support, but in the course of implementation I discovered information 
leaks in signal passing from trap handlers, affecting code to be written, 
so these are fixed first in this patch pair.

  Maciej

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

* [PATCH 1/2] traps: Fix SIGFPE information leak from `do_ov' and `do_trap_or_bp'
@ 2016-03-04  1:42   ` Maciej W. Rozycki
  0 siblings, 0 replies; 6+ messages in thread
From: Maciej W. Rozycki @ 2016-03-04  1:42 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: Pedro Alves, Luis Machado, linux-mips

Avoid sending a partially initialised `siginfo_t' structure along SIGFPE
signals issued from `do_ov' and `do_trap_or_bp', leading to information
leaking from the kernel stack.

Signed-off-by: Maciej W. Rozycki <macro@imgtec.com>
Cc: stable@vger.kernel.org
---
linux-mips-sig-info-leak.diff
Index: linux-sfr-test/arch/mips/kernel/traps.c
===================================================================
--- linux-sfr-test.orig/arch/mips/kernel/traps.c	2016-03-03 13:34:47.454048000 +0000
+++ linux-sfr-test/arch/mips/kernel/traps.c	2016-03-04 00:56:37.858781000 +0000
@@ -690,15 +690,15 @@ static int simulate_sync(struct pt_regs 
 asmlinkage void do_ov(struct pt_regs *regs)
 {
 	enum ctx_state prev_state;
-	siginfo_t info;
+	siginfo_t info = {
+		.si_signo = SIGFPE,
+		.si_code = FPE_INTOVF,
+		.si_addr = (void __user *)regs->cp0_epc,
+	};
 
 	prev_state = exception_enter();
 	die_if_kernel("Integer overflow", regs);
 
-	info.si_code = FPE_INTOVF;
-	info.si_signo = SIGFPE;
-	info.si_errno = 0;
-	info.si_addr = (void __user *) regs->cp0_epc;
 	force_sig_info(SIGFPE, &info, current);
 	exception_exit(prev_state);
 }
@@ -874,7 +874,7 @@ asmlinkage void do_fpe(struct pt_regs *r
 void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
 	const char *str)
 {
-	siginfo_t info;
+	siginfo_t info = { 0 };
 	char b[40];
 
 #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
@@ -903,7 +903,6 @@ void do_trap_or_bp(struct pt_regs *regs,
 		else
 			info.si_code = FPE_INTOVF;
 		info.si_signo = SIGFPE;
-		info.si_errno = 0;
 		info.si_addr = (void __user *) regs->cp0_epc;
 		force_sig_info(SIGFPE, &info, current);
 		break;

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

* [PATCH 1/2] traps: Fix SIGFPE information leak from `do_ov' and `do_trap_or_bp'
@ 2016-03-04  1:42   ` Maciej W. Rozycki
  0 siblings, 0 replies; 6+ messages in thread
From: Maciej W. Rozycki @ 2016-03-04  1:42 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: Pedro Alves, Luis Machado, linux-mips

Avoid sending a partially initialised `siginfo_t' structure along SIGFPE
signals issued from `do_ov' and `do_trap_or_bp', leading to information
leaking from the kernel stack.

Signed-off-by: Maciej W. Rozycki <macro@imgtec.com>
Cc: stable@vger.kernel.org
---
linux-mips-sig-info-leak.diff
Index: linux-sfr-test/arch/mips/kernel/traps.c
===================================================================
--- linux-sfr-test.orig/arch/mips/kernel/traps.c	2016-03-03 13:34:47.454048000 +0000
+++ linux-sfr-test/arch/mips/kernel/traps.c	2016-03-04 00:56:37.858781000 +0000
@@ -690,15 +690,15 @@ static int simulate_sync(struct pt_regs 
 asmlinkage void do_ov(struct pt_regs *regs)
 {
 	enum ctx_state prev_state;
-	siginfo_t info;
+	siginfo_t info = {
+		.si_signo = SIGFPE,
+		.si_code = FPE_INTOVF,
+		.si_addr = (void __user *)regs->cp0_epc,
+	};
 
 	prev_state = exception_enter();
 	die_if_kernel("Integer overflow", regs);
 
-	info.si_code = FPE_INTOVF;
-	info.si_signo = SIGFPE;
-	info.si_errno = 0;
-	info.si_addr = (void __user *) regs->cp0_epc;
 	force_sig_info(SIGFPE, &info, current);
 	exception_exit(prev_state);
 }
@@ -874,7 +874,7 @@ asmlinkage void do_fpe(struct pt_regs *r
 void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
 	const char *str)
 {
-	siginfo_t info;
+	siginfo_t info = { 0 };
 	char b[40];
 
 #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
@@ -903,7 +903,6 @@ void do_trap_or_bp(struct pt_regs *regs,
 		else
 			info.si_code = FPE_INTOVF;
 		info.si_signo = SIGFPE;
-		info.si_errno = 0;
 		info.si_addr = (void __user *) regs->cp0_epc;
 		force_sig_info(SIGFPE, &info, current);
 		break;

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

* [PATCH 2/2] traps: Correct the SIGTRAP debug ABI in `do_watch' and `do_trap_or_bp'
@ 2016-03-04  1:44   ` Maciej W. Rozycki
  0 siblings, 0 replies; 6+ messages in thread
From: Maciej W. Rozycki @ 2016-03-04  1:44 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: Pedro Alves, Luis Machado, linux-mips, gdb

Follow our own rules set in <asm/siginfo.h> for SIGTRAP signals issued 
from `do_watch' and `do_trap_or_bp' by setting the signal code to 
TRAP_HWBKPT and TRAP_BRKPT respectively, for Watch exceptions and for
those Breakpoint exceptions whose originating BREAK instruction's code
does not have a special meaning.  Keep Trap exceptions unaffected as 
these are not debug events.

No existing user software is expected to examine signal codes for these
signals as SI_KERNEL has been always used here.  This change makes the 
MIPS port more like other Linux ports, which reduces the complexity and 
provides for performance improvement in GDB.

Signed-off-by: Maciej W. Rozycki <macro@imgtec.com>
---
linux-mips-sigtrap-code.diff
Index: linux-sfr-test/arch/mips/include/asm/mips-r2-to-r6-emul.h
===================================================================
--- linux-sfr-test.orig/arch/mips/include/asm/mips-r2-to-r6-emul.h	2016-03-04 00:56:07.699559000 +0000
+++ linux-sfr-test/arch/mips/include/asm/mips-r2-to-r6-emul.h	2016-03-04 00:59:49.221206000 +0000
@@ -79,7 +79,7 @@ struct r2_decoder_table {
 };
 
 
-extern void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
+extern void do_trap_or_bp(struct pt_regs *regs, unsigned int code, int si_code,
 			  const char *str);
 
 #ifndef CONFIG_MIPSR2_TO_R6_EMULATOR
Index: linux-sfr-test/arch/mips/kernel/mips-r2-to-r6-emul.c
===================================================================
--- linux-sfr-test.orig/arch/mips/kernel/mips-r2-to-r6-emul.c	2016-03-04 00:56:07.701558000 +0000
+++ linux-sfr-test/arch/mips/kernel/mips-r2-to-r6-emul.c	2016-03-04 00:59:49.250211000 +0000
@@ -940,42 +940,42 @@ int mipsr2_decoder(struct pt_regs *regs,
 		switch (rt) {
 		case tgei_op:
 			if ((long)regs->regs[rs] >= MIPSInst_SIMM(inst))
-				do_trap_or_bp(regs, 0, "TGEI");
+				do_trap_or_bp(regs, 0, 0, "TGEI");
 
 			MIPS_R2_STATS(traps);
 
 			break;
 		case tgeiu_op:
 			if (regs->regs[rs] >= MIPSInst_UIMM(inst))
-				do_trap_or_bp(regs, 0, "TGEIU");
+				do_trap_or_bp(regs, 0, 0, "TGEIU");
 
 			MIPS_R2_STATS(traps);
 
 			break;
 		case tlti_op:
 			if ((long)regs->regs[rs] < MIPSInst_SIMM(inst))
-				do_trap_or_bp(regs, 0, "TLTI");
+				do_trap_or_bp(regs, 0, 0, "TLTI");
 
 			MIPS_R2_STATS(traps);
 
 			break;
 		case tltiu_op:
 			if (regs->regs[rs] < MIPSInst_UIMM(inst))
-				do_trap_or_bp(regs, 0, "TLTIU");
+				do_trap_or_bp(regs, 0, 0, "TLTIU");
 
 			MIPS_R2_STATS(traps);
 
 			break;
 		case teqi_op:
 			if (regs->regs[rs] == MIPSInst_SIMM(inst))
-				do_trap_or_bp(regs, 0, "TEQI");
+				do_trap_or_bp(regs, 0, 0, "TEQI");
 
 			MIPS_R2_STATS(traps);
 
 			break;
 		case tnei_op:
 			if (regs->regs[rs] != MIPSInst_SIMM(inst))
-				do_trap_or_bp(regs, 0, "TNEI");
+				do_trap_or_bp(regs, 0, 0, "TNEI");
 
 			MIPS_R2_STATS(traps);
 
Index: linux-sfr-test/arch/mips/kernel/traps.c
===================================================================
--- linux-sfr-test.orig/arch/mips/kernel/traps.c	2016-03-04 00:56:37.858781000 +0000
+++ linux-sfr-test/arch/mips/kernel/traps.c	2016-03-04 00:59:49.253206000 +0000
@@ -56,6 +56,7 @@
 #include <asm/pgtable.h>
 #include <asm/ptrace.h>
 #include <asm/sections.h>
+#include <asm/siginfo.h>
 #include <asm/tlbdebug.h>
 #include <asm/traps.h>
 #include <asm/uaccess.h>
@@ -871,7 +872,7 @@ asmlinkage void do_fpe(struct pt_regs *r
 	exception_exit(prev_state);
 }
 
-void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
+void do_trap_or_bp(struct pt_regs *regs, unsigned int code, int si_code,
 	const char *str)
 {
 	siginfo_t info = { 0 };
@@ -928,7 +929,13 @@ void do_trap_or_bp(struct pt_regs *regs,
 	default:
 		scnprintf(b, sizeof(b), "%s instruction in kernel code", str);
 		die_if_kernel(b, regs);
-		force_sig(SIGTRAP, current);
+		if (si_code) {
+			info.si_signo = SIGTRAP;
+			info.si_code = si_code;
+			force_sig_info(SIGTRAP, &info, current);
+		} else {
+			force_sig(SIGTRAP, current);
+		}
 	}
 }
 
@@ -1012,7 +1019,7 @@ asmlinkage void do_bp(struct pt_regs *re
 		break;
 	}
 
-	do_trap_or_bp(regs, bcode, "Break");
+	do_trap_or_bp(regs, bcode, TRAP_BRKPT, "Break");
 
 out:
 	set_fs(seg);
@@ -1054,7 +1061,7 @@ asmlinkage void do_tr(struct pt_regs *re
 			tcode = (opcode >> 6) & ((1 << 10) - 1);
 	}
 
-	do_trap_or_bp(regs, tcode, "Trap");
+	do_trap_or_bp(regs, tcode, 0, "Trap");
 
 out:
 	set_fs(seg);
@@ -1505,6 +1512,7 @@ asmlinkage void do_mdmx(struct pt_regs *
  */
 asmlinkage void do_watch(struct pt_regs *regs)
 {
+	siginfo_t info = { .si_signo = SIGTRAP, .si_code = TRAP_HWBKPT };
 	enum ctx_state prev_state;
 	u32 cause;
 
@@ -1525,7 +1533,7 @@ asmlinkage void do_watch(struct pt_regs 
 	if (test_tsk_thread_flag(current, TIF_LOAD_WATCH)) {
 		mips_read_watch_registers();
 		local_irq_enable();
-		force_sig(SIGTRAP, current);
+		force_sig_info(SIGTRAP, &info, current);
 	} else {
 		mips_clear_watch_registers();
 		local_irq_enable();

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

* [PATCH 2/2] traps: Correct the SIGTRAP debug ABI in `do_watch' and `do_trap_or_bp'
@ 2016-03-04  1:44   ` Maciej W. Rozycki
  0 siblings, 0 replies; 6+ messages in thread
From: Maciej W. Rozycki @ 2016-03-04  1:44 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: Pedro Alves, Luis Machado, linux-mips, gdb

Follow our own rules set in <asm/siginfo.h> for SIGTRAP signals issued 
from `do_watch' and `do_trap_or_bp' by setting the signal code to 
TRAP_HWBKPT and TRAP_BRKPT respectively, for Watch exceptions and for
those Breakpoint exceptions whose originating BREAK instruction's code
does not have a special meaning.  Keep Trap exceptions unaffected as 
these are not debug events.

No existing user software is expected to examine signal codes for these
signals as SI_KERNEL has been always used here.  This change makes the 
MIPS port more like other Linux ports, which reduces the complexity and 
provides for performance improvement in GDB.

Signed-off-by: Maciej W. Rozycki <macro@imgtec.com>
---
linux-mips-sigtrap-code.diff
Index: linux-sfr-test/arch/mips/include/asm/mips-r2-to-r6-emul.h
===================================================================
--- linux-sfr-test.orig/arch/mips/include/asm/mips-r2-to-r6-emul.h	2016-03-04 00:56:07.699559000 +0000
+++ linux-sfr-test/arch/mips/include/asm/mips-r2-to-r6-emul.h	2016-03-04 00:59:49.221206000 +0000
@@ -79,7 +79,7 @@ struct r2_decoder_table {
 };
 
 
-extern void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
+extern void do_trap_or_bp(struct pt_regs *regs, unsigned int code, int si_code,
 			  const char *str);
 
 #ifndef CONFIG_MIPSR2_TO_R6_EMULATOR
Index: linux-sfr-test/arch/mips/kernel/mips-r2-to-r6-emul.c
===================================================================
--- linux-sfr-test.orig/arch/mips/kernel/mips-r2-to-r6-emul.c	2016-03-04 00:56:07.701558000 +0000
+++ linux-sfr-test/arch/mips/kernel/mips-r2-to-r6-emul.c	2016-03-04 00:59:49.250211000 +0000
@@ -940,42 +940,42 @@ int mipsr2_decoder(struct pt_regs *regs,
 		switch (rt) {
 		case tgei_op:
 			if ((long)regs->regs[rs] >= MIPSInst_SIMM(inst))
-				do_trap_or_bp(regs, 0, "TGEI");
+				do_trap_or_bp(regs, 0, 0, "TGEI");
 
 			MIPS_R2_STATS(traps);
 
 			break;
 		case tgeiu_op:
 			if (regs->regs[rs] >= MIPSInst_UIMM(inst))
-				do_trap_or_bp(regs, 0, "TGEIU");
+				do_trap_or_bp(regs, 0, 0, "TGEIU");
 
 			MIPS_R2_STATS(traps);
 
 			break;
 		case tlti_op:
 			if ((long)regs->regs[rs] < MIPSInst_SIMM(inst))
-				do_trap_or_bp(regs, 0, "TLTI");
+				do_trap_or_bp(regs, 0, 0, "TLTI");
 
 			MIPS_R2_STATS(traps);
 
 			break;
 		case tltiu_op:
 			if (regs->regs[rs] < MIPSInst_UIMM(inst))
-				do_trap_or_bp(regs, 0, "TLTIU");
+				do_trap_or_bp(regs, 0, 0, "TLTIU");
 
 			MIPS_R2_STATS(traps);
 
 			break;
 		case teqi_op:
 			if (regs->regs[rs] == MIPSInst_SIMM(inst))
-				do_trap_or_bp(regs, 0, "TEQI");
+				do_trap_or_bp(regs, 0, 0, "TEQI");
 
 			MIPS_R2_STATS(traps);
 
 			break;
 		case tnei_op:
 			if (regs->regs[rs] != MIPSInst_SIMM(inst))
-				do_trap_or_bp(regs, 0, "TNEI");
+				do_trap_or_bp(regs, 0, 0, "TNEI");
 
 			MIPS_R2_STATS(traps);
 
Index: linux-sfr-test/arch/mips/kernel/traps.c
===================================================================
--- linux-sfr-test.orig/arch/mips/kernel/traps.c	2016-03-04 00:56:37.858781000 +0000
+++ linux-sfr-test/arch/mips/kernel/traps.c	2016-03-04 00:59:49.253206000 +0000
@@ -56,6 +56,7 @@
 #include <asm/pgtable.h>
 #include <asm/ptrace.h>
 #include <asm/sections.h>
+#include <asm/siginfo.h>
 #include <asm/tlbdebug.h>
 #include <asm/traps.h>
 #include <asm/uaccess.h>
@@ -871,7 +872,7 @@ asmlinkage void do_fpe(struct pt_regs *r
 	exception_exit(prev_state);
 }
 
-void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
+void do_trap_or_bp(struct pt_regs *regs, unsigned int code, int si_code,
 	const char *str)
 {
 	siginfo_t info = { 0 };
@@ -928,7 +929,13 @@ void do_trap_or_bp(struct pt_regs *regs,
 	default:
 		scnprintf(b, sizeof(b), "%s instruction in kernel code", str);
 		die_if_kernel(b, regs);
-		force_sig(SIGTRAP, current);
+		if (si_code) {
+			info.si_signo = SIGTRAP;
+			info.si_code = si_code;
+			force_sig_info(SIGTRAP, &info, current);
+		} else {
+			force_sig(SIGTRAP, current);
+		}
 	}
 }
 
@@ -1012,7 +1019,7 @@ asmlinkage void do_bp(struct pt_regs *re
 		break;
 	}
 
-	do_trap_or_bp(regs, bcode, "Break");
+	do_trap_or_bp(regs, bcode, TRAP_BRKPT, "Break");
 
 out:
 	set_fs(seg);
@@ -1054,7 +1061,7 @@ asmlinkage void do_tr(struct pt_regs *re
 			tcode = (opcode >> 6) & ((1 << 10) - 1);
 	}
 
-	do_trap_or_bp(regs, tcode, "Trap");
+	do_trap_or_bp(regs, tcode, 0, "Trap");
 
 out:
 	set_fs(seg);
@@ -1505,6 +1512,7 @@ asmlinkage void do_mdmx(struct pt_regs *
  */
 asmlinkage void do_watch(struct pt_regs *regs)
 {
+	siginfo_t info = { .si_signo = SIGTRAP, .si_code = TRAP_HWBKPT };
 	enum ctx_state prev_state;
 	u32 cause;
 
@@ -1525,7 +1533,7 @@ asmlinkage void do_watch(struct pt_regs 
 	if (test_tsk_thread_flag(current, TIF_LOAD_WATCH)) {
 		mips_read_watch_registers();
 		local_irq_enable();
-		force_sig(SIGTRAP, current);
+		force_sig_info(SIGTRAP, &info, current);
 	} else {
 		mips_clear_watch_registers();
 		local_irq_enable();

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

end of thread, other threads:[~2016-03-04  1:44 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-03-04  1:41 [PATCH 0/2] SIGFPE/SIGTRAP sending updates Maciej W. Rozycki
2016-03-04  1:41 ` Maciej W. Rozycki
2016-03-04  1:42 ` [PATCH 1/2] traps: Fix SIGFPE information leak from `do_ov' and `do_trap_or_bp' Maciej W. Rozycki
2016-03-04  1:42   ` Maciej W. Rozycki
2016-03-04  1:44 ` [PATCH 2/2] traps: Correct the SIGTRAP debug ABI in `do_watch' " Maciej W. Rozycki
2016-03-04  1:44   ` Maciej W. Rozycki

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.