kexec: Allocate kernel above bzImage's pref_address
authorChris Koch <chrisko@google.com>
Fri, 15 Dec 2023 19:05:21 +0000 (11:05 -0800)
committerDave Hansen <dave.hansen@linux.intel.com>
Thu, 22 Feb 2024 23:13:57 +0000 (15:13 -0800)
A relocatable kernel will relocate itself to pref_address if it is
loaded below pref_address. This means a booted kernel may be relocating
itself to an area with reserved memory on modern systems, potentially
clobbering arbitrary data that may be important to the system.

This is often the case, as the default value of PHYSICAL_START is
0x1000000 and kernels are typically loaded at 0x100000 or above by
bootloaders like iPXE or kexec. GRUB behaves like the approach
implemented here.

Also fixes the documentation around pref_address and PHYSICAL_START to
be accurate.

[ dhansen: changelog tweak ]

Co-developed-by: Cloud Hsu <cloudhsu@google.com>
Signed-off-by: Cloud Hsu <cloudhsu@google.com>
Signed-off-by: Chris Koch <chrisko@google.com>
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Reviewed-by: H. Peter Anvin (Intel) <hpa@zytor.com>
Link: https://lore.kernel.org/all/20231215190521.3796022-1-chrisko%40google.com
Documentation/arch/x86/boot.rst
arch/x86/Kconfig
arch/x86/kernel/kexec-bzimage64.c

index c513855a54bb99fa10c5e4029dc5ca38aeb03681..4fd492cb49704fa21fd368fe0832f332e952c83d 100644 (file)
@@ -878,7 +878,8 @@ Protocol:   2.10+
   address if possible.
 
   A non-relocatable kernel will unconditionally move itself and to run
-  at this address.
+  at this address. A relocatable kernel will move itself to this address if it
+  loaded below this address.
 
 ============   =======
 Field name:    init_size
index 5edec175b9bfc92dfac8832fc3600b843407828b..1a33575f98af43e424d396549c17f39f344c8402 100644 (file)
@@ -2114,11 +2114,11 @@ config PHYSICAL_START
        help
          This gives the physical address where the kernel is loaded.
 
-         If kernel is a not relocatable (CONFIG_RELOCATABLE=n) then
-         bzImage will decompress itself to above physical address and
-         run from there. Otherwise, bzImage will run from the address where
-         it has been loaded by the boot loader and will ignore above physical
-         address.
+         If the kernel is not relocatable (CONFIG_RELOCATABLE=n) then bzImage
+         will decompress itself to above physical address and run from there.
+         Otherwise, bzImage will run from the address where it has been loaded
+         by the boot loader. The only exception is if it is loaded below the
+         above physical address, in which case it will relocate itself there.
 
          In normal kdump cases one does not have to set/change this option
          as now bzImage can be compiled as a completely relocatable image
index 2a422e00ed4b42f7921c238a47702d47bf8888c5..cde167b0ea92adb08115bb359b2284ea3e6acbe0 100644 (file)
@@ -503,7 +503,10 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
        kbuf.bufsz =  kernel_len - kern16_size;
        kbuf.memsz = PAGE_ALIGN(header->init_size);
        kbuf.buf_align = header->kernel_alignment;
-       kbuf.buf_min = MIN_KERNEL_LOAD_ADDR;
+       if (header->pref_address < MIN_KERNEL_LOAD_ADDR)
+               kbuf.buf_min = MIN_KERNEL_LOAD_ADDR;
+       else
+               kbuf.buf_min = header->pref_address;
        kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
        ret = kexec_add_buffer(&kbuf);
        if (ret)