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

x86/crash: pass dm crypt keys to kdump kernel

1st kernel will build up the kernel command parameter dmcryptkeys as
similar to elfcorehdr to pass the memory address of the stored info of dm
crypt key to kdump kernel.

Link: https://lkml.kernel.org/r/20250502011246.99238-8-coxu@redhat.com
Signed-off-by: Coiby Xu <coxu@redhat.com>
Acked-by: Baoquan He <bhe@redhat.com>
Cc: "Daniel P. Berrange" <berrange@redhat.com>
Cc: Dave Hansen <dave.hansen@intel.com>
Cc: Dave Young <dyoung@redhat.com>
Cc: Jan Pazdziora <jpazdziora@redhat.com>
Cc: Liu Pingfan <kernelfans@gmail.com>
Cc: Milan Broz <gmazyland@gmail.com>
Cc: Ondrej Kozina <okozina@redhat.com>
Cc: Vitaly Kuznetsov <vkuznets@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Coiby Xu and committed by
Andrew Morton
5eb3f605 e1e6cd01

+47 -4
+2 -2
Documentation/admin-guide/kdump/kdump.rst
··· 551 551 ============================================ 552 552 553 553 CONFIG_CRASH_DM_CRYPT can be enabled to support saving the dump file to an 554 - encrypted disk volume. User space can interact with 555 - /sys/kernel/config/crash_dm_crypt_keys for setup, 554 + encrypted disk volume (only x86_64 supported for now). User space can interact 555 + with /sys/kernel/config/crash_dm_crypt_keys for setup, 556 556 557 557 1. Tell the first kernel what logon keys are needed to unlock the disk volumes, 558 558 # Add key #1
+24 -2
arch/x86/kernel/crash.c
··· 278 278 unsigned long long mend) 279 279 { 280 280 unsigned long start, end; 281 + int ret; 281 282 282 283 cmem->ranges[0].start = mstart; 283 284 cmem->ranges[0].end = mend; ··· 287 286 /* Exclude elf header region */ 288 287 start = image->elf_load_addr; 289 288 end = start + image->elf_headers_sz - 1; 290 - return crash_exclude_mem_range(cmem, start, end); 289 + ret = crash_exclude_mem_range(cmem, start, end); 290 + 291 + if (ret) 292 + return ret; 293 + 294 + /* Exclude dm crypt keys region */ 295 + if (image->dm_crypt_keys_addr) { 296 + start = image->dm_crypt_keys_addr; 297 + end = start + image->dm_crypt_keys_sz - 1; 298 + return crash_exclude_mem_range(cmem, start, end); 299 + } 300 + 301 + return ret; 291 302 } 292 303 293 304 /* Prepare memory map for crash dump kernel */ 294 305 int crash_setup_memmap_entries(struct kimage *image, struct boot_params *params) 295 306 { 307 + unsigned int nr_ranges = 0; 296 308 int i, ret = 0; 297 309 unsigned long flags; 298 310 struct e820_entry ei; 299 311 struct crash_memmap_data cmd; 300 312 struct crash_mem *cmem; 301 313 302 - cmem = vzalloc(struct_size(cmem, ranges, 1)); 314 + /* 315 + * Using random kexec_buf for passing dm crypt keys may cause a range 316 + * split. So use two slots here. 317 + */ 318 + nr_ranges = 2; 319 + cmem = vzalloc(struct_size(cmem, ranges, nr_ranges)); 303 320 if (!cmem) 304 321 return -ENOMEM; 322 + 323 + cmem->max_nr_ranges = nr_ranges; 324 + cmem->nr_ranges = 0; 305 325 306 326 memset(&cmd, 0, sizeof(struct crash_memmap_data)); 307 327 cmd.params = params;
+21
arch/x86/kernel/kexec-bzimage64.c
··· 27 27 #include <asm/kexec-bzimage64.h> 28 28 29 29 #define MAX_ELFCOREHDR_STR_LEN 30 /* elfcorehdr=0x<64bit-value> */ 30 + #define MAX_DMCRYPTKEYS_STR_LEN 31 /* dmcryptkeys=0x<64bit-value> */ 31 + 30 32 31 33 /* 32 34 * Defines lowest physical address for various segments. Not sure where ··· 78 76 if (image->type == KEXEC_TYPE_CRASH) { 79 77 len = sprintf(cmdline_ptr, 80 78 "elfcorehdr=0x%lx ", image->elf_load_addr); 79 + 80 + if (image->dm_crypt_keys_addr != 0) 81 + len += sprintf(cmdline_ptr + len, 82 + "dmcryptkeys=0x%lx ", image->dm_crypt_keys_addr); 81 83 } 82 84 memcpy(cmdline_ptr + len, cmdline, cmdline_len); 83 85 cmdline_len += len; ··· 447 441 ret = crash_load_segments(image); 448 442 if (ret) 449 443 return ERR_PTR(ret); 444 + ret = crash_load_dm_crypt_keys(image); 445 + if (ret == -ENOENT) { 446 + kexec_dprintk("No dm crypt key to load\n"); 447 + } else if (ret) { 448 + pr_err("Failed to load dm crypt keys\n"); 449 + return ERR_PTR(ret); 450 + } 451 + if (image->dm_crypt_keys_addr && 452 + cmdline_len + MAX_ELFCOREHDR_STR_LEN + MAX_DMCRYPTKEYS_STR_LEN > 453 + header->cmdline_size) { 454 + pr_err("Appending dmcryptkeys=<addr> to command line exceeds maximum allowed length\n"); 455 + return ERR_PTR(-EINVAL); 456 + } 450 457 } 451 458 #endif 452 459 ··· 487 468 efi_map_sz = efi_get_runtime_map_size(); 488 469 params_cmdline_sz = sizeof(struct boot_params) + cmdline_len + 489 470 MAX_ELFCOREHDR_STR_LEN; 471 + if (image->dm_crypt_keys_addr) 472 + params_cmdline_sz += MAX_DMCRYPTKEYS_STR_LEN; 490 473 params_cmdline_sz = ALIGN(params_cmdline_sz, 16); 491 474 kbuf.bufsz = params_cmdline_sz + ALIGN(efi_map_sz, 16) + 492 475 sizeof(struct setup_data) +