All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] x86, mpx: Fixes for 32-bit userspace
@ 2015-11-11 18:19 Dave Hansen
  2015-11-11 18:19 ` [PATCH 1/2] x86, mpx: do proper get_user() when running 32-bit binaries on 64-bit Dave Hansen
  2015-11-11 18:19 ` [PATCH 2/2] x86, mpx: fix 32-bit address space calculation Dave Hansen
  0 siblings, 2 replies; 5+ messages in thread
From: Dave Hansen @ 2015-11-11 18:19 UTC (permalink / raw)
  To: linux-kernel; +Cc: x86, Dave Hansen

These fix up two relatively minor issues that show up when running
32-bit kernels on 64-bit hardware, or 32-bit binaries on 64-bit
kernels.

 mpx.c |   47 +++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 41 insertions(+), 6 deletions(-)

Dave Hansen (2):
	x86, mpx: do proper get_user() when running 32-bit binaries on 64-bit
	x86, mpx: fix 32-bit address space calculation


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

* [PATCH 1/2] x86, mpx: do proper get_user() when running 32-bit binaries on 64-bit
  2015-11-11 18:19 [PATCH 0/2] x86, mpx: Fixes for 32-bit userspace Dave Hansen
@ 2015-11-11 18:19 ` Dave Hansen
  2015-11-12 13:27   ` [tip:x86/urgent] x86/mpx: Do proper get_user() when running 32-bit binaries on 64-bit kernels tip-bot for Dave Hansen
  2015-11-11 18:19 ` [PATCH 2/2] x86, mpx: fix 32-bit address space calculation Dave Hansen
  1 sibling, 1 reply; 5+ messages in thread
From: Dave Hansen @ 2015-11-11 18:19 UTC (permalink / raw)
  To: linux-kernel; +Cc: x86, Dave Hansen, dave.hansen


From: Dave Hansen <dave.hansen@linux.intel.com>

When you call get_user(foo, bar), you effectively do a

	copy_from_user(&foo, bar, sizeof(*bar));

Note that the sizeof() is implicit.

When we reach out to userspace to try to zap an entire "bounds table"
we need to go read a "bounds directory entry" in order to locate the
table's address.  The size of a "directory entry" depends on the
binary being run and is always the size of a pointer.

But, when we have a 64-bit kernel and a 32-bit application, the
directory entry is still only 32-bits long, but we fetch it with a
64-bit pointer which makes get_user() does a 64-bit fetch.  Reading
4 extra bytes isn't harmful, unless we are at the end of and run off
the table.  It might also cause the zero page to get faulted in
unnecessarily even if you are not at the end.

Fix it up by doing a special 32-bit get_user() via a cast when we
have 32-bit userspace.

Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
---

 b/arch/x86/mm/mpx.c |   25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff -puN arch/x86/mm/mpx.c~get_bd_entry arch/x86/mm/mpx.c
--- a/arch/x86/mm/mpx.c~get_bd_entry	2015-11-11 10:18:49.615230106 -0800
+++ b/arch/x86/mm/mpx.c	2015-11-11 10:18:49.619230288 -0800
@@ -586,6 +586,29 @@ static unsigned long mpx_bd_entry_to_bt_
 }
 
 /*
+ * We only want to do a 4-byte get_user() on 32-bit.  Otherwise,
+ * we might run off the end of the bounds table if we are on
+ * a 64-bit kernel and try to get 8 bytes.
+ */
+int get_user_bd_entry(struct mm_struct *mm, unsigned long *bd_entry_ret,
+		long __user *bd_entry_ptr)
+{
+	u32 bd_entry_32;
+	int ret;
+
+	if (is_64bit_mm(mm))
+		return get_user(*bd_entry_ret, bd_entry_ptr);
+
+	/*
+	 * Note that get_user() uses the type of the *pointer* to
+	 * establish the size of the get, not the destination.
+	 */
+	ret = get_user(bd_entry_32, (u32 __user *)bd_entry_ptr);
+	*bd_entry_ret = bd_entry_32;
+	return ret;
+}
+
+/*
  * Get the base of bounds tables pointed by specific bounds
  * directory entry.
  */
@@ -605,7 +628,7 @@ static int get_bt_addr(struct mm_struct
 		int need_write = 0;
 
 		pagefault_disable();
-		ret = get_user(bd_entry, bd_entry_ptr);
+		ret = get_user_bd_entry(mm, &bd_entry, bd_entry_ptr);
 		pagefault_enable();
 		if (!ret)
 			break;
_

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

* [PATCH 2/2] x86, mpx: fix 32-bit address space calculation
  2015-11-11 18:19 [PATCH 0/2] x86, mpx: Fixes for 32-bit userspace Dave Hansen
  2015-11-11 18:19 ` [PATCH 1/2] x86, mpx: do proper get_user() when running 32-bit binaries on 64-bit Dave Hansen
@ 2015-11-11 18:19 ` Dave Hansen
  2015-11-12 13:27   ` [tip:x86/urgent] x86/mpx: Fix " tip-bot for Dave Hansen
  1 sibling, 1 reply; 5+ messages in thread
From: Dave Hansen @ 2015-11-11 18:19 UTC (permalink / raw)
  To: linux-kernel; +Cc: x86, Dave Hansen, dave.hansen


From: Dave Hansen <dave.hansen@linux.intel.com>

I received a bug report that running 32-bit MPX binaries on
64-bit kernels was broken.  I traced it down to this little code
snippet.  We were switching our "number of bounds directory
entries" calculation correctly.  But, we didn't switch the other
side of the calculation: the virtual space size.

This meant that we were calculating an absurd size for
bd_entry_virt_space() on 32-bit because we used the 64-bit
virt_space.

This was _also_ broken for 32-bit kernels running on 64-bit
hardware since boot_cpu_data.x86_virt_bits=48 even when running
in 32-bit mode.

Correct that and properly handle all 3 possible cases:

 1. 32-bit binary on 64-bit kernel
 2. 64-bit binary on 64-bit kernel
 3. 32-bit binary on 32-bit kernel

This manifested in having bounds tables not properly unmapped.
It "leaked" memory but had no functional impact otherwise.

Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
---

 b/arch/x86/mm/mpx.c |   22 +++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff -puN arch/x86/mm/mpx.c~x86-mpx-fix-32-bit-address-space-calculation arch/x86/mm/mpx.c
--- a/arch/x86/mm/mpx.c~x86-mpx-fix-32-bit-address-space-calculation	2015-11-11 10:18:50.030248940 -0800
+++ b/arch/x86/mm/mpx.c	2015-11-11 10:18:50.033249076 -0800
@@ -723,11 +723,23 @@ static unsigned long mpx_get_bt_entry_of
  */
 static inline unsigned long bd_entry_virt_space(struct mm_struct *mm)
 {
-	unsigned long long virt_space = (1ULL << boot_cpu_data.x86_virt_bits);
-	if (is_64bit_mm(mm))
-		return virt_space / MPX_BD_NR_ENTRIES_64;
-	else
-		return virt_space / MPX_BD_NR_ENTRIES_32;
+	unsigned long long virt_space;
+	unsigned long long GB = (1ULL << 30);
+
+	/*
+	 * This covers 32-bit emulation as well as 32-bit kernels
+	 * running on 64-bit harware.
+	 */
+	if (!is_64bit_mm(mm))
+		return (4ULL * GB) / MPX_BD_NR_ENTRIES_32;
+
+	/*
+	 * 'x86_virt_bits' returns what the hardware is capable
+	 * of, and returns the full >32-bit adddress space when
+	 * running 32-bit kernels on 64-bit hardware.
+	 */
+	virt_space = (1ULL << boot_cpu_data.x86_virt_bits);
+	return virt_space / MPX_BD_NR_ENTRIES_64;
 }
 
 /*
_

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

* [tip:x86/urgent] x86/mpx: Do proper get_user() when running 32-bit binaries on 64-bit kernels
  2015-11-11 18:19 ` [PATCH 1/2] x86, mpx: do proper get_user() when running 32-bit binaries on 64-bit Dave Hansen
@ 2015-11-12 13:27   ` tip-bot for Dave Hansen
  0 siblings, 0 replies; 5+ messages in thread
From: tip-bot for Dave Hansen @ 2015-11-12 13:27 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: peterz, dave.hansen, bp, hpa, brgerst, mingo, linux-kernel,
	stable, tglx, torvalds, dvlasenk, dave, luto

Commit-ID:  46561c3959d6307d22139c24cd0bf196162e5681
Gitweb:     http://git.kernel.org/tip/46561c3959d6307d22139c24cd0bf196162e5681
Author:     Dave Hansen <dave.hansen@linux.intel.com>
AuthorDate: Wed, 11 Nov 2015 10:19:31 -0800
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Thu, 12 Nov 2015 09:20:37 +0100

x86/mpx: Do proper get_user() when running 32-bit binaries on 64-bit kernels

When you call get_user(foo, bar), you effectively do a

	copy_from_user(&foo, bar, sizeof(*bar));

Note that the sizeof() is implicit.

When we reach out to userspace to try to zap an entire "bounds
table" we need to go read a "bounds directory entry" in order to
locate the table's address.  The size of a "directory entry"
depends on the binary being run and is always the size of a
pointer.

But, when we have a 64-bit kernel and a 32-bit application, the
directory entry is still only 32-bits long, but we fetch it with
a 64-bit pointer which makes get_user() does a 64-bit fetch.
Reading 4 extra bytes isn't harmful, unless we are at the end of
and run off the table.  It might also cause the zero page to get
faulted in unnecessarily even if you are not at the end.

Fix it up by doing a special 32-bit get_user() via a cast when
we have 32-bit userspace.

Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Cc: <stable@vger.kernel.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Dave Hansen <dave@sr71.net>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20151111181931.3ACF6822@viggo.jf.intel.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/mm/mpx.c | 25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/arch/x86/mm/mpx.c b/arch/x86/mm/mpx.c
index b0ae85f..6127c5e 100644
--- a/arch/x86/mm/mpx.c
+++ b/arch/x86/mm/mpx.c
@@ -586,6 +586,29 @@ static unsigned long mpx_bd_entry_to_bt_addr(struct mm_struct *mm,
 }
 
 /*
+ * We only want to do a 4-byte get_user() on 32-bit.  Otherwise,
+ * we might run off the end of the bounds table if we are on
+ * a 64-bit kernel and try to get 8 bytes.
+ */
+int get_user_bd_entry(struct mm_struct *mm, unsigned long *bd_entry_ret,
+		long __user *bd_entry_ptr)
+{
+	u32 bd_entry_32;
+	int ret;
+
+	if (is_64bit_mm(mm))
+		return get_user(*bd_entry_ret, bd_entry_ptr);
+
+	/*
+	 * Note that get_user() uses the type of the *pointer* to
+	 * establish the size of the get, not the destination.
+	 */
+	ret = get_user(bd_entry_32, (u32 __user *)bd_entry_ptr);
+	*bd_entry_ret = bd_entry_32;
+	return ret;
+}
+
+/*
  * Get the base of bounds tables pointed by specific bounds
  * directory entry.
  */
@@ -605,7 +628,7 @@ static int get_bt_addr(struct mm_struct *mm,
 		int need_write = 0;
 
 		pagefault_disable();
-		ret = get_user(bd_entry, bd_entry_ptr);
+		ret = get_user_bd_entry(mm, &bd_entry, bd_entry_ptr);
 		pagefault_enable();
 		if (!ret)
 			break;

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

* [tip:x86/urgent] x86/mpx: Fix 32-bit address space calculation
  2015-11-11 18:19 ` [PATCH 2/2] x86, mpx: fix 32-bit address space calculation Dave Hansen
@ 2015-11-12 13:27   ` tip-bot for Dave Hansen
  0 siblings, 0 replies; 5+ messages in thread
From: tip-bot for Dave Hansen @ 2015-11-12 13:27 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: stable, luto, dave.hansen, torvalds, dave, peterz, dvlasenk,
	linux-kernel, mingo, brgerst, hpa, tglx, bp

Commit-ID:  f3119b830264d89d216bfb378ab65065dffa02d9
Gitweb:     http://git.kernel.org/tip/f3119b830264d89d216bfb378ab65065dffa02d9
Author:     Dave Hansen <dave.hansen@linux.intel.com>
AuthorDate: Wed, 11 Nov 2015 10:19:34 -0800
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Thu, 12 Nov 2015 09:20:37 +0100

x86/mpx: Fix 32-bit address space calculation

I received a bug report that running 32-bit MPX binaries on
64-bit kernels was broken.  I traced it down to this little code
snippet.  We were switching our "number of bounds directory
entries" calculation correctly.  But, we didn't switch the other
side of the calculation: the virtual space size.

This meant that we were calculating an absurd size for
bd_entry_virt_space() on 32-bit because we used the 64-bit
virt_space.

This was _also_ broken for 32-bit kernels running on 64-bit
hardware since boot_cpu_data.x86_virt_bits=48 even when running
in 32-bit mode.

Correct that and properly handle all 3 possible cases:

 1. 32-bit binary on 64-bit kernel
 2. 64-bit binary on 64-bit kernel
 3. 32-bit binary on 32-bit kernel

This manifested in having bounds tables not properly unmapped.
It "leaked" memory but had no functional impact otherwise.

Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Cc: <stable@vger.kernel.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Dave Hansen <dave@sr71.net>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20151111181934.FA7FAC34@viggo.jf.intel.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/mm/mpx.c | 22 +++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/arch/x86/mm/mpx.c b/arch/x86/mm/mpx.c
index 6127c5e..1202d5c 100644
--- a/arch/x86/mm/mpx.c
+++ b/arch/x86/mm/mpx.c
@@ -723,11 +723,23 @@ static unsigned long mpx_get_bt_entry_offset_bytes(struct mm_struct *mm,
  */
 static inline unsigned long bd_entry_virt_space(struct mm_struct *mm)
 {
-	unsigned long long virt_space = (1ULL << boot_cpu_data.x86_virt_bits);
-	if (is_64bit_mm(mm))
-		return virt_space / MPX_BD_NR_ENTRIES_64;
-	else
-		return virt_space / MPX_BD_NR_ENTRIES_32;
+	unsigned long long virt_space;
+	unsigned long long GB = (1ULL << 30);
+
+	/*
+	 * This covers 32-bit emulation as well as 32-bit kernels
+	 * running on 64-bit harware.
+	 */
+	if (!is_64bit_mm(mm))
+		return (4ULL * GB) / MPX_BD_NR_ENTRIES_32;
+
+	/*
+	 * 'x86_virt_bits' returns what the hardware is capable
+	 * of, and returns the full >32-bit adddress space when
+	 * running 32-bit kernels on 64-bit hardware.
+	 */
+	virt_space = (1ULL << boot_cpu_data.x86_virt_bits);
+	return virt_space / MPX_BD_NR_ENTRIES_64;
 }
 
 /*

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

end of thread, other threads:[~2015-11-12 13:29 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-11 18:19 [PATCH 0/2] x86, mpx: Fixes for 32-bit userspace Dave Hansen
2015-11-11 18:19 ` [PATCH 1/2] x86, mpx: do proper get_user() when running 32-bit binaries on 64-bit Dave Hansen
2015-11-12 13:27   ` [tip:x86/urgent] x86/mpx: Do proper get_user() when running 32-bit binaries on 64-bit kernels tip-bot for Dave Hansen
2015-11-11 18:19 ` [PATCH 2/2] x86, mpx: fix 32-bit address space calculation Dave Hansen
2015-11-12 13:27   ` [tip:x86/urgent] x86/mpx: Fix " tip-bot for Dave Hansen

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.