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