Skip to content

Commit aaf3e1d

Browse files
committed
x86/efistub: Omit physical KASLR when memory reservations exist
jira LE-4066 Rebuild_History Non-Buildable kernel-4.18.0-553.72.1.el8_10 commit-author Ard Biesheuvel <ardb@kernel.org> commit 15aa8fb Empty-Commit: Cherry-Pick Conflicts during history rebuild. Will be included in final tarball splat. Ref for failed cherry-pick at: ciq/ciq_backports/kernel-4.18.0-553.72.1.el8_10/15aa8fb8.failed The legacy decompressor has elaborate logic to ensure that the randomized physical placement of the decompressed kernel image does not conflict with any memory reservations, including ones specified on the command line using mem=, memmap=, efi_fake_mem= or hugepages=, which are taken into account by the kernel proper at a later stage. When booting in EFI mode, it is the firmware's job to ensure that the chosen range does not conflict with any memory reservations that it knows about, and this is trivially achieved by using the firmware's memory allocation APIs. That leaves reservations specified on the command line, though, which the firmware knows nothing about, as these regions have no other special significance to the platform. Since commit a1b87d5 ("x86/efistub: Avoid legacy decompressor when doing EFI boot") these reservations are not taken into account when randomizing the physical placement, which may result in conflicts where the memory cannot be reserved by the kernel proper because its own executable image resides there. To avoid having to duplicate or reuse the existing complicated logic, disable physical KASLR entirely when such overrides are specified. These are mostly diagnostic tools or niche features, and physical KASLR (as opposed to virtual KASLR, which is much more important as it affects the memory addresses observed by code executing in the kernel) is something we can live without. Closes: https://lkml.kernel.org/r/FA5F6719-8824-4B04-803E-82990E65E627%40akamai.com Reported-by: Ben Chaney <bchaney@akamai.com> Fixes: a1b87d5 ("x86/efistub: Avoid legacy decompressor when doing EFI boot") Cc: <stable@vger.kernel.org> # v6.1+ Reviewed-by: Kees Cook <keescook@chromium.org> Signed-off-by: Ard Biesheuvel <ardb@kernel.org> (cherry picked from commit 15aa8fb) Signed-off-by: Jonathan Maple <jmaple@ciq.com> # Conflicts: # arch/x86/boot/compressed/eboot.c
1 parent 8493040 commit aaf3e1d

File tree

1 file changed

+142
-0
lines changed

1 file changed

+142
-0
lines changed
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
x86/efistub: Omit physical KASLR when memory reservations exist
2+
3+
jira LE-4066
4+
Rebuild_History Non-Buildable kernel-4.18.0-553.72.1.el8_10
5+
commit-author Ard Biesheuvel <ardb@kernel.org>
6+
commit 15aa8fb852f995dd234a57f12dfb989044968bb6
7+
Empty-Commit: Cherry-Pick Conflicts during history rebuild.
8+
Will be included in final tarball splat. Ref for failed cherry-pick at:
9+
ciq/ciq_backports/kernel-4.18.0-553.72.1.el8_10/15aa8fb8.failed
10+
11+
The legacy decompressor has elaborate logic to ensure that the
12+
randomized physical placement of the decompressed kernel image does not
13+
conflict with any memory reservations, including ones specified on the
14+
command line using mem=, memmap=, efi_fake_mem= or hugepages=, which are
15+
taken into account by the kernel proper at a later stage.
16+
17+
When booting in EFI mode, it is the firmware's job to ensure that the
18+
chosen range does not conflict with any memory reservations that it
19+
knows about, and this is trivially achieved by using the firmware's
20+
memory allocation APIs.
21+
22+
That leaves reservations specified on the command line, though, which
23+
the firmware knows nothing about, as these regions have no other special
24+
significance to the platform. Since commit
25+
26+
a1b87d54f4e4 ("x86/efistub: Avoid legacy decompressor when doing EFI boot")
27+
28+
these reservations are not taken into account when randomizing the
29+
physical placement, which may result in conflicts where the memory
30+
cannot be reserved by the kernel proper because its own executable image
31+
resides there.
32+
33+
To avoid having to duplicate or reuse the existing complicated logic,
34+
disable physical KASLR entirely when such overrides are specified. These
35+
are mostly diagnostic tools or niche features, and physical KASLR (as
36+
opposed to virtual KASLR, which is much more important as it affects the
37+
memory addresses observed by code executing in the kernel) is something
38+
we can live without.
39+
40+
Closes: https://lkml.kernel.org/r/FA5F6719-8824-4B04-803E-82990E65E627%40akamai.com
41+
Reported-by: Ben Chaney <bchaney@akamai.com>
42+
Fixes: a1b87d54f4e4 ("x86/efistub: Avoid legacy decompressor when doing EFI boot")
43+
Cc: <stable@vger.kernel.org> # v6.1+
44+
Reviewed-by: Kees Cook <keescook@chromium.org>
45+
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
46+
(cherry picked from commit 15aa8fb852f995dd234a57f12dfb989044968bb6)
47+
Signed-off-by: Jonathan Maple <jmaple@ciq.com>
48+
49+
# Conflicts:
50+
# arch/x86/boot/compressed/eboot.c
51+
diff --cc arch/x86/boot/compressed/eboot.c
52+
index 5df189735432,8ac4ac9fddef..000000000000
53+
--- a/arch/x86/boot/compressed/eboot.c
54+
+++ b/arch/x86/boot/compressed/eboot.c
55+
@@@ -858,11 -772,29 +858,31 @@@ static void efi_get_seed(void *seed, in
56+
57+
static void error(char *str)
58+
{
59+
- efi_warn("Decompression failed: %s\n", str);
60+
+ efi_printk(sys_table, "Decompression failed: ");
61+
+ efi_printk(sys_table, str);
62+
+ efi_printk(sys_table, "\n");
63+
}
64+
65+
+ static const char *cmdline_memmap_override;
66+
+
67+
+ static efi_status_t parse_options(const char *cmdline)
68+
+ {
69+
+ static const char opts[][14] = {
70+
+ "mem=", "memmap=", "efi_fake_mem=", "hugepages="
71+
+ };
72+
+
73+
+ for (int i = 0; i < ARRAY_SIZE(opts); i++) {
74+
+ const char *p = strstr(cmdline, opts[i]);
75+
+
76+
+ if (p == cmdline || (p > cmdline && isspace(p[-1]))) {
77+
+ cmdline_memmap_override = opts[i];
78+
+ break;
79+
+ }
80+
+ }
81+
+
82+
+ return efi_parse_options(cmdline);
83+
+ }
84+
+
85+
static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry)
86+
{
87+
unsigned long virt_addr = LOAD_PHYSICAL_ADDR;
88+
@@@ -890,9 -822,14 +910,13 @@@
89+
*
90+
* https://bugzilla.kernel.org/show_bug.cgi?id=218173
91+
*/
92+
- if (efi_system_table->hdr.revision <= EFI_2_00_SYSTEM_TABLE_REVISION &&
93+
+ if (sys_table->hdr.revision <= EFI_2_00_SYSTEM_TABLE_REVISION &&
94+
!memcmp(efistub_fw_vendor(), ami, sizeof(ami))) {
95+
- efi_debug("AMI firmware v2.0 or older detected - disabling physical KASLR\n");
96+
seed[0] = 0;
97+
+ } else if (cmdline_memmap_override) {
98+
+ efi_info("%s detected on the kernel command line - disabling physical KASLR\n",
99+
+ cmdline_memmap_override);
100+
+ seed[0] = 0;
101+
}
102+
103+
boot_params_ptr->hdr.loadflags |= KASLR_FLAG;
104+
@@@ -988,7 -901,33 +1012,37 @@@ void __noreturn efi_main(struct efi_con
105+
106+
status = efi_setup_5level_paging();
107+
if (status != EFI_SUCCESS) {
108+
++<<<<<<< HEAD:arch/x86/boot/compressed/eboot.c
109+
+ efi_printk(sys_table, "efi_setup_5level_paging() failed!\n");
110+
++=======
111+
+ efi_err("efi_setup_5level_paging() failed!\n");
112+
+ goto fail;
113+
+ }
114+
+
115+
+ #ifdef CONFIG_CMDLINE_BOOL
116+
+ status = parse_options(CONFIG_CMDLINE);
117+
+ if (status != EFI_SUCCESS) {
118+
+ efi_err("Failed to parse options\n");
119+
+ goto fail;
120+
+ }
121+
+ #endif
122+
+ if (!IS_ENABLED(CONFIG_CMDLINE_OVERRIDE)) {
123+
+ unsigned long cmdline_paddr = ((u64)hdr->cmd_line_ptr |
124+
+ ((u64)boot_params->ext_cmd_line_ptr << 32));
125+
+ status = parse_options((char *)cmdline_paddr);
126+
+ if (status != EFI_SUCCESS) {
127+
+ efi_err("Failed to parse options\n");
128+
+ goto fail;
129+
+ }
130+
+ }
131+
+
132+
+ if (efi_mem_encrypt > 0)
133+
+ hdr->xloadflags |= XLF_MEM_ENCRYPTION;
134+
+
135+
+ status = efi_decompress_kernel(&kernel_entry);
136+
+ if (status != EFI_SUCCESS) {
137+
+ efi_err("Failed to decompress kernel\n");
138+
++>>>>>>> 15aa8fb852f9 (x86/efistub: Omit physical KASLR when memory reservations exist):drivers/firmware/efi/libstub/x86-stub.c
139+
goto fail;
140+
}
141+
142+
* Unmerged path arch/x86/boot/compressed/eboot.c

0 commit comments

Comments
 (0)