From: Felix Fu fuzhen5@huawei.com
felix (4): kaslr: add nokaslr memory region Kconfig support efi/libstub: add arm64 nokaslr memory regions x86/boot: add x86 nokaslr memory regions kaslr: enable CONFIG_NOKASLR_MEM_RANGE in openeuler_defconfig
arch/arm64/configs/openeuler_defconfig | 1 + arch/x86/boot/compressed/kaslr.c | 44 +++++++ arch/x86/configs/openeuler_defconfig | 1 + drivers/firmware/efi/libstub/arm64-stub.c | 118 ++++++++++++++++++ .../firmware/efi/libstub/efi-stub-helper.c | 7 +- drivers/firmware/efi/libstub/efistub.h | 10 ++ drivers/firmware/efi/libstub/randomalloc.c | 17 +++ init/Kconfig | 7 ++ 8 files changed, 204 insertions(+), 1 deletion(-)
Offering: HULK hulk inclusion category: feature bugzilla: 189284
--------------------------------
add Kconfig NOKASLR_MEM_RANGE support. allow users to mark at most 4 memory regions as unavailable for kaslr
Signed-off-by: felix fuzhen5@huawei.com Signed-off-by: Felix Fu fuzhen5@huawei.com --- init/Kconfig | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/init/Kconfig b/init/Kconfig index 69bd400daeb3..8db300661d03 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -2542,3 +2542,10 @@ config ARCH_HAS_SYNC_CORE_BEFORE_USERMODE # <asm/syscall_wrapper.h>. config ARCH_HAS_SYSCALL_WRAPPER def_bool n + +config NOKASLR_MEM_RANGE + bool "Allow users to mark at most 4 memory regions as unavailable for kaslr" + default n + help + Say y here and add kernel parameters as nokaslr=nn[KMG]-ss[KMG] to avoid kaslr + place kernel image in such memory regions \ No newline at end of file
Offering: HULK hulk inclusion category: feature bugzilla: 189284
--------------------------------
allow users to mark at most 4 regions as not available for kaslr
Signed-off-by: felix fuzhen5@huawei.com Signed-off-by: Felix Fu fuzhen5@huawei.com --- drivers/firmware/efi/libstub/arm64-stub.c | 118 ++++++++++++++++++ .../firmware/efi/libstub/efi-stub-helper.c | 7 +- drivers/firmware/efi/libstub/efistub.h | 10 ++ drivers/firmware/efi/libstub/randomalloc.c | 17 +++ 4 files changed, 151 insertions(+), 1 deletion(-)
diff --git a/drivers/firmware/efi/libstub/arm64-stub.c b/drivers/firmware/efi/libstub/arm64-stub.c index ae6790218339..ff2fcddbbbbb 100644 --- a/drivers/firmware/efi/libstub/arm64-stub.c +++ b/drivers/firmware/efi/libstub/arm64-stub.c @@ -104,6 +104,124 @@ void free_avoid_memmap(void) } }
+#ifdef CONFIG_NOKASLR_MEM_RANGE +#define MAX_MEM_NOKASLR_REGIONS 4 + +struct mem_region { + unsigned long long start; + unsigned long long size; +}; + +struct mem_region mem_nokaslr[MAX_MEM_NOKASLR_REGIONS]; + +void efi_parse_option_nokaslr_ranges(char *str) +{ + int i = 0; + + while (str && (i < MAX_MEM_NOKASLR_REGIONS)) { + char *oldstr; + u64 start, end; + char *k = strchr(str, ','); + + if (k) + *k++ = 0; + + oldstr = str; + start = memparse(str, &str); + if (str == oldstr || *str != '-') { + efi_warn("Nokaslr values "%s" error.\n", oldstr); + break; + } + end = memparse(str + 1, &str); + if (start >= end) { + efi_warn("Nokaslr values "%s" error, start >= end.\n", oldstr); + break; + } + + mem_nokaslr[i].start = start; + mem_nokaslr[i].size = end - start; + str = k; + i++; + } +} + +static bool mem_overlaps(struct mem_region *one, struct mem_region *two) +{ + if (one->start + one->size <= two->start) + return false; + if (one->start >= two->start + two->size) + return false; + return true; +} + +static bool mem_avoid_overlap(struct mem_region *region, struct mem_region *overlap) +{ + int i; + u64 earliest = region->start + region->size; + bool is_overlapping = false; + + for (i = 0; i < MAX_MEM_NOKASLR_REGIONS; i++) { + if (mem_overlaps(region, &mem_nokaslr[i]) && + mem_nokaslr[i].start < earliest) { + *overlap = mem_nokaslr[i]; + earliest = overlap->start; + is_overlapping = true; + } + } + return is_overlapping; +} + +unsigned long cal_slots_avoid_overlap(efi_memory_desc_t *md, unsigned long size, u8 cal_type, + unsigned long align_shift, unsigned long target) +{ + struct mem_region region, overlap; + unsigned long region_end, first, last; + unsigned long align = 1UL << align_shift; + unsigned long total_slots = 0, slots; + + region.start = md->phys_addr; + region_end = min(md->phys_addr + md->num_pages * EFI_PAGE_SIZE - 1, (u64)ULONG_MAX); + + while (region.start < region_end) { + first = round_up(region.start, align); + last = round_down(region_end - size + 1, align); + + if (first > last) + break; + + region.size = region_end - region.start + 1; + + if (!mem_avoid_overlap(®ion, &overlap)) { + slots = ((last - first) >> align_shift) + 1; + total_slots += slots; + + if (cal_type == CAL_SLOTS_PHYADDR) + return first + target * align; + + break; + } + + if (overlap.start >= region.start + size) { + slots = ((round_up(overlap.start - size + 1, align) - first) >> + align_shift) + 1; + total_slots += slots; + + if (cal_type == CAL_SLOTS_PHYADDR) { + if (target > slots) + target -= slots; + else + return first + target * align; + } + } + + /* Clip off the overlapping region and start over. */ + region.start = overlap.start + overlap.size; + } + + return total_slots; +} +#endif + efi_status_t check_platform_features(void) { u64 tg; diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c index 8670654bf561..dc3fbd0914f5 100644 --- a/drivers/firmware/efi/libstub/efi-stub-helper.c +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c @@ -212,7 +212,12 @@ efi_status_t efi_parse_options(char const *cmdline) break;
if (!strcmp(param, "nokaslr")) { - efi_nokaslr = true; +#if defined(CONFIG_NOKASLR_MEM_RANGE) && defined(CONFIG_ARM64) + if (val) + efi_parse_option_nokaslr_ranges(val); + else +#endif + efi_nokaslr = true; } else if (!strcmp(param, "quiet")) { efi_loglevel = CONSOLE_LOGLEVEL_QUIET; } else if (!strcmp(param, "noinitrd")) { diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h index b823f76bb739..ee4c57a285e7 100644 --- a/drivers/firmware/efi/libstub/efistub.h +++ b/drivers/firmware/efi/libstub/efistub.h @@ -838,6 +838,16 @@ static inline void mem_avoid_memmap(void) { } static inline void free_avoid_memmap(void) { } #endif
+#if defined(CONFIG_NOKASLR_MEM_RANGE) && defined(CONFIG_ARM64) +#define CAL_SLOTS_NUMBER 0 +#define CAL_SLOTS_PHYADDR 1 + +void efi_parse_option_nokaslr_ranges(char *str); +unsigned long cal_slots_avoid_overlap(efi_memory_desc_t *md, unsigned long size, u8 cal_type, + unsigned long align_shift, unsigned long target); +#endif + + efi_status_t efi_setup_gop(struct screen_info *si, efi_guid_t *proto, unsigned long size);
diff --git a/drivers/firmware/efi/libstub/randomalloc.c b/drivers/firmware/efi/libstub/randomalloc.c index 724155b9e10d..3be5120c651d 100644 --- a/drivers/firmware/efi/libstub/randomalloc.c +++ b/drivers/firmware/efi/libstub/randomalloc.c @@ -39,7 +39,11 @@ static unsigned long get_entry_num_slots(efi_memory_desc_t *md, if (first_slot > last_slot) return 0;
+#if defined(CONFIG_NOKASLR_MEM_RANGE) && defined(CONFIG_ARM64) + return cal_slots_avoid_overlap(md, size, CAL_SLOTS_NUMBER, align_shift, 0); +#else return ((unsigned long)(last_slot - first_slot) >> align_shift) + 1; +#endif }
/* @@ -88,6 +92,14 @@ efi_status_t efi_random_alloc(unsigned long size, total_slots += slots; }
+#if defined(CONFIG_NOKASLR_MEM_RANGE) && defined(CONFIG_ARM64) + if (total_slots == 0) { + efi_info("Physical KASLR disabled: no suitable momory region!\n"); + efi_bs_call(free_pool, memory_map); + return EFI_OUT_OF_RESOURCES; + } +#endif + /* find a random number between 0 and total_slots */ target_slot = (total_slots * (u64)(random_seed & U32_MAX)) >> 32;
@@ -112,7 +124,12 @@ efi_status_t efi_random_alloc(unsigned long size, continue; }
+#if defined(CONFIG_NOKASLR_MEM_RANGE) && defined(CONFIG_ARM64) + target = cal_slots_avoid_overlap(md, size, CAL_SLOTS_PHYADDR, ilog2(align), + target_slot); +#else target = round_up(md->phys_addr, align) + target_slot * align; +#endif pages = size / EFI_PAGE_SIZE;
status = efi_bs_call(allocate_pages, EFI_ALLOCATE_ADDRESS,
Offering: HULK hulk inclusion category: feature bugzilla: 189284
--------------------------------
allow users to mark at most 4 regions as not available for kaslr
Signed-off-by: felix fuzhen5@huawei.com Signed-off-by: Felix Fu fuzhen5@huawei.com --- arch/x86/boot/compressed/kaslr.c | 44 ++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+)
diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c index b92fffbe761f..8f280b197d40 100644 --- a/arch/x86/boot/compressed/kaslr.c +++ b/arch/x86/boot/compressed/kaslr.c @@ -79,6 +79,9 @@ static unsigned long get_boot_seed(void) /* Only supporting at most 4 unusable memmap regions with kaslr */ #define MAX_MEMMAP_REGIONS 4
+#ifdef CONFIG_NOKASLR_MEM_RANGE +#define MAX_MEM_NOKASLR_REGIONS 4 +#endif static bool memmap_too_large;
@@ -98,6 +101,10 @@ enum mem_avoid_index { MEM_AVOID_BOOTPARAMS, MEM_AVOID_MEMMAP_BEGIN, MEM_AVOID_MEMMAP_END = MEM_AVOID_MEMMAP_BEGIN + MAX_MEMMAP_REGIONS - 1, +#ifdef CONFIG_NOKASLR_MEM_RANGE + MEM_AVOID_MEM_NOKASLR_BEGIN, + MEM_AVOID_MEM_NOKASLR_END = MEM_AVOID_MEM_NOKASLR_BEGIN + MAX_MEM_NOKASLR_REGIONS - 1, +#endif MEM_AVOID_MAX, };
@@ -227,6 +234,39 @@ static void mem_avoid_memmap(enum parse_mode mode, char *str) memmap_too_large = true; }
+#ifdef CONFIG_NOKASLR_MEM_RANGE +static void mem_avoid_mem_nokaslr(char *str) +{ + int i = 0; + + while (str && (i < MAX_MEM_NOKASLR_REGIONS)) { + char *oldstr; + u64 start, end; + char *k = strchr(str, ','); + + if (k) + *k++ = 0; + + oldstr = str; + start = memparse(str, &str); + if (str == oldstr || *str != '-') { + warn("Nokaslr values error.\n"); + break; + } + + end = memparse(str + 1, &str); + if (start >= end) { + warn("Nokaslr values error, start should be less than end.\n"); + break; + } + + mem_avoid[MEM_AVOID_MEM_NOKASLR_BEGIN + i].start = start; + mem_avoid[MEM_AVOID_MEM_NOKASLR_BEGIN + i].size = end - start; + str = k; + i++; + } +} +#endif /* Store the number of 1GB huge pages which users specified: */ static unsigned long max_gb_huge_pages;
@@ -302,6 +342,10 @@ static void handle_mem_options(void) } else if (!strcmp(param, "efi_fake_mem")) { mem_avoid_memmap(PARSE_EFI, val); } +#ifdef CONFIG_NOKASLR_MEM_RANGE + else if (!strcmp(param, "nokaslr") && val) + mem_avoid_mem_nokaslr(val); +#endif }
free(tmp_cmdline);
Offering: HULK hulk inclusion category: feature bugzilla: 189284
--------------------------------
enable CONFIG_NOKASLR_MEM_RANGE in openeuler_defconfig of x86 and arm64
Signed-off-by: felix fuzhen5@huawei.com Signed-off-by: Felix Fu fuzhen5@huawei.com --- arch/arm64/configs/openeuler_defconfig | 1 + arch/x86/configs/openeuler_defconfig | 1 + 2 files changed, 2 insertions(+)
diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig index 158a9f3bb8fd..ab491462958f 100644 --- a/arch/arm64/configs/openeuler_defconfig +++ b/arch/arm64/configs/openeuler_defconfig @@ -543,6 +543,7 @@ CONFIG_ARM64_PSEUDO_NMI=y CONFIG_RELOCATABLE=y CONFIG_RANDOMIZE_BASE=y CONFIG_RANDOMIZE_MODULE_REGION_FULL=y +CONFIG_NOKASLR_MEM_RANGE=y CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y CONFIG_STACKPROTECTOR_PER_TASK=y CONFIG_ASCEND_FEATURES=y diff --git a/arch/x86/configs/openeuler_defconfig b/arch/x86/configs/openeuler_defconfig index 4f912e543270..f3633bdb2e1a 100644 --- a/arch/x86/configs/openeuler_defconfig +++ b/arch/x86/configs/openeuler_defconfig @@ -482,6 +482,7 @@ CONFIG_PHYSICAL_ALIGN=0x200000 CONFIG_DYNAMIC_MEMORY_LAYOUT=y CONFIG_RANDOMIZE_MEMORY=y CONFIG_RANDOMIZE_MEMORY_PHYSICAL_PADDING=0xa +CONFIG_NOKASLR_MEM_RANGE=y CONFIG_HOTPLUG_CPU=y # CONFIG_BOOTPARAM_HOTPLUG_CPU0 is not set # CONFIG_DEBUG_HOTPLUG_CPU0 is not set
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/3735 邮件列表地址:https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/E...
FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://gitee.com/openeuler/kernel/pulls/3735 Mailing list address: https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/E...