* [PATCH 0/2] arm64: traps.c fix + cleanup @ 2016-06-13 10:15 Mark Rutland 2016-06-13 10:15 ` [PATCH 1/2] arm64: fix dump_instr when PAN and UAO are in use Mark Rutland 2016-06-13 10:15 ` [PATCH 2/2] arm64: simplify dump_mem Mark Rutland 0 siblings, 2 replies; 7+ messages in thread From: Mark Rutland @ 2016-06-13 10:15 UTC (permalink / raw) To: linux-arm-kernel Vladimir pointed out that we have an issue with handling undefined instruction when both PAN & UAO are in use, due to dump_instr always using KERNEL_DS, regardles of the context of the undefined instruction. Patch 1 addresses this. While investigating, I noticed that our dump_mem usage looked a bit suspicious. It turns out that we try to handle a case that doesn't happen in practice, and do so inconsistently, but as the code is never called this is not harmful in practice. Patch 2 removes the redundant code. Thanks, Mark. Mark Rutland (2): arm64: fix dump_instr when PAN and UAO are in use arm64: simplify dump_mem arch/arm64/kernel/traps.c | 57 ++++++++++++++++++++--------------------------- 1 file changed, 24 insertions(+), 33 deletions(-) -- 1.9.1 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/2] arm64: fix dump_instr when PAN and UAO are in use 2016-06-13 10:15 [PATCH 0/2] arm64: traps.c fix + cleanup Mark Rutland @ 2016-06-13 10:15 ` Mark Rutland 2016-06-13 12:15 ` Vladimir Murzin 2016-06-13 12:48 ` Will Deacon 2016-06-13 10:15 ` [PATCH 2/2] arm64: simplify dump_mem Mark Rutland 1 sibling, 2 replies; 7+ messages in thread From: Mark Rutland @ 2016-06-13 10:15 UTC (permalink / raw) To: linux-arm-kernel If the kernel is set to show unhandled signals, and a user task does not handle a SIGILL as a result of an instruction abort, we will attempt to log the offending instruction with dump_instr before killing the task. We use dump_instr to log the encoding of the offending userspace instruction. However, dump_instr is also used to dump instructions from kernel space, and internally always switches to KERNEL_DS before dumping the instruction with get_user. When both PAN and UAO are in use, reading a user instruction via get_user while in KERNEL_DS will result in a permission fault, which leads to an Oops. As we have regs corresponding to the context of the original instruction abort, we can inspect this and only flip to KERNEL_DS if the original abort was taken from the kernel, avoiding this issue. At the same time, remove the redundant (and incorrect) comments regarding the order dump_mem and dump_instr are called in. Signed-off-by: Mark Rutland <mark.rutland@arm.com> Reported-by: Vladimir Murzin <vladimir.murzin@arm.com> Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: James Morse <james.morse@arm.com> Cc: Robin Murphy <robin.murphy@arm.com> Cc: Will Deacon <will.deacon@arm.com> Fixes: 57f4959bad0a154a ("arm64: kernel: Add support for User Access Override") --- arch/arm64/kernel/traps.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index f7cf463..2a43012 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -64,8 +64,7 @@ static void dump_mem(const char *lvl, const char *str, unsigned long bottom, /* * We need to switch to kernel mode so that we can use __get_user - * to safely read from kernel space. Note that we now dump the - * code first, just in case the backtrace kills us. + * to safely read from kernel space. */ fs = get_fs(); set_fs(KERNEL_DS); @@ -111,21 +110,12 @@ static void dump_backtrace_entry(unsigned long where) print_ip_sym(where); } -static void dump_instr(const char *lvl, struct pt_regs *regs) +static void __dump_instr(const char *lvl, struct pt_regs *regs) { unsigned long addr = instruction_pointer(regs); - mm_segment_t fs; char str[sizeof("00000000 ") * 5 + 2 + 1], *p = str; int i; - /* - * We need to switch to kernel mode so that we can use __get_user - * to safely read from kernel space. Note that we now dump the - * code first, just in case the backtrace kills us. - */ - fs = get_fs(); - set_fs(KERNEL_DS); - for (i = -4; i < 1; i++) { unsigned int val, bad; @@ -139,8 +129,18 @@ static void dump_instr(const char *lvl, struct pt_regs *regs) } } printk("%sCode: %s\n", lvl, str); +} - set_fs(fs); +static void dump_instr(const char *lvl, struct pt_regs *regs) +{ + if (!user_mode(regs)) { + mm_segment_t fs = get_fs(); + set_fs(KERNEL_DS); + __dump_instr(lvl, regs); + set_fs(fs); + } else { + __dump_instr(lvl, regs); + } } static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) -- 1.9.1 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 1/2] arm64: fix dump_instr when PAN and UAO are in use 2016-06-13 10:15 ` [PATCH 1/2] arm64: fix dump_instr when PAN and UAO are in use Mark Rutland @ 2016-06-13 12:15 ` Vladimir Murzin 2016-06-13 12:48 ` Will Deacon 1 sibling, 0 replies; 7+ messages in thread From: Vladimir Murzin @ 2016-06-13 12:15 UTC (permalink / raw) To: linux-arm-kernel On 13/06/16 11:15, Mark Rutland wrote: > If the kernel is set to show unhandled signals, and a user task does not > handle a SIGILL as a result of an instruction abort, we will attempt to > log the offending instruction with dump_instr before killing the task. > > We use dump_instr to log the encoding of the offending userspace > instruction. However, dump_instr is also used to dump instructions from > kernel space, and internally always switches to KERNEL_DS before dumping > the instruction with get_user. When both PAN and UAO are in use, reading > a user instruction via get_user while in KERNEL_DS will result in a > permission fault, which leads to an Oops. > > As we have regs corresponding to the context of the original instruction > abort, we can inspect this and only flip to KERNEL_DS if the original > abort was taken from the kernel, avoiding this issue. At the same time, > remove the redundant (and incorrect) comments regarding the order > dump_mem and dump_instr are called in. > > Signed-off-by: Mark Rutland <mark.rutland@arm.com> > Reported-by: Vladimir Murzin <vladimir.murzin@arm.com> > Cc: Catalin Marinas <catalin.marinas@arm.com> > Cc: James Morse <james.morse@arm.com> > Cc: Robin Murphy <robin.murphy@arm.com> > Cc: Will Deacon <will.deacon@arm.com> > Fixes: 57f4959bad0a154a ("arm64: kernel: Add support for User Access Override") FWIW: Tested-by: Vladimir Murzin <vladimir.murzin@arm.com> with $ echo 0 > /proc/sys/abi/swp Removed swp emulation handler $. /swp_test $ cat swp_test.c int main(void) { unsigned long ret, x = 42, y = 24; asm volatile("swp %0, %1, [%2]" : "=&r" (ret) : "r" (x), "r" (&y) : "memory"); return ret; } Thanks Vladimir ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/2] arm64: fix dump_instr when PAN and UAO are in use 2016-06-13 10:15 ` [PATCH 1/2] arm64: fix dump_instr when PAN and UAO are in use Mark Rutland 2016-06-13 12:15 ` Vladimir Murzin @ 2016-06-13 12:48 ` Will Deacon 2016-06-13 12:54 ` Mark Rutland 1 sibling, 1 reply; 7+ messages in thread From: Will Deacon @ 2016-06-13 12:48 UTC (permalink / raw) To: linux-arm-kernel On Mon, Jun 13, 2016 at 11:15:14AM +0100, Mark Rutland wrote: > If the kernel is set to show unhandled signals, and a user task does not > handle a SIGILL as a result of an instruction abort, we will attempt to > log the offending instruction with dump_instr before killing the task. > > We use dump_instr to log the encoding of the offending userspace > instruction. However, dump_instr is also used to dump instructions from > kernel space, and internally always switches to KERNEL_DS before dumping > the instruction with get_user. When both PAN and UAO are in use, reading > a user instruction via get_user while in KERNEL_DS will result in a > permission fault, which leads to an Oops. > > As we have regs corresponding to the context of the original instruction > abort, we can inspect this and only flip to KERNEL_DS if the original > abort was taken from the kernel, avoiding this issue. At the same time, > remove the redundant (and incorrect) comments regarding the order > dump_mem and dump_instr are called in. > > Signed-off-by: Mark Rutland <mark.rutland@arm.com> > Reported-by: Vladimir Murzin <vladimir.murzin@arm.com> > Cc: Catalin Marinas <catalin.marinas@arm.com> > Cc: James Morse <james.morse@arm.com> > Cc: Robin Murphy <robin.murphy@arm.com> > Cc: Will Deacon <will.deacon@arm.com> > Fixes: 57f4959bad0a154a ("arm64: kernel: Add support for User Access Override") > --- > arch/arm64/kernel/traps.c | 26 +++++++++++++------------- > 1 file changed, 13 insertions(+), 13 deletions(-) Queued as a fix for 4.8 w/ Vladimir's Tested-by. Please try to keep fixes and cleanups/features separate in future series. Will ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/2] arm64: fix dump_instr when PAN and UAO are in use 2016-06-13 12:48 ` Will Deacon @ 2016-06-13 12:54 ` Mark Rutland 0 siblings, 0 replies; 7+ messages in thread From: Mark Rutland @ 2016-06-13 12:54 UTC (permalink / raw) To: linux-arm-kernel On Mon, Jun 13, 2016 at 01:48:24PM +0100, Will Deacon wrote: > On Mon, Jun 13, 2016 at 11:15:14AM +0100, Mark Rutland wrote: > > If the kernel is set to show unhandled signals, and a user task does not > > handle a SIGILL as a result of an instruction abort, we will attempt to > > log the offending instruction with dump_instr before killing the task. > > > > We use dump_instr to log the encoding of the offending userspace > > instruction. However, dump_instr is also used to dump instructions from > > kernel space, and internally always switches to KERNEL_DS before dumping > > the instruction with get_user. When both PAN and UAO are in use, reading > > a user instruction via get_user while in KERNEL_DS will result in a > > permission fault, which leads to an Oops. > > > > As we have regs corresponding to the context of the original instruction > > abort, we can inspect this and only flip to KERNEL_DS if the original > > abort was taken from the kernel, avoiding this issue. At the same time, > > remove the redundant (and incorrect) comments regarding the order > > dump_mem and dump_instr are called in. > > > > Signed-off-by: Mark Rutland <mark.rutland@arm.com> > > Reported-by: Vladimir Murzin <vladimir.murzin@arm.com> > > Cc: Catalin Marinas <catalin.marinas@arm.com> > > Cc: James Morse <james.morse@arm.com> > > Cc: Robin Murphy <robin.murphy@arm.com> > > Cc: Will Deacon <will.deacon@arm.com> > > Fixes: 57f4959bad0a154a ("arm64: kernel: Add support for User Access Override") > > --- > > arch/arm64/kernel/traps.c | 26 +++++++++++++------------- > > 1 file changed, 13 insertions(+), 13 deletions(-) > > Queued as a fix for 4.8 w/ Vladimir's Tested-by. Please try to keep fixes > and cleanups/features separate in future series. Cheers, will do. I assume you've only taken patch 1, and it's up to Catalin to take patch 2 for v4.8. I'll poke as necessary for that to happen. Thanks, Mark. ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 2/2] arm64: simplify dump_mem 2016-06-13 10:15 [PATCH 0/2] arm64: traps.c fix + cleanup Mark Rutland 2016-06-13 10:15 ` [PATCH 1/2] arm64: fix dump_instr when PAN and UAO are in use Mark Rutland @ 2016-06-13 10:15 ` Mark Rutland 2016-06-21 14:48 ` Catalin Marinas 1 sibling, 1 reply; 7+ messages in thread From: Mark Rutland @ 2016-06-13 10:15 UTC (permalink / raw) To: linux-arm-kernel Currently dump_mem attempts to dump memory in 64-bit chunks when reporting a failure in 64-bit code, or 32-bit chunks when reporting a failure in 32-bit code. We added code to handle these two cases separately in commit e147ae6d7f908412 ("arm64: modify the dump mem for 64 bit addresses"). However, in all cases dump_mem is called, the failing context is a kernel rather than user context. Additionally dump_mem is assumed to only be used for kernel contexts, as internally it switches to KERNEL_DS, and its callers pass kernel stack bounds. This patch removes the redundant 32-bit chunk logic and associated compat parameter, largely reverting the aforementioned commit. For the call in __die(), the check of in_interrupt() is removed also, as __die() is only called in response to faults from the kernel's exception level, and thus the !user_mode(regs) check is sufficient. Were this not the case, the used of task_stack_page(tsk) to generate the stack bounds would be erroneous. Signed-off-by: Mark Rutland <mark.rutland@arm.com> Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Will Deacon <will.deacon@arm.com> --- arch/arm64/kernel/traps.c | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index 2a43012..d9da2c5 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -52,15 +52,14 @@ static const char *handler[]= { int show_unhandled_signals = 1; /* - * Dump out the contents of some memory nicely... + * Dump out the contents of some kernel memory nicely... */ static void dump_mem(const char *lvl, const char *str, unsigned long bottom, - unsigned long top, bool compat) + unsigned long top) { unsigned long first; mm_segment_t fs; int i; - unsigned int width = compat ? 4 : 8; /* * We need to switch to kernel mode so that we can use __get_user @@ -78,22 +77,15 @@ static void dump_mem(const char *lvl, const char *str, unsigned long bottom, memset(str, ' ', sizeof(str)); str[sizeof(str) - 1] = '\0'; - for (p = first, i = 0; i < (32 / width) - && p < top; i++, p += width) { + for (p = first, i = 0; i < (32 / 8) + && p < top; i++, p += 8) { if (p >= bottom && p < top) { unsigned long val; - if (width == 8) { - if (__get_user(val, (unsigned long *)p) == 0) - sprintf(str + i * 17, " %016lx", val); - else - sprintf(str + i * 17, " ????????????????"); - } else { - if (__get_user(val, (unsigned int *)p) == 0) - sprintf(str + i * 9, " %08lx", val); - else - sprintf(str + i * 9, " ????????"); - } + if (__get_user(val, (unsigned long *)p) == 0) + sprintf(str + i * 17, " %016lx", val); + else + sprintf(str + i * 17, " ????????????????"); } } printk("%s%04lx:%s\n", lvl, first & 0xffff, str); @@ -216,7 +208,7 @@ static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) stack = IRQ_STACK_TO_TASK_STACK(irq_stack_ptr); dump_mem("", "Exception stack", stack, - stack + sizeof(struct pt_regs), false); + stack + sizeof(struct pt_regs)); } } } @@ -254,10 +246,9 @@ static int __die(const char *str, int err, struct thread_info *thread, pr_emerg("Process %.*s (pid: %d, stack limit = 0x%p)\n", TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), thread + 1); - if (!user_mode(regs) || in_interrupt()) { + if (!user_mode(regs)) { dump_mem(KERN_EMERG, "Stack: ", regs->sp, - THREAD_SIZE + (unsigned long)task_stack_page(tsk), - compat_user_mode(regs)); + THREAD_SIZE + (unsigned long)task_stack_page(tsk)); dump_backtrace(regs, tsk); dump_instr(KERN_EMERG, regs); } -- 1.9.1 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/2] arm64: simplify dump_mem 2016-06-13 10:15 ` [PATCH 2/2] arm64: simplify dump_mem Mark Rutland @ 2016-06-21 14:48 ` Catalin Marinas 0 siblings, 0 replies; 7+ messages in thread From: Catalin Marinas @ 2016-06-21 14:48 UTC (permalink / raw) To: linux-arm-kernel On Mon, Jun 13, 2016 at 11:15:15AM +0100, Mark Rutland wrote: > Currently dump_mem attempts to dump memory in 64-bit chunks when > reporting a failure in 64-bit code, or 32-bit chunks when reporting a > failure in 32-bit code. We added code to handle these two cases > separately in commit e147ae6d7f908412 ("arm64: modify the dump mem for > 64 bit addresses"). > > However, in all cases dump_mem is called, the failing context is a > kernel rather than user context. Additionally dump_mem is assumed to > only be used for kernel contexts, as internally it switches to > KERNEL_DS, and its callers pass kernel stack bounds. > > This patch removes the redundant 32-bit chunk logic and associated > compat parameter, largely reverting the aforementioned commit. For the > call in __die(), the check of in_interrupt() is removed also, as __die() > is only called in response to faults from the kernel's exception level, > and thus the !user_mode(regs) check is sufficient. Were this not the > case, the used of task_stack_page(tsk) to generate the stack bounds > would be erroneous. > > Signed-off-by: Mark Rutland <mark.rutland@arm.com> > Cc: Catalin Marinas <catalin.marinas@arm.com> > Cc: Will Deacon <will.deacon@arm.com> Queued for 4.8. Thanks. -- Catalin ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2016-06-21 14:48 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2016-06-13 10:15 [PATCH 0/2] arm64: traps.c fix + cleanup Mark Rutland 2016-06-13 10:15 ` [PATCH 1/2] arm64: fix dump_instr when PAN and UAO are in use Mark Rutland 2016-06-13 12:15 ` Vladimir Murzin 2016-06-13 12:48 ` Will Deacon 2016-06-13 12:54 ` Mark Rutland 2016-06-13 10:15 ` [PATCH 2/2] arm64: simplify dump_mem Mark Rutland 2016-06-21 14:48 ` Catalin Marinas
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).