Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86/compressed/64: Add identity mappings for setup_data entries

The decompressed kernel initially relies on the identity map set up by
the boot/compressed kernel for accessing things like boot_params. With
the recent introduction of SEV-SNP support, the decompressed kernel
also needs to access the setup_data entries pointed to by
boot_params->hdr.setup_data.

This can lead to a crash in the kexec kernel during early boot due to
these entries not currently being included in the initial identity map,
see thread at Link below.

Include mappings for the setup_data entries in the initial identity map.

[ bp: Massage commit message and use a helper var for better readability. ]

Fixes: b190a043c49a ("x86/sev: Add SEV-SNP feature detection/setup")
Reported-by: Jun'ichi Nomura <junichi.nomura@nec.com>
Signed-off-by: Michael Roth <michael.roth@amd.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Link: https://lore.kernel.org/r/TYCPR01MB694815CD815E98945F63C99183B49@TYCPR01MB6948.jpnprd01.prod.outlook.com

authored by

Michael Roth and committed by
Borislav Petkov
b57feed2 7e09ac27

+13
+13
arch/x86/boot/compressed/ident_map_64.c
··· 110 110 void initialize_identity_maps(void *rmode) 111 111 { 112 112 unsigned long cmdline; 113 + struct setup_data *sd; 113 114 114 115 /* Exclude the encryption mask from __PHYSICAL_MASK */ 115 116 physical_mask &= ~sme_me_mask; ··· 163 162 kernel_add_identity_map((unsigned long)boot_params, (unsigned long)(boot_params + 1)); 164 163 cmdline = get_cmd_line_ptr(); 165 164 kernel_add_identity_map(cmdline, cmdline + COMMAND_LINE_SIZE); 165 + 166 + /* 167 + * Also map the setup_data entries passed via boot_params in case they 168 + * need to be accessed by uncompressed kernel via the identity mapping. 169 + */ 170 + sd = (struct setup_data *)boot_params->hdr.setup_data; 171 + while (sd) { 172 + unsigned long sd_addr = (unsigned long)sd; 173 + 174 + kernel_add_identity_map(sd_addr, sd_addr + sizeof(*sd) + sd->len); 175 + sd = (struct setup_data *)sd->next; 176 + } 166 177 167 178 sev_prep_identity_maps(top_level_pgt); 168 179