| From b2eed9b58811283d00fa861944cb75797d4e52a7 Mon Sep 17 00:00:00 2001 |
| From: Ard Biesheuvel <ard.biesheuvel@arm.com> |
| Date: Thu, 23 May 2019 10:17:37 +0100 |
| Subject: arm64/kernel: kaslr: reduce module randomization range to 2 GB |
| |
| From: Ard Biesheuvel <ard.biesheuvel@arm.com> |
| |
| commit b2eed9b58811283d00fa861944cb75797d4e52a7 upstream. |
| |
| The following commit |
| |
| 7290d5809571 ("module: use relative references for __ksymtab entries") |
| |
| updated the ksymtab handling of some KASLR capable architectures |
| so that ksymtab entries are emitted as pairs of 32-bit relative |
| references. This reduces the size of the entries, but more |
| importantly, it gets rid of statically assigned absolute |
| addresses, which require fixing up at boot time if the kernel |
| is self relocating (which takes a 24 byte RELA entry for each |
| member of the ksymtab struct). |
| |
| Since ksymtab entries are always part of the same module as the |
| symbol they export, it was assumed at the time that a 32-bit |
| relative reference is always sufficient to capture the offset |
| between a ksymtab entry and its target symbol. |
| |
| Unfortunately, this is not always true: in the case of per-CPU |
| variables, a per-CPU variable's base address (which usually differs |
| from the actual address of any of its per-CPU copies) is allocated |
| in the vicinity of the ..data.percpu section in the core kernel |
| (i.e., in the per-CPU reserved region which follows the section |
| containing the core kernel's statically allocated per-CPU variables). |
| |
| Since we randomize the module space over a 4 GB window covering |
| the core kernel (based on the -/+ 4 GB range of an ADRP/ADD pair), |
| we may end up putting the core kernel out of the -/+ 2 GB range of |
| 32-bit relative references of module ksymtab entries that refer to |
| per-CPU variables. |
| |
| So reduce the module randomization range a bit further. We lose |
| 1 bit of randomization this way, but this is something we can |
| tolerate. |
| |
| Cc: <stable@vger.kernel.org> # v4.19+ |
| Signed-off-by: Ard Biesheuvel <ard.biesheuvel@arm.com> |
| Signed-off-by: Will Deacon <will.deacon@arm.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| arch/arm64/kernel/kaslr.c | 6 +++--- |
| arch/arm64/kernel/module.c | 2 +- |
| 2 files changed, 4 insertions(+), 4 deletions(-) |
| |
| --- a/arch/arm64/kernel/kaslr.c |
| +++ b/arch/arm64/kernel/kaslr.c |
| @@ -145,15 +145,15 @@ u64 __init kaslr_early_init(u64 dt_phys) |
| |
| if (IS_ENABLED(CONFIG_RANDOMIZE_MODULE_REGION_FULL)) { |
| /* |
| - * Randomize the module region over a 4 GB window covering the |
| + * Randomize the module region over a 2 GB window covering the |
| * kernel. This reduces the risk of modules leaking information |
| * about the address of the kernel itself, but results in |
| * branches between modules and the core kernel that are |
| * resolved via PLTs. (Branches between modules will be |
| * resolved normally.) |
| */ |
| - module_range = SZ_4G - (u64)(_end - _stext); |
| - module_alloc_base = max((u64)_end + offset - SZ_4G, |
| + module_range = SZ_2G - (u64)(_end - _stext); |
| + module_alloc_base = max((u64)_end + offset - SZ_2G, |
| (u64)MODULES_VADDR); |
| } else { |
| /* |
| --- a/arch/arm64/kernel/module.c |
| +++ b/arch/arm64/kernel/module.c |
| @@ -56,7 +56,7 @@ void *module_alloc(unsigned long size) |
| * can simply omit this fallback in that case. |
| */ |
| p = __vmalloc_node_range(size, MODULE_ALIGN, module_alloc_base, |
| - module_alloc_base + SZ_4G, GFP_KERNEL, |
| + module_alloc_base + SZ_2G, GFP_KERNEL, |
| PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE, |
| __builtin_return_address(0)); |
| |