From: Felix Fu fuzhen5@huawei.com
hulk inclusion category: feature bugzilla: https://gitee.com/src-openeuler/kernel/issues/IAI881 CVE: NA
-----------------------------------------
This reverts commit 60c8a2d415995e359fd2b9f2da6acb0bc392127a.
Signed-off-by: Felix Fu fuzhen5@huawei.com --- arch/arm/boot/compressed/Makefile | 9 +- arch/arm/boot/compressed/head.S | 88 ------ arch/arm/boot/compressed/kaslr.c | 433 ----------------------------- arch/arm/include/asm/vmlinux.lds.h | 3 +- arch/arm/kernel/vmlinux.lds.S | 15 +- 5 files changed, 3 insertions(+), 545 deletions(-) delete mode 100644 arch/arm/boot/compressed/kaslr.c
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 203efc1d0c81..abba7458d1c3 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -85,17 +85,10 @@ compress-$(CONFIG_KERNEL_LZ4) = lz4_with_size
libfdt_objs := fdt_rw.o fdt_ro.o fdt_wip.o fdt.o
-ifneq ($(CONFIG_ARM_ATAG_DTB_COMPAT)$(CONFIG_RANDOMIZE_BASE),) -OBJS += $(libfdt_objs) ifeq ($(CONFIG_ARM_ATAG_DTB_COMPAT),y) CFLAGS_REMOVE_atags_to_fdt.o += -Wframe-larger-than=${CONFIG_FRAME_WARN} CFLAGS_atags_to_fdt.o += -Wframe-larger-than=1280 -OBJS += atags_to_fdt.o -endif -ifeq ($(CONFIG_RANDOMIZE_BASE),y) -OBJS += kaslr.o -CFLAGS_kaslr.o := -I $(srctree)/scripts/dtc/libfdt -endif +OBJS += $(libfdt_objs) atags_to_fdt.o endif ifeq ($(CONFIG_USE_OF),y) OBJS += $(libfdt_objs) fdt_check_mem_start.o diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index 79d88fb10714..2021baee35ad 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -174,25 +174,6 @@ #endif .endm
- .macro record_seed -#ifdef CONFIG_RANDOMIZE_BASE - sub ip, r1, ip, ror #1 @ poor man's kaslr seed, will - sub ip, r2, ip, ror #2 @ be superseded by kaslr-seed - sub ip, r3, ip, ror #3 @ from /chosen if present - sub ip, r4, ip, ror #5 - sub ip, r5, ip, ror #8 - sub ip, r6, ip, ror #13 - sub ip, r7, ip, ror #21 - sub ip, r8, ip, ror #3 - sub ip, r9, ip, ror #24 - sub ip, r10, ip, ror #27 - sub ip, r11, ip, ror #19 - sub ip, r13, ip, ror #14 - sub ip, r14, ip, ror #2 - str_l ip, __kaslr_seed, r9 -#endif - .endm - .section ".start", "ax" /* * sort out different calling conventions @@ -241,7 +222,6 @@ start: __EFI_HEADER 1: ARM_BE8( setend be ) @ go BE8 if compiled for BE8 - record_seed AR_CLASS( mrs r9, cpsr ) #ifdef CONFIG_ARM_VIRT_EXT bl __hyp_stub_install @ get into SVC mode, reversibly @@ -466,38 +446,6 @@ restart: adr r0, LC1 dtb_check_done: #endif
-#ifdef CONFIG_RANDOMIZE_BASE - ldr r1, __kaslr_offset @ check if the kaslr_offset is - cmp r1, #0 @ already set - bne 1f - - stmfd sp!, {r0-r3, ip, lr} - adr_l r2, _text @ start of zImage - stmfd sp!, {r2, r8, r10} @ pass stack arguments - - ldr_l r3, __kaslr_seed -#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) || defined(CONFIG_CPU_V7) - /* - * Get some pseudo-entropy from the low bits of the generic - * timer if it is implemented. - */ - mrc p15, 0, r1, c0, c1, 1 @ read ID_PFR1 register - tst r1, #0x10000 @ have generic timer? - mrrcne p15, 1, r3, r1, c14 @ read CNTVCT -#endif - adr_l r0, __kaslr_offset @ pass &__kaslr_offset in r0 - mov r1, r4 @ pass base address - mov r2, r9 @ pass decompressed image size - eor r3, r3, r3, ror #16 @ pass pseudorandom seed - bl kaslr_early_init - add sp, sp, #12 - cmp r0, #0 - addne r4, r4, r0 @ add offset to base address - ldmfd sp!, {r0-r3, ip, lr} - bne restart -1: -#endif - /* * Check to see if we will overwrite ourselves. * r4 = final kernel address (possibly with LSB set) @@ -1491,46 +1439,10 @@ __enter_kernel: mov r0, #0 @ must be 0 mov r1, r7 @ restore architecture number mov r2, r8 @ restore atags pointer -#ifdef CONFIG_RANDOMIZE_BASE - ldr r3, __kaslr_offset - add r4, r4, #4 @ skip first instruction -#endif ARM( mov pc, r4 ) @ call kernel M_CLASS( add r4, r4, #1 ) @ enter in Thumb mode for M class THUMB( bx r4 ) @ entry point is always ARM for A/R classes
-#ifdef CONFIG_RANDOMIZE_BASE - /* - * Minimal implementation of CRC-16 that does not use a - * lookup table and uses 32-bit wide loads, so it still - * performs reasonably well with the D-cache off. Equivalent - * to lib/crc16.c for input sizes that are 4 byte multiples. - */ -ENTRY(__crc16) - push {r4, lr} - ldr r3, =0xa001 @ CRC-16 polynomial -0: subs r2, r2, #4 - popmi {r4, pc} - ldr r4, [r1], #4 -#ifdef __ARMEB__ - eor ip, r4, r4, ror #16 @ endian swap - bic ip, ip, #0x00ff0000 - mov r4, r4, ror #8 - eor r4, r4, ip, lsr #8 -#endif - eor r0, r0, r4 - .rept 32 - lsrs r0, r0, #1 - eorcs r0, r0, r3 - .endr - b 0b -ENDPROC(__crc16) - - .align 2 -__kaslr_seed: .long 0 -__kaslr_offset: .long 0 -#endif - reloc_code_end:
#ifdef CONFIG_EFI_STUB diff --git a/arch/arm/boot/compressed/kaslr.c b/arch/arm/boot/compressed/kaslr.c deleted file mode 100644 index 169c6774f5ad..000000000000 --- a/arch/arm/boot/compressed/kaslr.c +++ /dev/null @@ -1,433 +0,0 @@ -/* - * Copyright (C) 2017 Linaro Ltd; ard.biesheuvel@linaro.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include <linux/libfdt_env.h> -#include <libfdt.h> -#include <linux/types.h> -#include <generated/compile.h> -#include <generated/utsrelease.h> -#include <generated/utsversion.h> -#include <linux/pgtable.h> - -#include CONFIG_UNCOMPRESS_INCLUDE - -struct regions { - u32 pa_start; - u32 pa_end; - u32 image_size; - u32 zimage_start; - u32 zimage_size; - u32 dtb_start; - u32 dtb_size; - u32 initrd_start; - u32 initrd_size; - int reserved_mem; - int reserved_mem_addr_cells; - int reserved_mem_size_cells; -}; - -extern u32 __crc16(u32 crc, u32 const input[], int byte_count); - -static u32 __memparse(const char *val, const char **retptr) -{ - int base = 10; - u32 ret = 0; - - if (*val == '0') { - val++; - if (*val == 'x' || *val == 'X') { - val++; - base = 16; - } else { - base = 8; - } - } - - while (*val != ',' && *val != ' ' && *val != '\0') { - char c = *val++; - - switch (c) { - case '0' ... '9': - ret = ret * base + (c - '0'); - continue; - case 'a' ... 'f': - ret = ret * base + (c - 'a' + 10); - continue; - case 'A' ... 'F': - ret = ret * base + (c - 'A' + 10); - continue; - case 'g': - case 'G': - ret <<= 10; - fallthrough; - case 'm': - case 'M': - ret <<= 10; - fallthrough; - case 'k': - case 'K': - ret <<= 10; - break; - default: - if (retptr) - *retptr = NULL; - return 0; - } - } - if (retptr) - *retptr = val; - return ret; -} - -static bool regions_intersect(u32 s1, u32 e1, u32 s2, u32 e2) -{ - return e1 >= s2 && e2 >= s1; -} - -static bool intersects_reserved_region(const void *fdt, u32 start, - u32 end, struct regions *regions) -{ - int subnode, len, i; - u64 base, size; - - /* check for overlap with /memreserve/ entries */ - for (i = 0; i < fdt_num_mem_rsv(fdt); i++) { - if (fdt_get_mem_rsv(fdt, i, &base, &size) < 0) - continue; - if (regions_intersect(start, end, base, base + size)) - return true; - } - - if (regions->reserved_mem < 0) - return false; - - /* check for overlap with static reservations in /reserved-memory */ - for (subnode = fdt_first_subnode(fdt, regions->reserved_mem); - subnode >= 0; - subnode = fdt_next_subnode(fdt, subnode)) { - const fdt32_t *reg; - - len = 0; - reg = fdt_getprop(fdt, subnode, "reg", &len); - while (len >= (regions->reserved_mem_addr_cells + - regions->reserved_mem_size_cells)) { - - base = fdt32_to_cpu(reg[0]); - if (regions->reserved_mem_addr_cells == 2) - base = (base << 32) | fdt32_to_cpu(reg[1]); - - reg += regions->reserved_mem_addr_cells; - len -= 4 * regions->reserved_mem_addr_cells; - - size = fdt32_to_cpu(reg[0]); - if (regions->reserved_mem_size_cells == 2) - size = (size << 32) | fdt32_to_cpu(reg[1]); - - reg += regions->reserved_mem_size_cells; - len -= 4 * regions->reserved_mem_size_cells; - - if (base >= regions->pa_end) - continue; - - if (regions_intersect(start, end, base, - min(base + size, (u64)U32_MAX))) - return true; - } - } - return false; -} - -static bool intersects_occupied_region(const void *fdt, u32 start, - u32 end, struct regions *regions) -{ - if (regions_intersect(start, end, regions->zimage_start, - regions->zimage_start + regions->zimage_size)) - return true; - - if (regions_intersect(start, end, regions->initrd_start, - regions->initrd_start + regions->initrd_size)) - return true; - - if (regions_intersect(start, end, regions->dtb_start, - regions->dtb_start + regions->dtb_size)) - return true; - - return intersects_reserved_region(fdt, start, end, regions); -} - -static u32 count_suitable_regions(const void *fdt, struct regions *regions, - u32 *bitmap) -{ - u32 pa, i = 0, ret = 0; - - for (pa = regions->pa_start; pa < regions->pa_end; pa += SZ_2M, i++) { - if (!intersects_occupied_region(fdt, pa, - pa + regions->image_size, - regions)) { - ret++; - } else { - /* set 'occupied' bit */ - bitmap[i >> 5] |= BIT(i & 0x1f); - } - } - return ret; -} - -/* The caller ensures that num is within the range of regions.*/ -static u32 get_region_number(u32 num, u32 *bitmap, u32 size) -{ - u32 i, cnt = size * BITS_PER_BYTE * sizeof(u32); - - for (i = 0; i < cnt; i++) { - if (bitmap[i >> 5] & BIT(i & 0x1f)) - continue; - if (num-- == 0) - break; - } - - return i; -} - -static void get_cell_sizes(const void *fdt, int node, int *addr_cells, - int *size_cells) -{ - const int *prop; - int len; - - /* - * Retrieve the #address-cells and #size-cells properties - * from the 'node', or use the default if not provided. - */ - *addr_cells = *size_cells = 1; - - prop = fdt_getprop(fdt, node, "#address-cells", &len); - if (len == 4) - *addr_cells = fdt32_to_cpu(*prop); - prop = fdt_getprop(fdt, node, "#size-cells", &len); - if (len == 4) - *size_cells = fdt32_to_cpu(*prop); -} - -/* - * Original method only consider the first memory node in dtb, - * but there may be more than one memory nodes, we only consider - * the memory node zImage exists. - */ -static u32 get_memory_end(const void *fdt, u32 zimage_start) -{ - int mem_node, address_cells, size_cells, len; - const fdt32_t *reg; - - /* Look for a node called "memory" at the lowest level of the tree */ - mem_node = fdt_path_offset(fdt, "/memory"); - if (mem_node <= 0) - return 0; - - get_cell_sizes(fdt, 0, &address_cells, &size_cells); - - while (mem_node >= 0) { - /* - * Now find the 'reg' property of the /memory node, and iterate over - * the base/size pairs. - */ - len = 0; - reg = fdt_getprop(fdt, mem_node, "reg", &len); - while (len >= 4 * (address_cells + size_cells)) { - u64 base, size; - base = fdt32_to_cpu(reg[0]); - if (address_cells == 2) - base = (base << 32) | fdt32_to_cpu(reg[1]); - - reg += address_cells; - len -= 4 * address_cells; - - size = fdt32_to_cpu(reg[0]); - if (size_cells == 2) - size = (size << 32) | fdt32_to_cpu(reg[1]); - - reg += size_cells; - len -= 4 * size_cells; - - /* Get the base and size of the zimage memory node */ - if (zimage_start >= base && zimage_start < base + size) - return base + size; - } - /* If current memory node is not the one zImage exists, then traverse next memory node. */ - mem_node = fdt_node_offset_by_prop_value(fdt, mem_node, "device_type", "memory", sizeof("memory")); - } - - return 0; -} - -static char *__strstr(const char *s1, const char *s2, int l2) -{ - int l1; - - l1 = strlen(s1); - while (l1 >= l2) { - l1--; - if (!memcmp(s1, s2, l2)) - return (char *)s1; - s1++; - } - return NULL; -} - -static const char *get_cmdline_param(const char *cmdline, const char *param, - int param_size) -{ - static const char default_cmdline[] = CONFIG_CMDLINE; - const char *p; - - if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline != NULL) { - p = __strstr(cmdline, param, param_size); - if (p == cmdline || - (p > cmdline && *(p - 1) == ' ')) - return p; - } - - if (IS_ENABLED(CONFIG_CMDLINE_FORCE) || - IS_ENABLED(CONFIG_CMDLINE_EXTEND)) { - p = __strstr(default_cmdline, param, param_size); - if (p == default_cmdline || - (p > default_cmdline && *(p - 1) == ' ')) - return p; - } - return NULL; -} - -u32 kaslr_early_init(u32 *kaslr_offset, u32 image_base, u32 image_size, - u32 seed, u32 zimage_start, const void *fdt, - u32 zimage_end) -{ - static const char __aligned(4) build_id[] = UTS_VERSION UTS_RELEASE; - u32 bitmap[(VMALLOC_END - PAGE_OFFSET) / SZ_2M / 32] = {}; - struct regions regions; - const char *command_line; - const char *p; - int chosen, len; - u32 lowmem_top, count, num, mem_fdt; - - if (IS_ENABLED(CONFIG_EFI_STUB)) { - extern u32 __efi_kaslr_offset; - - if (__efi_kaslr_offset == U32_MAX) - return 0; - } - - if (fdt_check_header(fdt)) - return 0; - - chosen = fdt_path_offset(fdt, "/chosen"); - if (chosen < 0) - return 0; - - command_line = fdt_getprop(fdt, chosen, "bootargs", &len); - - /* check the command line for the presence of 'nokaslr' */ - p = get_cmdline_param(command_line, "nokaslr", sizeof("nokaslr") - 1); - if (p != NULL) - return 0; - - /* check the command line for the presence of 'vmalloc=' */ - p = get_cmdline_param(command_line, "vmalloc=", sizeof("vmalloc=") - 1); - if (p != NULL) - lowmem_top = VMALLOC_END - __memparse(p + 8, NULL) - - VMALLOC_OFFSET; - else - lowmem_top = VMALLOC_DEFAULT_BASE; - - regions.image_size = image_base % SZ_128M + round_up(image_size, SZ_2M); - regions.pa_start = round_down(image_base, SZ_128M); - regions.pa_end = lowmem_top - PAGE_OFFSET + regions.pa_start; - regions.zimage_start = zimage_start; - regions.zimage_size = zimage_end - zimage_start; - regions.dtb_start = (u32)fdt; - regions.dtb_size = fdt_totalsize(fdt); - - /* - * Stir up the seed a bit by taking the CRC of the DTB: - * hopefully there's a /chosen/kaslr-seed in there. - */ - seed = __crc16(seed, fdt, regions.dtb_size); - - /* stir a bit more using data that changes between builds */ - seed = __crc16(seed, (u32 *)build_id, sizeof(build_id)); - - /* check for initrd on the command line */ - regions.initrd_start = regions.initrd_size = 0; - p = get_cmdline_param(command_line, "initrd=", sizeof("initrd=") - 1); - if (p != NULL) { - regions.initrd_start = __memparse(p + 7, &p); - if (*p++ == ',') - regions.initrd_size = __memparse(p, NULL); - if (regions.initrd_size == 0) - regions.initrd_start = 0; - } - - /* ... or in /chosen */ - if (regions.initrd_size == 0) { - const fdt32_t *prop; - u64 start = 0, end = 0; - - prop = fdt_getprop(fdt, chosen, "linux,initrd-start", &len); - if (prop) { - start = fdt32_to_cpu(prop[0]); - if (len == 8) - start = (start << 32) | fdt32_to_cpu(prop[1]); - } - - prop = fdt_getprop(fdt, chosen, "linux,initrd-end", &len); - if (prop) { - end = fdt32_to_cpu(prop[0]); - if (len == 8) - end = (end << 32) | fdt32_to_cpu(prop[1]); - } - if (start != 0 && end != 0 && start < U32_MAX) { - regions.initrd_start = start; - regions.initrd_size = min_t(u64, end, U32_MAX) - start; - } - } - - /* - * check the memory nodes for the size of the lowmem region, traverse - * all memory nodes to find the node in which zImage exists, we - * randomize kernel only in the one zImage exists. - */ - mem_fdt = get_memory_end(fdt, zimage_start); - if (mem_fdt) - regions.pa_end = min(regions.pa_end, mem_fdt) - regions.image_size; - else - regions.pa_end = regions.pa_end - regions.image_size; - - /* check for a reserved-memory node and record its cell sizes */ - regions.reserved_mem = fdt_path_offset(fdt, "/reserved-memory"); - if (regions.reserved_mem >= 0) - get_cell_sizes(fdt, regions.reserved_mem, - ®ions.reserved_mem_addr_cells, - ®ions.reserved_mem_size_cells); - - /* - * Iterate over the physical memory range covered by the lowmem region - * in 2 MB increments, and count each offset at which we don't overlap - * with any of the reserved regions for the zImage itself, the DTB, - * the initrd and any regions described as reserved in the device tree. - * If the region does overlap, set the respective bit in the bitmap[]. - * Using this random value, we go over the bitmap and count zero bits - * until we counted enough iterations, and return the offset we ended - * up at. - */ - count = count_suitable_regions(fdt, ®ions, bitmap); - - num = ((u16)seed * count) >> 16; - - *kaslr_offset = get_region_number(num, bitmap, sizeof(bitmap) / sizeof(u32)) * SZ_2M; - - return *kaslr_offset; -} diff --git a/arch/arm/include/asm/vmlinux.lds.h b/arch/arm/include/asm/vmlinux.lds.h index dcc319b10a09..e291fef3213f 100644 --- a/arch/arm/include/asm/vmlinux.lds.h +++ b/arch/arm/include/asm/vmlinux.lds.h @@ -75,7 +75,7 @@ */ #define ARM_ASSERTS \ .plt : { \ - *(.iplt) * (.rel.iplt) * (.iplt) * (.igot.plt) * (.plt) \ + *(.iplt) *(.rel.iplt) *(.iplt) *(.igot.plt) \ } \ ASSERT(SIZEOF(.plt) == 0, \ "Unexpected run-time procedure linkages detected!") @@ -105,7 +105,6 @@ ARM_STUBS_TEXT \ . = ALIGN(4); \ *(.got) /* Global offset table */ \ - *(.got.plt) \ ARM_CPU_KEEP(PROC_INFO)
/* Stack unwinding tables */ diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index b659b4b69e01..d6ccf647eef7 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -69,10 +69,6 @@ SECTIONS #endif _etext = .; /* End of text section */
- .gnu.hash : { - *(.gnu.hash) - } - RO_DATA(PAGE_SIZE)
. = ALIGN(4); @@ -120,7 +116,7 @@ SECTIONS #endif .rel.dyn : ALIGN(8) { __rel_begin = .; - *(.rel .rel.* .rel.dyn .rel*) + *(.rel .rel.* .rel.dyn) } __rel_end = ADDR(.rel.dyn) + SIZEOF(.rel.dyn);
@@ -153,15 +149,6 @@ SECTIONS
_sdata = .; RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_ALIGN) - - .data.rel.local : { - *(.data.rel.local) - } - - .data.rel.ro : { - *(.data.rel.ro) - } - _edata = .;
BSS_SECTION(0, 0, 0)