Messages in this thread Patch in this message | | | Subject | [PATCH 2/2] x86, mpx: fix 32-bit address space calculation | From | Dave Hansen <> | Date | Wed, 11 Nov 2015 10:19:34 -0800 |
| |
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; } /* _
| |