* [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.