lkml.org 
[lkml]   [2019]   [Jan]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v16 7/7] x86/boot/KASLR: Limit KASLR to extracting kernel in immovable memory
    Date
    KASLR may randomly choose some positions which are located in movable
    memory regions. It will break memory hotplug feature and make the
    movable memory chosen by KASLR can't be removed.

    The solution is to limit KASLR to choose memory regions in immovable
    node according to SRAT tables.
    When CONFIG_EARLY_SRAT_PARSE is enabled, walk through SRAT to get the
    information of immovable memory so that KASLR knows where should be
    chosen for randomization.

    Signed-off-by: Chao Fan <fanc.fnst@cn.fujitsu.com>
    ---
    arch/x86/boot/compressed/kaslr.c | 72 +++++++++++++++++++++++++++-----
    arch/x86/boot/compressed/misc.h | 1 +
    2 files changed, 62 insertions(+), 11 deletions(-)

    diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
    index b251572e77af..c6721c6d4b46 100644
    --- a/arch/x86/boot/compressed/kaslr.c
    +++ b/arch/x86/boot/compressed/kaslr.c
    @@ -97,6 +97,8 @@ static bool memmap_too_large;
    /* Store memory limit specified by "mem=nn[KMG]" or "memmap=nn[KMG]" */
    static unsigned long long mem_limit = ULLONG_MAX;

    +/* Amount of immovable memory regions */
    +static int num_immovable_mem;

    enum mem_avoid_index {
    MEM_AVOID_ZO_RANGE = 0,
    @@ -413,6 +415,9 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size,
    /* Mark the memmap regions we need to avoid */
    handle_mem_options();

    + /* Mark the immovable regions we need to choose */
    + num_immovable_mem = count_immovable_mem_regions();
    +
    #ifdef CONFIG_X86_VERBOSE_BOOTUP
    /* Make sure video RAM can be used. */
    add_identity_map(0, PMD_SIZE);
    @@ -568,9 +573,9 @@ static unsigned long slots_fetch_random(void)
    return 0;
    }

    -static void process_mem_region(struct mem_vector *entry,
    - unsigned long minimum,
    - unsigned long image_size)
    +static void __process_mem_region(struct mem_vector *entry,
    + unsigned long minimum,
    + unsigned long image_size)
    {
    struct mem_vector region, overlap;
    unsigned long start_orig, end;
    @@ -646,6 +651,57 @@ static void process_mem_region(struct mem_vector *entry,
    }
    }

    +static bool process_mem_region(struct mem_vector *region,
    + unsigned long long minimum,
    + unsigned long long image_size)
    +{
    + int i;
    + /*
    + * If no immovable memory found, or MEMORY_HOTREMOVE disabled,
    + * walk all the regions, so use region directly.
    + */
    + if (!num_immovable_mem) {
    + __process_mem_region(region, minimum, image_size);
    +
    + if (slot_area_index == MAX_SLOT_AREA) {
    + debug_putstr("Aborted e820/efi memmap scan (slot_areas full)!\n");
    + return 1;
    + }
    + return 0;
    + }
    +
    +#ifdef CONFIG_MEMORY_HOTREMOVE
    + /*
    + * If immovable memory found, filter the intersection between
    + * immovable memory and region to __process_mem_region().
    + * Otherwise, go on old code.
    + */
    + for (i = 0; i < num_immovable_mem; i++) {
    + unsigned long long start, end, entry_end, region_end;
    + struct mem_vector entry;
    +
    + if (!mem_overlaps(region, &immovable_mem[i]))
    + continue;
    +
    + start = immovable_mem[i].start;
    + end = start + immovable_mem[i].size;
    + region_end = region->start + region->size;
    +
    + entry.start = clamp(region->start, start, end);
    + entry_end = clamp(region_end, start, end);
    + entry.size = entry_end - entry.start;
    +
    + __process_mem_region(&entry, minimum, image_size);
    +
    + if (slot_area_index == MAX_SLOT_AREA) {
    + debug_putstr("Aborted e820/efi memmap scan when walking immovable regions(slot_areas full)!\n");
    + return 1;
    + }
    + }
    + return 0;
    +#endif
    +}
    +
    #ifdef CONFIG_EFI
    /*
    * Returns true if mirror region found (and must have been processed
    @@ -711,11 +767,8 @@ process_efi_entries(unsigned long minimum, unsigned long image_size)

    region.start = md->phys_addr;
    region.size = md->num_pages << EFI_PAGE_SHIFT;
    - process_mem_region(&region, minimum, image_size);
    - if (slot_area_index == MAX_SLOT_AREA) {
    - debug_putstr("Aborted EFI scan (slot_areas full)!\n");
    + if (process_mem_region(&region, minimum, image_size))
    break;
    - }
    }
    return true;
    }
    @@ -742,11 +795,8 @@ static void process_e820_entries(unsigned long minimum,
    continue;
    region.start = entry->addr;
    region.size = entry->size;
    - process_mem_region(&region, minimum, image_size);
    - if (slot_area_index == MAX_SLOT_AREA) {
    - debug_putstr("Aborted e820 scan (slot_areas full)!\n");
    + if (process_mem_region(&region, minimum, image_size))
    break;
    - }
    }
    }

    diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h
    index 6fc51cebec7e..dd941d622760 100644
    --- a/arch/x86/boot/compressed/misc.h
    +++ b/arch/x86/boot/compressed/misc.h
    @@ -133,6 +133,7 @@ static inline acpi_physical_address get_rsdp_addr(void) { return 0; }
    #endif

    #if defined(CONFIG_RANDOMIZE_BASE) && defined(CONFIG_MEMORY_HOTREMOVE)
    +extern struct mem_vector immovable_mem[MAX_NUMNODES*2];
    int count_immovable_mem_regions(void);
    #else
    static inline int count_immovable_mem_regions(void) { return 0; }
    --
    2.20.1


    \
     
     \ /
      Last update: 2019-01-23 12:11    [W:3.474 / U:0.040 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site