[PATCH 6/6] arm64: module: rework module VA range selection

Shanker Donthineni sdonthineni at nvidia.com
Wed May 10 05:12:42 PDT 2023


Hi Mark,

On 5/9/23 06:14, Mark Rutland wrote:
>          if (IS_ENABLED(CONFIG_RANDOMIZE_MODULE_REGION_FULL)) {
> -               /*
> -                * 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_2G - (u64)(_end - _stext);
> -               module_alloc_base = max((u64)_end - SZ_2G, (u64)MODULES_VADDR);
> +               pr_info("2G module region forced by RANDOMIZE_MODULE_REGION_FULL\n");
> +       } else if (kernel_size >= SZ_128M) {
> +               pr_info("2G module region forced by kernel size (%llu bytes)\n",
> +                       kernel_size);
> +       } else if (IS_ENABLED(CONFIG_RANOMIZE_BASE)) {
> +               module_direct_base = choose_random_bounding_box(SZ_128M,
> +                                                               kernel_start,
> +                                                               kernel_end);
>          } else {
> -               /*
> -                * Randomize the module region by setting module_alloc_base to
> -                * a PAGE_SIZE multiple in the range [_etext - MODULES_VSIZE,
> -                * _stext) . This guarantees that the resulting region still
> -                * covers [_stext, _etext], and that all relative branches can
> -                * be resolved without veneers unless this region is exhausted
> -                * and we fall back to a larger 2GB window in module_alloc()
> -                * when ARM64_MODULE_PLTS is enabled.
> -                */
> -               module_range = MODULES_VSIZE - (u64)(_etext - _stext);
> +               module_direct_base = kernel_end - SZ_128M;
>          }
> 
> -       /* use the lower 21 bits to randomize the base of the module region */
> -       module_alloc_base += (module_range * (seed & ((1 << 21) - 1))) >> 21;
> -       module_alloc_base &= PAGE_MASK;
> +       if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
> +               u64 min, max;
> +
> +               if (module_direct_base) {
> +                       min = module_direct_base;
> +                       max = module_direct_base + SZ_128M;
> +               } else {
> +                       min = kernel_start;
> +                       max = kernel_end;
> +               }
> +
> +               module_plt_base = choose_random_bounding_box(SZ_2G, min, max);
> +       } else {
> +               module_plt_base = kernel_end - SZ_2G;
> +       }

Sharing the 2GB space with other VMALLOC callers caused it to run out, which was
the original problem. Is it feasible to avoid randomizing 'module_plt_base' and
'module_direct_base' when KASLR is disabled via the kernel boot parameter or when
a random seed is not available? This approach would guarantee the full availability
of the entire 2GB space for modules/kernel.

--- a/arch/arm64/kernel/module.c
+++ b/arch/arm64/kernel/module.c
@@ -88,7 +88,7 @@ static int __init module_init_limits(void)
         } else if (kernel_size >= SZ_128M) {
                 pr_info("2G module region forced by kernel size (%llu bytes)\n",
                         kernel_size);
-       } else if (IS_ENABLED(CONFIG_RANOMIZE_BASE)) {
+       } else if (IS_ENABLED(CONFIG_RANOMIZE_BASE) && kaslr_enabled()) {
                 module_direct_base = choose_random_bounding_box(SZ_128M,
                                                                 kernel_start,
                                                                 kernel_end);
@@ -96,7 +96,7 @@ static int __init module_init_limits(void)
                 module_direct_base = kernel_end - SZ_128M;
         }

-       if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
+       if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && kaslr_enabled()) {
                 u64 min, max;

                 if (module_direct_base) {
@@ -112,6 +112,7 @@ static int __init module_init_limits(void)
                 module_plt_base = kernel_end - SZ_2G;
         }

-Shanker



More information about the linux-arm-kernel mailing list