All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] arm: ensure dump_instr() checks addr_limit
@ 2017-11-02 16:34 ` Mark Rutland
  0 siblings, 0 replies; 12+ messages in thread
From: Mark Rutland @ 2017-11-02 16:34 UTC (permalink / raw)
  To: linux-arm-kernel; +Cc: Mark Rutland, Russell King, stable

Signed-off-by: Mark Rutland <mark.rutland@arm.com>

When CONFIG_DEBUG_USER is enabled, it's possible for a user to
deliberately trigger dump_instr() with a chosen kernel address.

Let's avoid problems resulting from this by using get_user() rather than
__get_user(), ensuring that we don't erroneously access kernel memory.

So that we can use the same code to dump user instructions and kernel
instructions, the common dumping code is factored out to __dump_instr(),
with the fs manipulated appropriately in dump_instr() around calls to
this.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Russell King <rmk+kernel@armlinux.org.uk>
Cc: stable@vger.kernel.org
---
 arch/arm/kernel/traps.c | 28 ++++++++++++++++++----------
 1 file changed, 18 insertions(+), 10 deletions(-)

diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 948c648fea00..0fcd82f01388 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -154,30 +154,26 @@ static void dump_mem(const char *lvl, const char *str, unsigned long bottom,
 	set_fs(fs);
 }
 
-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);
 	const int thumb = thumb_mode(regs);
 	const int width = thumb ? 4 : 8;
-	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.
+	 * 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 + !!thumb; i++) {
 		unsigned int val, bad;
 
 		if (thumb)
-			bad = __get_user(val, &((u16 *)addr)[i]);
+			bad = get_user(val, &((u16 *)addr)[i]);
 		else
-			bad = __get_user(val, &((u32 *)addr)[i]);
+			bad = get_user(val, &((u32 *)addr)[i]);
 
 		if (!bad)
 			p += sprintf(p, i == 0 ? "(%0*x) " : "%0*x ",
@@ -188,8 +184,20 @@ 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)
+{
+	mm_segment_t fs;
+
+	if (!user_mode(regs)) {
+		fs = get_fs();
+		set_fs(KERNEL_DS);
+		__dump_instr(lvl, regs);
+		set_fs(fs);
+	} else {
+		__dump_instr(lvl, regs);
+	}
 }
 
 #ifdef CONFIG_ARM_UNWIND
-- 
2.11.0

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

* [PATCH] arm: ensure dump_instr() checks addr_limit
@ 2017-11-02 16:34 ` Mark Rutland
  0 siblings, 0 replies; 12+ messages in thread
From: Mark Rutland @ 2017-11-02 16:34 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Mark Rutland <mark.rutland@arm.com>

When CONFIG_DEBUG_USER is enabled, it's possible for a user to
deliberately trigger dump_instr() with a chosen kernel address.

Let's avoid problems resulting from this by using get_user() rather than
__get_user(), ensuring that we don't erroneously access kernel memory.

So that we can use the same code to dump user instructions and kernel
instructions, the common dumping code is factored out to __dump_instr(),
with the fs manipulated appropriately in dump_instr() around calls to
this.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Russell King <rmk+kernel@armlinux.org.uk>
Cc: stable at vger.kernel.org
---
 arch/arm/kernel/traps.c | 28 ++++++++++++++++++----------
 1 file changed, 18 insertions(+), 10 deletions(-)

diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 948c648fea00..0fcd82f01388 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -154,30 +154,26 @@ static void dump_mem(const char *lvl, const char *str, unsigned long bottom,
 	set_fs(fs);
 }
 
-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);
 	const int thumb = thumb_mode(regs);
 	const int width = thumb ? 4 : 8;
-	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.
+	 * 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 + !!thumb; i++) {
 		unsigned int val, bad;
 
 		if (thumb)
-			bad = __get_user(val, &((u16 *)addr)[i]);
+			bad = get_user(val, &((u16 *)addr)[i]);
 		else
-			bad = __get_user(val, &((u32 *)addr)[i]);
+			bad = get_user(val, &((u32 *)addr)[i]);
 
 		if (!bad)
 			p += sprintf(p, i == 0 ? "(%0*x) " : "%0*x ",
@@ -188,8 +184,20 @@ 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)
+{
+	mm_segment_t fs;
+
+	if (!user_mode(regs)) {
+		fs = get_fs();
+		set_fs(KERNEL_DS);
+		__dump_instr(lvl, regs);
+		set_fs(fs);
+	} else {
+		__dump_instr(lvl, regs);
+	}
 }
 
 #ifdef CONFIG_ARM_UNWIND
-- 
2.11.0

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

* Re: [PATCH] arm: ensure dump_instr() checks addr_limit
  2017-11-02 16:34 ` Mark Rutland
@ 2017-11-02 16:47   ` Greg KH
  -1 siblings, 0 replies; 12+ messages in thread
From: Greg KH @ 2017-11-02 16:47 UTC (permalink / raw)
  To: Mark Rutland; +Cc: linux-arm-kernel, Russell King, stable

On Thu, Nov 02, 2017 at 04:34:52PM +0000, Mark Rutland wrote:
> Signed-off-by: Mark Rutland <mark.rutland@arm.com>

Huh?  What's that doing up here?

> When CONFIG_DEBUG_USER is enabled, it's possible for a user to
> deliberately trigger dump_instr() with a chosen kernel address.
> 
> Let's avoid problems resulting from this by using get_user() rather than
> __get_user(), ensuring that we don't erroneously access kernel memory.
> 
> So that we can use the same code to dump user instructions and kernel
> instructions, the common dumping code is factored out to __dump_instr(),
> with the fs manipulated appropriately in dump_instr() around calls to
> this.
> 
> Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> Cc: Russell King <rmk+kernel@armlinux.org.uk>
> Cc: stable@vger.kernel.org

It's right here...

confused.

greg k-h

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

* [PATCH] arm: ensure dump_instr() checks addr_limit
@ 2017-11-02 16:47   ` Greg KH
  0 siblings, 0 replies; 12+ messages in thread
From: Greg KH @ 2017-11-02 16:47 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Nov 02, 2017 at 04:34:52PM +0000, Mark Rutland wrote:
> Signed-off-by: Mark Rutland <mark.rutland@arm.com>

Huh?  What's that doing up here?

> When CONFIG_DEBUG_USER is enabled, it's possible for a user to
> deliberately trigger dump_instr() with a chosen kernel address.
> 
> Let's avoid problems resulting from this by using get_user() rather than
> __get_user(), ensuring that we don't erroneously access kernel memory.
> 
> So that we can use the same code to dump user instructions and kernel
> instructions, the common dumping code is factored out to __dump_instr(),
> with the fs manipulated appropriately in dump_instr() around calls to
> this.
> 
> Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> Cc: Russell King <rmk+kernel@armlinux.org.uk>
> Cc: stable at vger.kernel.org

It's right here...

confused.

greg k-h

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

* Re: [PATCH] arm: ensure dump_instr() checks addr_limit
  2017-11-02 16:34 ` Mark Rutland
@ 2017-11-02 16:57   ` Russell King - ARM Linux
  -1 siblings, 0 replies; 12+ messages in thread
From: Russell King - ARM Linux @ 2017-11-02 16:57 UTC (permalink / raw)
  To: Mark Rutland; +Cc: linux-arm-kernel, stable

On Thu, Nov 02, 2017 at 04:34:52PM +0000, Mark Rutland wrote:
> Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> 
> When CONFIG_DEBUG_USER is enabled, it's possible for a user to
> deliberately trigger dump_instr() with a chosen kernel address.

Hi Mark,

Please show how userspace could trigger that, as I don't think it's
possible.  Firstly, you need to set PC to a kernel address, which
will trigger an abort.

When that happens, we'll get a section permission fault, and head
to do_sect_fault().  This will call do_bad_area(), which will detect
that it's a userspace fault (because of the CPSR value).

This calls show_pte() and show_regs().  show_pte() shows the page
table values only.  show_regs() shows the register values, and then
dumps the kernel stack via show_stack().  Nothing in this path calls
dump_instr().

The places where dump_instr() is called from are:

	die()
	do_undefinstr()
	bad_syscall()
	arm_syscall()
	baddataabort() (only for late v4 faulting architectures)

The last four all need the CPU to have read and attempted to execute
the instruction, so the permission checks must have passed.  Userspace
can't achieve that by setting the PC to a kernel address.

die() is called when we enter an exception in an invalid mode, or we
have a kernel mode fault (CPSR in kernel mode) that we can't handle,
we have fault handling disabled (never the case when running user
code), or we have no mm (kernel thread).

So, I don't see how the kernel could be provoked to dump instructions
from kernel space by the user.

Please show a working example.

Thanks.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up

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

* [PATCH] arm: ensure dump_instr() checks addr_limit
@ 2017-11-02 16:57   ` Russell King - ARM Linux
  0 siblings, 0 replies; 12+ messages in thread
From: Russell King - ARM Linux @ 2017-11-02 16:57 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Nov 02, 2017 at 04:34:52PM +0000, Mark Rutland wrote:
> Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> 
> When CONFIG_DEBUG_USER is enabled, it's possible for a user to
> deliberately trigger dump_instr() with a chosen kernel address.

Hi Mark,

Please show how userspace could trigger that, as I don't think it's
possible.  Firstly, you need to set PC to a kernel address, which
will trigger an abort.

When that happens, we'll get a section permission fault, and head
to do_sect_fault().  This will call do_bad_area(), which will detect
that it's a userspace fault (because of the CPSR value).

This calls show_pte() and show_regs().  show_pte() shows the page
table values only.  show_regs() shows the register values, and then
dumps the kernel stack via show_stack().  Nothing in this path calls
dump_instr().

The places where dump_instr() is called from are:

	die()
	do_undefinstr()
	bad_syscall()
	arm_syscall()
	baddataabort() (only for late v4 faulting architectures)

The last four all need the CPU to have read and attempted to execute
the instruction, so the permission checks must have passed.  Userspace
can't achieve that by setting the PC to a kernel address.

die() is called when we enter an exception in an invalid mode, or we
have a kernel mode fault (CPSR in kernel mode) that we can't handle,
we have fault handling disabled (never the case when running user
code), or we have no mm (kernel thread).

So, I don't see how the kernel could be provoked to dump instructions
from kernel space by the user.

Please show a working example.

Thanks.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up

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

* Re: [PATCH] arm: ensure dump_instr() checks addr_limit
  2017-11-02 16:47   ` Greg KH
@ 2017-11-02 17:30     ` Mark Rutland
  -1 siblings, 0 replies; 12+ messages in thread
From: Mark Rutland @ 2017-11-02 17:30 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-arm-kernel, Russell King, stable

On Thu, Nov 02, 2017 at 05:47:06PM +0100, Greg KH wrote:
> On Thu, Nov 02, 2017 at 04:34:52PM +0000, Mark Rutland wrote:
> > Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> 
> Huh?  What's that doing up here?

[...]

> > Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> > Cc: Russell King <rmk+kernel@armlinux.org.uk>
> > Cc: stable@vger.kernel.org
> 
> It's right here...

Sorry; I'd generated this commit message from another. I must've
accidentally passed -s to git commit before copying the text I wanted.

I will be more careful in future, and I'll remove the first instance
if/when submitting this to Russell's patch system.

Thanks,
Mark.

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

* [PATCH] arm: ensure dump_instr() checks addr_limit
@ 2017-11-02 17:30     ` Mark Rutland
  0 siblings, 0 replies; 12+ messages in thread
From: Mark Rutland @ 2017-11-02 17:30 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Nov 02, 2017 at 05:47:06PM +0100, Greg KH wrote:
> On Thu, Nov 02, 2017 at 04:34:52PM +0000, Mark Rutland wrote:
> > Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> 
> Huh?  What's that doing up here?

[...]

> > Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> > Cc: Russell King <rmk+kernel@armlinux.org.uk>
> > Cc: stable at vger.kernel.org
> 
> It's right here...

Sorry; I'd generated this commit message from another. I must've
accidentally passed -s to git commit before copying the text I wanted.

I will be more careful in future, and I'll remove the first instance
if/when submitting this to Russell's patch system.

Thanks,
Mark.

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

* Re: [PATCH] arm: ensure dump_instr() checks addr_limit
  2017-11-02 17:30     ` Mark Rutland
@ 2017-11-02 17:46       ` Greg KH
  -1 siblings, 0 replies; 12+ messages in thread
From: Greg KH @ 2017-11-02 17:46 UTC (permalink / raw)
  To: Mark Rutland; +Cc: linux-arm-kernel, Russell King, stable

On Thu, Nov 02, 2017 at 05:30:04PM +0000, Mark Rutland wrote:
> On Thu, Nov 02, 2017 at 05:47:06PM +0100, Greg KH wrote:
> > On Thu, Nov 02, 2017 at 04:34:52PM +0000, Mark Rutland wrote:
> > > Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> > 
> > Huh?  What's that doing up here?
> 
> [...]
> 
> > > Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> > > Cc: Russell King <rmk+kernel@armlinux.org.uk>
> > > Cc: stable@vger.kernel.org
> > 
> > It's right here...
> 
> Sorry; I'd generated this commit message from another. I must've
> accidentally passed -s to git commit before copying the text I wanted.
> 
> I will be more careful in future, and I'll remove the first instance
> if/when submitting this to Russell's patch system.

Russell's patch system?  That's still in use and required?  Ugh, that's
crazy...

Anyway, thanks for fixing it up.

greg k-h

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

* [PATCH] arm: ensure dump_instr() checks addr_limit
@ 2017-11-02 17:46       ` Greg KH
  0 siblings, 0 replies; 12+ messages in thread
From: Greg KH @ 2017-11-02 17:46 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Nov 02, 2017 at 05:30:04PM +0000, Mark Rutland wrote:
> On Thu, Nov 02, 2017 at 05:47:06PM +0100, Greg KH wrote:
> > On Thu, Nov 02, 2017 at 04:34:52PM +0000, Mark Rutland wrote:
> > > Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> > 
> > Huh?  What's that doing up here?
> 
> [...]
> 
> > > Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> > > Cc: Russell King <rmk+kernel@armlinux.org.uk>
> > > Cc: stable at vger.kernel.org
> > 
> > It's right here...
> 
> Sorry; I'd generated this commit message from another. I must've
> accidentally passed -s to git commit before copying the text I wanted.
> 
> I will be more careful in future, and I'll remove the first instance
> if/when submitting this to Russell's patch system.

Russell's patch system?  That's still in use and required?  Ugh, that's
crazy...

Anyway, thanks for fixing it up.

greg k-h

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

* Re: [PATCH] arm: ensure dump_instr() checks addr_limit
  2017-11-02 17:46       ` Greg KH
@ 2017-11-02 17:50         ` Russell King - ARM Linux
  -1 siblings, 0 replies; 12+ messages in thread
From: Russell King - ARM Linux @ 2017-11-02 17:50 UTC (permalink / raw)
  To: Greg KH; +Cc: Mark Rutland, linux-arm-kernel, stable

On Thu, Nov 02, 2017 at 06:46:28PM +0100, Greg KH wrote:
> On Thu, Nov 02, 2017 at 05:30:04PM +0000, Mark Rutland wrote:
> > On Thu, Nov 02, 2017 at 05:47:06PM +0100, Greg KH wrote:
> > > On Thu, Nov 02, 2017 at 04:34:52PM +0000, Mark Rutland wrote:
> > > > Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> > > 
> > > Huh?  What's that doing up here?
> > 
> > [...]
> > 
> > > > Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> > > > Cc: Russell King <rmk+kernel@armlinux.org.uk>
> > > > Cc: stable@vger.kernel.org
> > > 
> > > It's right here...
> > 
> > Sorry; I'd generated this commit message from another. I must've
> > accidentally passed -s to git commit before copying the text I wanted.
> > 
> > I will be more careful in future, and I'll remove the first instance
> > if/when submitting this to Russell's patch system.
> 
> Russell's patch system?  That's still in use and required?  Ugh, that's
> crazy...

Better than me missing patches because they've been buried under tonnes
of email.  It also does a fair number of checks, and there's been some
discussion today about adding to the checks it does to catch stupidity
in what the binutils assembler now accepts (to stop patches that appear
to be tested but are broken from getting in, as what happened last night.)

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up

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

* [PATCH] arm: ensure dump_instr() checks addr_limit
@ 2017-11-02 17:50         ` Russell King - ARM Linux
  0 siblings, 0 replies; 12+ messages in thread
From: Russell King - ARM Linux @ 2017-11-02 17:50 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Nov 02, 2017 at 06:46:28PM +0100, Greg KH wrote:
> On Thu, Nov 02, 2017 at 05:30:04PM +0000, Mark Rutland wrote:
> > On Thu, Nov 02, 2017 at 05:47:06PM +0100, Greg KH wrote:
> > > On Thu, Nov 02, 2017 at 04:34:52PM +0000, Mark Rutland wrote:
> > > > Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> > > 
> > > Huh?  What's that doing up here?
> > 
> > [...]
> > 
> > > > Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> > > > Cc: Russell King <rmk+kernel@armlinux.org.uk>
> > > > Cc: stable at vger.kernel.org
> > > 
> > > It's right here...
> > 
> > Sorry; I'd generated this commit message from another. I must've
> > accidentally passed -s to git commit before copying the text I wanted.
> > 
> > I will be more careful in future, and I'll remove the first instance
> > if/when submitting this to Russell's patch system.
> 
> Russell's patch system?  That's still in use and required?  Ugh, that's
> crazy...

Better than me missing patches because they've been buried under tonnes
of email.  It also does a fair number of checks, and there's been some
discussion today about adding to the checks it does to catch stupidity
in what the binutils assembler now accepts (to stop patches that appear
to be tested but are broken from getting in, as what happened last night.)

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up

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

end of thread, other threads:[~2017-11-02 17:50 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-11-02 16:34 [PATCH] arm: ensure dump_instr() checks addr_limit Mark Rutland
2017-11-02 16:34 ` Mark Rutland
2017-11-02 16:47 ` Greg KH
2017-11-02 16:47   ` Greg KH
2017-11-02 17:30   ` Mark Rutland
2017-11-02 17:30     ` Mark Rutland
2017-11-02 17:46     ` Greg KH
2017-11-02 17:46       ` Greg KH
2017-11-02 17:50       ` Russell King - ARM Linux
2017-11-02 17:50         ` Russell King - ARM Linux
2017-11-02 16:57 ` Russell King - ARM Linux
2017-11-02 16:57   ` Russell King - ARM Linux

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.