* [PATCH v4 1/9] crash_dump: Fix potential double free and UAF of keys_header
[not found] <20260828084900.1496839-1-coiby.xu@gmail.com>
@ 2026-08-28 8:48 ` Coiby Xu
2026-08-30 6:30 ` Sourabh Jain
2026-08-30 7:07 ` Sourabh Jain
2026-08-28 8:48 ` [PATCH v4 2/9] crash_dump: Disallow writing to dm-crypt configfs during kexec_file_load syscall Coiby Xu
` (7 subsequent siblings)
8 siblings, 2 replies; 16+ messages in thread
From: Coiby Xu @ 2026-08-28 8:48 UTC (permalink / raw)
To: kexec
Cc: Andrew Morton, Sourabh Jain, Baoquan He, Dave Young,
Pratyush Yadav, Mike Rapoport, Pasha Tatashin, open list
If kexec_add_buffer somehow fails, keys_header will be freed. Depending
on /sys/kernel/config/crash_dm_crypt_key/reuse, it will lead to the
following two problems if the kexec_file_load syscall is called again,
1. Double free of keys_header if reuse=false
2. UAF of keys_header if reuse=true
To address these problems and also make it easier to reason about the
code, keep two invariants,
1. keys_header will always be freed at the end of kexec_file_load
syscall except during kdump image unloading for CPU/memory
hot-plugging support
2. There will always be valid keys_header if reuse=true
Fixes: 479e58549b0f ("crash_dump: store dm crypt keys in kdump reserved memory")
Fixes: 9ebfa8dcaea7 ("crash_dump: reuse saved dm crypt keys for CPU/memory hot-plugging")
Reported-by: Sourabh Jain <sourabhjain@linux.ibm.com>
Signed-off-by: Coiby Xu <coiby.xu@gmail.com>
---
include/linux/kexec.h | 6 ++++
kernel/crash_dump_dm_crypt.c | 66 ++++++++++++++++++++++++++----------
kernel/kexec_file.c | 2 ++
3 files changed, 56 insertions(+), 18 deletions(-)
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index 0af8ae4fdd08..0fa8bac04576 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -552,6 +552,12 @@ void set_kexec_sig_enforced(void);
static inline void set_kexec_sig_enforced(void) {}
#endif
+#ifdef CONFIG_CRASH_DM_CRYPT
+void kexec_file_post_load_cleanup_dm_crypt(struct kimage *image);
+#else
+static inline void kexec_file_post_load_cleanup_dm_crypt(struct kimage *image) {}
+#endif
+
#endif /* !defined(__ASSEBMLY__) */
#endif /* LINUX_KEXEC_H */
diff --git a/kernel/crash_dump_dm_crypt.c b/kernel/crash_dump_dm_crypt.c
index c685497cd470..4335b6cb1fc4 100644
--- a/kernel/crash_dump_dm_crypt.c
+++ b/kernel/crash_dump_dm_crypt.c
@@ -84,18 +84,25 @@ static int add_key_to_keyring(struct dm_crypt_key *dm_key,
return r;
}
-static void get_keys_from_kdump_reserved_memory(void)
+static int get_keys_from_kdump_reserved_memory(void)
{
struct keys_header *keys_header_loaded;
+ size_t keys_header_size;
- arch_kexec_unprotect_crashkres();
+ keys_header_size = get_keys_header_size(key_count);
+ keys_header = kzalloc(keys_header_size, GFP_KERNEL);
+ if (!keys_header)
+ return -ENOMEM;
+ arch_kexec_unprotect_crashkres();
keys_header_loaded = kmap_local_page(pfn_to_page(
kexec_crash_image->dm_crypt_keys_addr >> PAGE_SHIFT));
- memcpy(keys_header, keys_header_loaded, get_keys_header_size(key_count));
+ memcpy(keys_header, keys_header_loaded, keys_header_size);
kunmap_local(keys_header_loaded);
arch_kexec_protect_crashkres();
+
+ return 0;
}
static int restore_dm_crypt_keys_to_thread_keyring(void)
@@ -286,17 +293,28 @@ static ssize_t config_keys_reuse_show(struct config_item *item, char *page)
static ssize_t config_keys_reuse_store(struct config_item *item,
const char *page, size_t count)
{
+ bool val;
+ int r;
+
if (!kexec_crash_image || !kexec_crash_image->dm_crypt_keys_addr) {
kexec_dprintk(
"dm-crypt keys haven't be saved to crash-reserved memory\n");
return -EINVAL;
}
- if (kstrtobool(page, &is_dm_key_reused))
+ if (kstrtobool(page, &val) || !val)
return -EINVAL;
- if (is_dm_key_reused)
- get_keys_from_kdump_reserved_memory();
+ if (is_dm_key_reused) {
+ pr_info("Already got dm-crypt keys, please continue with kexec_file_load syscall\n");
+ } else {
+ r = get_keys_from_kdump_reserved_memory();
+ if (r) {
+ pr_warn("Failed to get dm-crypt keys from reserved memory\n");
+ return r;
+ }
+ is_dm_key_reused = true;
+ }
return count;
}
@@ -369,9 +387,6 @@ static int build_keys_header(void)
struct config_key *key;
int i, r;
- if (keys_header != NULL)
- kvfree(keys_header);
-
keys_header = kzalloc(get_keys_header_size(key_count), GFP_KERNEL);
if (!keys_header)
return -ENOMEM;
@@ -415,8 +430,7 @@ int crash_load_dm_crypt_keys(struct kimage *image)
.top_down = false,
.random = true,
};
- int r;
-
+ int r = 0;
if (key_count <= 0) {
kexec_dprintk("No dm-crypt keys\n");
@@ -424,14 +438,15 @@ int crash_load_dm_crypt_keys(struct kimage *image)
}
if (!is_dm_key_reused) {
- image->dm_crypt_keys_addr = 0;
r = build_keys_header();
- if (r) {
- pr_err("Failed to build dm-crypt keys header, ret=%d\n", r);
- return r;
- }
+ if (r)
+ goto out;
}
+ /*
+ * keys_header will be copied to reserver memory later and then be
+ * cleaned up at the end of kexec_file_load syscall
+ */
kbuf.buffer = keys_header;
kbuf.bufsz = get_keys_header_size(key_count);
@@ -441,18 +456,33 @@ int crash_load_dm_crypt_keys(struct kimage *image)
r = kexec_add_buffer(&kbuf);
if (r) {
pr_err("Failed to call kexec_add_buffer, ret=%d\n", r);
- kvfree((void *)kbuf.buffer);
- return r;
+ goto out;
}
+
image->dm_crypt_keys_addr = kbuf.mem;
image->dm_crypt_keys_sz = kbuf.bufsz;
kexec_dprintk(
"Loaded dm crypt keys to kexec_buffer bufsz=0x%lx memsz=0x%lx\n",
kbuf.bufsz, kbuf.memsz);
+out:
+ is_dm_key_reused = false;
return r;
}
+void kexec_file_post_load_cleanup_dm_crypt(struct kimage *image)
+{
+ /*
+ * For CPU/memory hot-plugging, the kdump image will be reloaded. Prevent
+ * keys_header from being cleaned up during unloading when
+ * is_dm_key_reused=true
+ */
+ if (!is_dm_key_reused) {
+ kfree_sensitive(keys_header);
+ keys_header = NULL;
+ }
+}
+
static int __init configfs_dmcrypt_keys_init(void)
{
int ret;
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 59fb9d71e9d8..062f7e79016d 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -140,6 +140,8 @@ void kimage_file_post_load_cleanup(struct kimage *image)
kfree(image->image_loader_data);
image->image_loader_data = NULL;
+ kexec_file_post_load_cleanup_dm_crypt(image);
+
kexec_file_dbg_print = false;
}
--
2.55.0
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH v4 1/9] crash_dump: Fix potential double free and UAF of keys_header
2026-08-28 8:48 ` [PATCH v4 1/9] crash_dump: Fix potential double free and UAF of keys_header Coiby Xu
@ 2026-08-30 6:30 ` Sourabh Jain
2026-08-30 7:07 ` Sourabh Jain
1 sibling, 0 replies; 16+ messages in thread
From: Sourabh Jain @ 2026-08-30 6:30 UTC (permalink / raw)
To: Coiby Xu, kexec
Cc: Andrew Morton, Baoquan He, Dave Young, Pratyush Yadav,
Mike Rapoport, Pasha Tatashin, open list, Jinjie Ruan
Hello Coiby,
On 28/08/26 14:18, Coiby Xu wrote:
> If kexec_add_buffer somehow fails, keys_header will be freed. Depending
> on /sys/kernel/config/crash_dm_crypt_key/reuse, it will lead to the
> following two problems if the kexec_file_load syscall is called again,
> 1. Double free of keys_header if reuse=false
> 2. UAF of keys_header if reuse=true
>
> To address these problems and also make it easier to reason about the
> code, keep two invariants,
> 1. keys_header will always be freed at the end of kexec_file_load
> syscall except during kdump image unloading for CPU/memory
> hot-plugging support
> 2. There will always be valid keys_header if reuse=true
>
> Fixes: 479e58549b0f ("crash_dump: store dm crypt keys in kdump reserved memory")
> Fixes: 9ebfa8dcaea7 ("crash_dump: reuse saved dm crypt keys for CPU/memory hot-plugging")
> Reported-by: Sourabh Jain <sourabhjain@linux.ibm.com>
> Signed-off-by: Coiby Xu <coiby.xu@gmail.com>
> ---
> include/linux/kexec.h | 6 ++++
> kernel/crash_dump_dm_crypt.c | 66 ++++++++++++++++++++++++++----------
> kernel/kexec_file.c | 2 ++
> 3 files changed, 56 insertions(+), 18 deletions(-)
>
> diff --git a/include/linux/kexec.h b/include/linux/kexec.h
> index 0af8ae4fdd08..0fa8bac04576 100644
> --- a/include/linux/kexec.h
> +++ b/include/linux/kexec.h
> @@ -552,6 +552,12 @@ void set_kexec_sig_enforced(void);
> static inline void set_kexec_sig_enforced(void) {}
> #endif
>
> +#ifdef CONFIG_CRASH_DM_CRYPT
> +void kexec_file_post_load_cleanup_dm_crypt(struct kimage *image);
> +#else
> +static inline void kexec_file_post_load_cleanup_dm_crypt(struct kimage *image) {}
> +#endif
> +
> #endif /* !defined(__ASSEBMLY__) */
>
> #endif /* LINUX_KEXEC_H */
> diff --git a/kernel/crash_dump_dm_crypt.c b/kernel/crash_dump_dm_crypt.c
> index c685497cd470..4335b6cb1fc4 100644
> --- a/kernel/crash_dump_dm_crypt.c
> +++ b/kernel/crash_dump_dm_crypt.c
> @@ -84,18 +84,25 @@ static int add_key_to_keyring(struct dm_crypt_key *dm_key,
> return r;
> }
>
> -static void get_keys_from_kdump_reserved_memory(void)
> +static int get_keys_from_kdump_reserved_memory(void)
> {
> struct keys_header *keys_header_loaded;
> + size_t keys_header_size;
>
> - arch_kexec_unprotect_crashkres();
> + keys_header_size = get_keys_header_size(key_count);
> + keys_header = kzalloc(keys_header_size, GFP_KERNEL);
> + if (!keys_header)
> + return -ENOMEM;
>
> + arch_kexec_unprotect_crashkres();
> keys_header_loaded = kmap_local_page(pfn_to_page(
> kexec_crash_image->dm_crypt_keys_addr >> PAGE_SHIFT));
>
> - memcpy(keys_header, keys_header_loaded, get_keys_header_size(key_count));
> + memcpy(keys_header, keys_header_loaded, keys_header_size);
> kunmap_local(keys_header_loaded);
> arch_kexec_protect_crashkres();
> +
> + return 0;
> }
>
> static int restore_dm_crypt_keys_to_thread_keyring(void)
> @@ -286,17 +293,28 @@ static ssize_t config_keys_reuse_show(struct config_item *item, char *page)
> static ssize_t config_keys_reuse_store(struct config_item *item,
> const char *page, size_t count)
> {
> + bool val;
> + int r;
> +
> if (!kexec_crash_image || !kexec_crash_image->dm_crypt_keys_addr) {
> kexec_dprintk(
> "dm-crypt keys haven't be saved to crash-reserved memory\n");
> return -EINVAL;
> }
>
> - if (kstrtobool(page, &is_dm_key_reused))
> + if (kstrtobool(page, &val) || !val)
> return -EINVAL;
>
> - if (is_dm_key_reused)
> - get_keys_from_kdump_reserved_memory();
> + if (is_dm_key_reused) {
> + pr_info("Already got dm-crypt keys, please continue with kexec_file_load syscall\n");
> + } else {
> + r = get_keys_from_kdump_reserved_memory();
> + if (r) {
> + pr_warn("Failed to get dm-crypt keys from reserved memory\n");
> + return r;
> + }
> + is_dm_key_reused = true;
> + }
>
> return count;
> }
> @@ -369,9 +387,6 @@ static int build_keys_header(void)
> struct config_key *key;
> int i, r;
>
> - if (keys_header != NULL)
> - kvfree(keys_header);
> -
> keys_header = kzalloc(get_keys_header_size(key_count), GFP_KERNEL);
> if (!keys_header)
> return -ENOMEM;
> @@ -415,8 +430,7 @@ int crash_load_dm_crypt_keys(struct kimage *image)
> .top_down = false,
> .random = true,
> };
> - int r;
> -
> + int r = 0;
>
> if (key_count <= 0) {
> kexec_dprintk("No dm-crypt keys\n");
> @@ -424,14 +438,15 @@ int crash_load_dm_crypt_keys(struct kimage *image)
> }
>
> if (!is_dm_key_reused) {
> - image->dm_crypt_keys_addr = 0;
> r = build_keys_header();
> - if (r) {
> - pr_err("Failed to build dm-crypt keys header, ret=%d\n", r);
> - return r;
> - }
> + if (r)
> + goto out;
> }
>
> + /*
> + * keys_header will be copied to reserver memory later and then be
> + * cleaned up at the end of kexec_file_load syscall
> + */
> kbuf.buffer = keys_header;
> kbuf.bufsz = get_keys_header_size(key_count);
>
> @@ -441,18 +456,33 @@ int crash_load_dm_crypt_keys(struct kimage *image)
> r = kexec_add_buffer(&kbuf);
> if (r) {
> pr_err("Failed to call kexec_add_buffer, ret=%d\n", r);
> - kvfree((void *)kbuf.buffer);
> - return r;
> + goto out;
> }
> +
> image->dm_crypt_keys_addr = kbuf.mem;
> image->dm_crypt_keys_sz = kbuf.bufsz;
> kexec_dprintk(
> "Loaded dm crypt keys to kexec_buffer bufsz=0x%lx memsz=0x%lx\n",
> kbuf.bufsz, kbuf.memsz);
>
> +out:
> + is_dm_key_reused = false;
> return r;
> }
>
> +void kexec_file_post_load_cleanup_dm_crypt(struct kimage *image)
> +{
> + /*
> + * For CPU/memory hot-plugging, the kdump image will be reloaded. Prevent
> + * keys_header from being cleaned up during unloading when
> + * is_dm_key_reused=true
> + */
> + if (!is_dm_key_reused) {
> + kfree_sensitive(keys_header);
> + keys_header = NULL;
The below patch from Jinjie has proposed to free and reset the
keys_header in
the below patch:
https://lore.kernel.org/all/20260826092541.3905933-8-ruanjinjie@huawei.com/
I suggest to Jinjie to consider dropping his patch and review this one
instead.
I CCed you on the above patch series so feel free share you thoughts.
- Sourabh Jain
> + }
> +}
> +
> static int __init configfs_dmcrypt_keys_init(void)
> {
> int ret;
> diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
> index 59fb9d71e9d8..062f7e79016d 100644
> --- a/kernel/kexec_file.c
> +++ b/kernel/kexec_file.c
> @@ -140,6 +140,8 @@ void kimage_file_post_load_cleanup(struct kimage *image)
> kfree(image->image_loader_data);
> image->image_loader_data = NULL;
>
> + kexec_file_post_load_cleanup_dm_crypt(image);
> +
> kexec_file_dbg_print = false;
> }
>
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH v4 1/9] crash_dump: Fix potential double free and UAF of keys_header
2026-08-28 8:48 ` [PATCH v4 1/9] crash_dump: Fix potential double free and UAF of keys_header Coiby Xu
2026-08-30 6:30 ` Sourabh Jain
@ 2026-08-30 7:07 ` Sourabh Jain
1 sibling, 0 replies; 16+ messages in thread
From: Sourabh Jain @ 2026-08-30 7:07 UTC (permalink / raw)
To: Coiby Xu, kexec
Cc: Andrew Morton, Baoquan He, Dave Young, Pratyush Yadav,
Mike Rapoport, Pasha Tatashin, open list
Nit: I feel 2/9 should be the first patch.
The changes on this patch looks good to me. Feel free to add:
Reviewed-by: Sourabh Jain <sourabhjain@linux.ibm.com>
- Sourabh Jain
On 28/08/26 14:18, Coiby Xu wrote:
> If kexec_add_buffer somehow fails, keys_header will be freed. Depending
> on /sys/kernel/config/crash_dm_crypt_key/reuse, it will lead to the
> following two problems if the kexec_file_load syscall is called again,
> 1. Double free of keys_header if reuse=false
> 2. UAF of keys_header if reuse=true
>
> To address these problems and also make it easier to reason about the
> code, keep two invariants,
> 1. keys_header will always be freed at the end of kexec_file_load
> syscall except during kdump image unloading for CPU/memory
> hot-plugging support
> 2. There will always be valid keys_header if reuse=true
>
> Fixes: 479e58549b0f ("crash_dump: store dm crypt keys in kdump reserved memory")
> Fixes: 9ebfa8dcaea7 ("crash_dump: reuse saved dm crypt keys for CPU/memory hot-plugging")
> Reported-by: Sourabh Jain <sourabhjain@linux.ibm.com>
> Signed-off-by: Coiby Xu <coiby.xu@gmail.com>
> ---
> include/linux/kexec.h | 6 ++++
> kernel/crash_dump_dm_crypt.c | 66 ++++++++++++++++++++++++++----------
> kernel/kexec_file.c | 2 ++
> 3 files changed, 56 insertions(+), 18 deletions(-)
>
> diff --git a/include/linux/kexec.h b/include/linux/kexec.h
> index 0af8ae4fdd08..0fa8bac04576 100644
> --- a/include/linux/kexec.h
> +++ b/include/linux/kexec.h
> @@ -552,6 +552,12 @@ void set_kexec_sig_enforced(void);
> static inline void set_kexec_sig_enforced(void) {}
> #endif
>
> +#ifdef CONFIG_CRASH_DM_CRYPT
> +void kexec_file_post_load_cleanup_dm_crypt(struct kimage *image);
> +#else
> +static inline void kexec_file_post_load_cleanup_dm_crypt(struct kimage *image) {}
> +#endif
> +
> #endif /* !defined(__ASSEBMLY__) */
>
> #endif /* LINUX_KEXEC_H */
> diff --git a/kernel/crash_dump_dm_crypt.c b/kernel/crash_dump_dm_crypt.c
> index c685497cd470..4335b6cb1fc4 100644
> --- a/kernel/crash_dump_dm_crypt.c
> +++ b/kernel/crash_dump_dm_crypt.c
> @@ -84,18 +84,25 @@ static int add_key_to_keyring(struct dm_crypt_key *dm_key,
> return r;
> }
>
> -static void get_keys_from_kdump_reserved_memory(void)
> +static int get_keys_from_kdump_reserved_memory(void)
> {
> struct keys_header *keys_header_loaded;
> + size_t keys_header_size;
>
> - arch_kexec_unprotect_crashkres();
> + keys_header_size = get_keys_header_size(key_count);
> + keys_header = kzalloc(keys_header_size, GFP_KERNEL);
> + if (!keys_header)
> + return -ENOMEM;
>
> + arch_kexec_unprotect_crashkres();
> keys_header_loaded = kmap_local_page(pfn_to_page(
> kexec_crash_image->dm_crypt_keys_addr >> PAGE_SHIFT));
>
> - memcpy(keys_header, keys_header_loaded, get_keys_header_size(key_count));
> + memcpy(keys_header, keys_header_loaded, keys_header_size);
> kunmap_local(keys_header_loaded);
> arch_kexec_protect_crashkres();
> +
> + return 0;
> }
>
> static int restore_dm_crypt_keys_to_thread_keyring(void)
> @@ -286,17 +293,28 @@ static ssize_t config_keys_reuse_show(struct config_item *item, char *page)
> static ssize_t config_keys_reuse_store(struct config_item *item,
> const char *page, size_t count)
> {
> + bool val;
> + int r;
> +
> if (!kexec_crash_image || !kexec_crash_image->dm_crypt_keys_addr) {
> kexec_dprintk(
> "dm-crypt keys haven't be saved to crash-reserved memory\n");
> return -EINVAL;
> }
>
> - if (kstrtobool(page, &is_dm_key_reused))
> + if (kstrtobool(page, &val) || !val)
> return -EINVAL;
>
> - if (is_dm_key_reused)
> - get_keys_from_kdump_reserved_memory();
> + if (is_dm_key_reused) {
> + pr_info("Already got dm-crypt keys, please continue with kexec_file_load syscall\n");
> + } else {
> + r = get_keys_from_kdump_reserved_memory();
> + if (r) {
> + pr_warn("Failed to get dm-crypt keys from reserved memory\n");
> + return r;
> + }
> + is_dm_key_reused = true;
> + }
>
> return count;
> }
> @@ -369,9 +387,6 @@ static int build_keys_header(void)
> struct config_key *key;
> int i, r;
>
> - if (keys_header != NULL)
> - kvfree(keys_header);
> -
> keys_header = kzalloc(get_keys_header_size(key_count), GFP_KERNEL);
> if (!keys_header)
> return -ENOMEM;
> @@ -415,8 +430,7 @@ int crash_load_dm_crypt_keys(struct kimage *image)
> .top_down = false,
> .random = true,
> };
> - int r;
> -
> + int r = 0;
>
> if (key_count <= 0) {
> kexec_dprintk("No dm-crypt keys\n");
> @@ -424,14 +438,15 @@ int crash_load_dm_crypt_keys(struct kimage *image)
> }
>
> if (!is_dm_key_reused) {
> - image->dm_crypt_keys_addr = 0;
> r = build_keys_header();
> - if (r) {
> - pr_err("Failed to build dm-crypt keys header, ret=%d\n", r);
> - return r;
> - }
> + if (r)
> + goto out;
> }
>
> + /*
> + * keys_header will be copied to reserver memory later and then be
> + * cleaned up at the end of kexec_file_load syscall
> + */
> kbuf.buffer = keys_header;
> kbuf.bufsz = get_keys_header_size(key_count);
>
> @@ -441,18 +456,33 @@ int crash_load_dm_crypt_keys(struct kimage *image)
> r = kexec_add_buffer(&kbuf);
> if (r) {
> pr_err("Failed to call kexec_add_buffer, ret=%d\n", r);
> - kvfree((void *)kbuf.buffer);
> - return r;
> + goto out;
> }
> +
> image->dm_crypt_keys_addr = kbuf.mem;
> image->dm_crypt_keys_sz = kbuf.bufsz;
> kexec_dprintk(
> "Loaded dm crypt keys to kexec_buffer bufsz=0x%lx memsz=0x%lx\n",
> kbuf.bufsz, kbuf.memsz);
>
> +out:
> + is_dm_key_reused = false;
> return r;
> }
>
> +void kexec_file_post_load_cleanup_dm_crypt(struct kimage *image)
> +{
> + /*
> + * For CPU/memory hot-plugging, the kdump image will be reloaded. Prevent
> + * keys_header from being cleaned up during unloading when
> + * is_dm_key_reused=true
> + */
> + if (!is_dm_key_reused) {
> + kfree_sensitive(keys_header);
> + keys_header = NULL;
> + }
> +}
> +
> static int __init configfs_dmcrypt_keys_init(void)
> {
> int ret;
> diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
> index 59fb9d71e9d8..062f7e79016d 100644
> --- a/kernel/kexec_file.c
> +++ b/kernel/kexec_file.c
> @@ -140,6 +140,8 @@ void kimage_file_post_load_cleanup(struct kimage *image)
> kfree(image->image_loader_data);
> image->image_loader_data = NULL;
>
> + kexec_file_post_load_cleanup_dm_crypt(image);
> +
> kexec_file_dbg_print = false;
> }
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v4 2/9] crash_dump: Disallow writing to dm-crypt configfs during kexec_file_load syscall
[not found] <20260828084900.1496839-1-coiby.xu@gmail.com>
2026-08-28 8:48 ` [PATCH v4 1/9] crash_dump: Fix potential double free and UAF of keys_header Coiby Xu
@ 2026-08-28 8:48 ` Coiby Xu
2026-08-29 7:02 ` Sourabh Jain
2026-08-28 8:48 ` [PATCH v4 3/9] crash_dump: Read the number of dm-crypt keys from reserved memory Coiby Xu
` (6 subsequent siblings)
8 siblings, 1 reply; 16+ messages in thread
From: Coiby Xu @ 2026-08-28 8:48 UTC (permalink / raw)
To: kexec
Cc: Andrew Morton, Sourabh Jain, Baoquan He, Dave Young,
Pratyush Yadav, Mike Rapoport, Pasha Tatashin, open list
If writing to the configfs group happens concurrently during
kexec_file_load syscall, it may lead to the following issues,
- buffer overflow if dm-crypt keys are added after allocation
- stale total_keys if dm-crypt keys are removed during iteration
- keys_header will not be freed if config/crash_dm_crypt_key/reuse is
set true
So hold config_keys_subsys.su_mutex for the entire sequence during the
kexec_file_load syscall to ensure a consistent snapshot. To have serial
access to config/crash_dm_crypt_key/reuse, use the kexec lock as we also
need to access kexec_crash_image serially.
Fixes: 479e58549b0f ("crash_dump: store dm crypt keys in kdump reserved memory")
Suggested-by: Sourabh Jain <sourabhjain@linux.ibm.com>
Signed-off-by: Coiby Xu <coiby.xu@gmail.com>
---
kernel/crash_dump_dm_crypt.c | 28 ++++++++++++++++++++++++----
1 file changed, 24 insertions(+), 4 deletions(-)
diff --git a/kernel/crash_dump_dm_crypt.c b/kernel/crash_dump_dm_crypt.c
index 4335b6cb1fc4..026c7de4ad85 100644
--- a/kernel/crash_dump_dm_crypt.c
+++ b/kernel/crash_dump_dm_crypt.c
@@ -7,6 +7,7 @@
#include <linux/configfs.h>
#include <linux/module.h>
#include <linux/sysfs.h>
+#include "kexec_internal.h"
#define KEY_NUM_MAX 128 /* maximum dm crypt keys */
#define KEY_SIZE_MAX 256 /* maximum dm crypt key size */
@@ -296,14 +297,20 @@ static ssize_t config_keys_reuse_store(struct config_item *item,
bool val;
int r;
+ if (!kexec_trylock()) {
+ r = -EBUSY;
+ goto unlock;
+ }
+
+ r = -EINVAL;
if (!kexec_crash_image || !kexec_crash_image->dm_crypt_keys_addr) {
kexec_dprintk(
"dm-crypt keys haven't be saved to crash-reserved memory\n");
- return -EINVAL;
+ goto unlock;
}
if (kstrtobool(page, &val) || !val)
- return -EINVAL;
+ goto unlock;
if (is_dm_key_reused) {
pr_info("Already got dm-crypt keys, please continue with kexec_file_load syscall\n");
@@ -311,12 +318,15 @@ static ssize_t config_keys_reuse_store(struct config_item *item,
r = get_keys_from_kdump_reserved_memory();
if (r) {
pr_warn("Failed to get dm-crypt keys from reserved memory\n");
- return r;
+ goto unlock;
}
is_dm_key_reused = true;
}
- return count;
+ r = count;
+unlock:
+ kexec_unlock();
+ return r;
}
CONFIGFS_ATTR(config_keys_, reuse);
@@ -421,6 +431,8 @@ static int build_keys_header(void)
return 0;
}
+static bool mutex_acquired;
+
int crash_load_dm_crypt_keys(struct kimage *image)
{
struct kexec_buf kbuf = {
@@ -432,6 +444,9 @@ int crash_load_dm_crypt_keys(struct kimage *image)
};
int r = 0;
+ mutex_lock(&config_keys_subsys.su_mutex);
+ mutex_acquired = true;
+
if (key_count <= 0) {
kexec_dprintk("No dm-crypt keys\n");
return 0;
@@ -481,6 +496,11 @@ void kexec_file_post_load_cleanup_dm_crypt(struct kimage *image)
kfree_sensitive(keys_header);
keys_header = NULL;
}
+
+ if (mutex_acquired) {
+ mutex_unlock(&config_keys_subsys.su_mutex);
+ mutex_acquired = false;
+ }
}
static int __init configfs_dmcrypt_keys_init(void)
--
2.55.0
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH v4 2/9] crash_dump: Disallow writing to dm-crypt configfs during kexec_file_load syscall
2026-08-28 8:48 ` [PATCH v4 2/9] crash_dump: Disallow writing to dm-crypt configfs during kexec_file_load syscall Coiby Xu
@ 2026-08-29 7:02 ` Sourabh Jain
2026-08-29 12:17 ` Coiby Xu
0 siblings, 1 reply; 16+ messages in thread
From: Sourabh Jain @ 2026-08-29 7:02 UTC (permalink / raw)
To: Coiby Xu, kexec
Cc: Andrew Morton, Baoquan He, Dave Young, Pratyush Yadav,
Mike Rapoport, Pasha Tatashin, open list
On 28/08/26 14:18, Coiby Xu wrote:
> If writing to the configfs group happens concurrently during
> kexec_file_load syscall, it may lead to the following issues,
> - buffer overflow if dm-crypt keys are added after allocation
> - stale total_keys if dm-crypt keys are removed during iteration
> - keys_header will not be freed if config/crash_dm_crypt_key/reuse is
> set true
>
> So hold config_keys_subsys.su_mutex for the entire sequence during the
> kexec_file_load syscall to ensure a consistent snapshot. To have serial
> access to config/crash_dm_crypt_key/reuse, use the kexec lock as we also
> need to access kexec_crash_image serially.
>
> Fixes: 479e58549b0f ("crash_dump: store dm crypt keys in kdump reserved memory")
> Suggested-by: Sourabh Jain <sourabhjain@linux.ibm.com>
> Signed-off-by: Coiby Xu <coiby.xu@gmail.com>
> ---
> kernel/crash_dump_dm_crypt.c | 28 ++++++++++++++++++++++++----
> 1 file changed, 24 insertions(+), 4 deletions(-)
>
> diff --git a/kernel/crash_dump_dm_crypt.c b/kernel/crash_dump_dm_crypt.c
> index 4335b6cb1fc4..026c7de4ad85 100644
> --- a/kernel/crash_dump_dm_crypt.c
> +++ b/kernel/crash_dump_dm_crypt.c
> @@ -7,6 +7,7 @@
> #include <linux/configfs.h>
> #include <linux/module.h>
> #include <linux/sysfs.h>
> +#include "kexec_internal.h"
>
> #define KEY_NUM_MAX 128 /* maximum dm crypt keys */
> #define KEY_SIZE_MAX 256 /* maximum dm crypt key size */
> @@ -296,14 +297,20 @@ static ssize_t config_keys_reuse_store(struct config_item *item,
> bool val;
> int r;
>
> + if (!kexec_trylock()) {
> + r = -EBUSY;
> + goto unlock;
Are we unlocking a lock that we didn't acquire? How about returning
-EBUSY directly instead?
> + }
> +
> + r = -EINVAL;
> if (!kexec_crash_image || !kexec_crash_image->dm_crypt_keys_addr) {
> kexec_dprintk(
> "dm-crypt keys haven't be saved to crash-reserved memory\n");
> - return -EINVAL;
> + goto unlock;
> }
>
> if (kstrtobool(page, &val) || !val)
> - return -EINVAL;
> + goto unlock;
>
> if (is_dm_key_reused) {
> pr_info("Already got dm-crypt keys, please continue with kexec_file_load syscall\n");
> @@ -311,12 +318,15 @@ static ssize_t config_keys_reuse_store(struct config_item *item,
> r = get_keys_from_kdump_reserved_memory();
> if (r) {
> pr_warn("Failed to get dm-crypt keys from reserved memory\n");
> - return r;
> + goto unlock;
> }
> is_dm_key_reused = true;
[...]
> }
>
> - return count;
> + r = count;
> +unlock:
> + kexec_unlock();
> + return r;
> }
>
> CONFIGFS_ATTR(config_keys_, reuse);
> @@ -421,6 +431,8 @@ static int build_keys_header(void)
> return 0;
> }
>
> +static bool mutex_acquired;
> +
> int crash_load_dm_crypt_keys(struct kimage *image)
> {
> struct kexec_buf kbuf = {
> @@ -432,6 +444,9 @@ int crash_load_dm_crypt_keys(struct kimage *image)
> };
> int r = 0;
>
> + mutex_lock(&config_keys_subsys.su_mutex);
> + mutex_acquired = true;
> +
> if (key_count <= 0) {
> kexec_dprintk("No dm-crypt keys\n");
> return 0;
> @@ -481,6 +496,11 @@ void kexec_file_post_load_cleanup_dm_crypt(struct kimage *image)
I explored the kexec_file_load syscall entry path and noticed
that there is a path where the call to
kimage_file_post_load_cleanup() can be skipped.
For example, if kexec_file_load is called and everything goes well
but kexec_post_load() fails, we skip
kimage_file_post_load_cleanup(), and consequently
kexec_file_post_load_cleanup_dm_crypt() as well.
If that happens, the config_keys_subsys.su_mutex remains locked,
which could cause problems with the next kexec load, right?
- Sourabh Jain
> kfree_sensitive(keys_header);
> keys_header = NULL;
> }
> +
> + if (mutex_acquired) {
> + mutex_unlock(&config_keys_subsys.su_mutex);
> + mutex_acquired = false;
> + }
> }
>
> static int __init configfs_dmcrypt_keys_init(void)
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH v4 2/9] crash_dump: Disallow writing to dm-crypt configfs during kexec_file_load syscall
2026-08-29 7:02 ` Sourabh Jain
@ 2026-08-29 12:17 ` Coiby Xu
2026-08-30 5:37 ` Sourabh Jain
0 siblings, 1 reply; 16+ messages in thread
From: Coiby Xu @ 2026-08-29 12:17 UTC (permalink / raw)
To: Sourabh Jain
Cc: kexec, Andrew Morton, Baoquan He, Dave Young, Pratyush Yadav,
Mike Rapoport, Pasha Tatashin, open list
On Sat, Aug 29, 2026 at 12:32:46PM +0530, Sourabh Jain wrote:
>
>
>On 28/08/26 14:18, Coiby Xu wrote:
>>If writing to the configfs group happens concurrently during
>>kexec_file_load syscall, it may lead to the following issues,
>> - buffer overflow if dm-crypt keys are added after allocation
>> - stale total_keys if dm-crypt keys are removed during iteration
>> - keys_header will not be freed if config/crash_dm_crypt_key/reuse is
>> set true
>>
>>So hold config_keys_subsys.su_mutex for the entire sequence during the
>>kexec_file_load syscall to ensure a consistent snapshot. To have serial
>>access to config/crash_dm_crypt_key/reuse, use the kexec lock as we also
>>need to access kexec_crash_image serially.
>>
>>Fixes: 479e58549b0f ("crash_dump: store dm crypt keys in kdump reserved memory")
>>Suggested-by: Sourabh Jain <sourabhjain@linux.ibm.com>
>>Signed-off-by: Coiby Xu <coiby.xu@gmail.com>
>>---
>> kernel/crash_dump_dm_crypt.c | 28 ++++++++++++++++++++++++----
>> 1 file changed, 24 insertions(+), 4 deletions(-)
>>
>>diff --git a/kernel/crash_dump_dm_crypt.c b/kernel/crash_dump_dm_crypt.c
>>index 4335b6cb1fc4..026c7de4ad85 100644
>>--- a/kernel/crash_dump_dm_crypt.c
>>+++ b/kernel/crash_dump_dm_crypt.c
>>@@ -7,6 +7,7 @@
>> #include <linux/configfs.h>
>> #include <linux/module.h>
>> #include <linux/sysfs.h>
>>+#include "kexec_internal.h"
>> #define KEY_NUM_MAX 128 /* maximum dm crypt keys */
>> #define KEY_SIZE_MAX 256 /* maximum dm crypt key size */
>>@@ -296,14 +297,20 @@ static ssize_t config_keys_reuse_store(struct config_item *item,
>> bool val;
>> int r;
>>+ if (!kexec_trylock()) {
>>+ r = -EBUSY;
>>+ goto unlock;
>
>
>Are we unlocking a lock that we didn't acquire? How about returning
>-EBUSY directly instead?
Ah, thanks for catching my mistake! And also thanks for prioritizing
reviewing my patch!
>
>
>>+ }
>>+
>>+ r = -EINVAL;
>> if (!kexec_crash_image || !kexec_crash_image->dm_crypt_keys_addr) {
>> kexec_dprintk(
>> "dm-crypt keys haven't be saved to crash-reserved memory\n");
>>- return -EINVAL;
>>+ goto unlock;
>> }
>> if (kstrtobool(page, &val) || !val)
>>- return -EINVAL;
>>+ goto unlock;
>> if (is_dm_key_reused) {
>> pr_info("Already got dm-crypt keys, please continue with kexec_file_load syscall\n");
>>@@ -311,12 +318,15 @@ static ssize_t config_keys_reuse_store(struct config_item *item,
>> r = get_keys_from_kdump_reserved_memory();
>> if (r) {
>> pr_warn("Failed to get dm-crypt keys from reserved memory\n");
>>- return r;
>>+ goto unlock;
>> }
>> is_dm_key_reused = true;
>[...]
>> }
>>- return count;
>>+ r = count;
>>+unlock:
>>+ kexec_unlock();
>>+ return r;
>> }
>> CONFIGFS_ATTR(config_keys_, reuse);
>>@@ -421,6 +431,8 @@ static int build_keys_header(void)
>> return 0;
>> }
>>+static bool mutex_acquired;
>>+
>> int crash_load_dm_crypt_keys(struct kimage *image)
>> {
>> struct kexec_buf kbuf = {
>>@@ -432,6 +444,9 @@ int crash_load_dm_crypt_keys(struct kimage *image)
>> };
>> int r = 0;
>>+ mutex_lock(&config_keys_subsys.su_mutex);
>>+ mutex_acquired = true;
>>+
>> if (key_count <= 0) {
>> kexec_dprintk("No dm-crypt keys\n");
>> return 0;
>>@@ -481,6 +496,11 @@ void kexec_file_post_load_cleanup_dm_crypt(struct kimage *image)
>
>I explored the kexec_file_load syscall entry path and noticed
>that there is a path where the call to
>kimage_file_post_load_cleanup() can be skipped.
>
>For example, if kexec_file_load is called and everything goes well
>but kexec_post_load() fails, we skip
>kimage_file_post_load_cleanup(), and consequently
>kexec_file_post_load_cleanup_dm_crypt() as well.
>
>If that happens, the config_keys_subsys.su_mutex remains locked,
>which could cause problems with the next kexec load, right?
Thanks for exploring the kexec_file_load syscall entry path! I took a
further look at it. Even though kimage_file_post_load_cleanup can be
skipped, kimage_free will be called regardless which will in turn call
kimage_file_post_load_cleanup.
// kernel/kexec_core.c
void kimage_free(struct kimage *image)
{
/*
* Free up any temporary buffers allocated. This might hit if
* error occurred much later after buffer allocation.
*/
if (image->file_mode)
kimage_file_post_load_cleanup(image);
}
But I realize by using kexec lock to ensure serial access to
is_dm_key_reused, we can actually release the mutex lock at the end of
crash_load_dm_crypt_keys function which can make the code simpler and
potentially more robust. Thanks for inspiring me to find a better
way!
>
>- Sourabh Jain
>
>> kfree_sensitive(keys_header);
>> keys_header = NULL;
>> }
>>+
>>+ if (mutex_acquired) {
>>+ mutex_unlock(&config_keys_subsys.su_mutex);
>>+ mutex_acquired = false;
>>+ }
>> }
>> static int __init configfs_dmcrypt_keys_init(void)
>
--
Best regards,
Coiby
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH v4 2/9] crash_dump: Disallow writing to dm-crypt configfs during kexec_file_load syscall
2026-08-29 12:17 ` Coiby Xu
@ 2026-08-30 5:37 ` Sourabh Jain
0 siblings, 0 replies; 16+ messages in thread
From: Sourabh Jain @ 2026-08-30 5:37 UTC (permalink / raw)
To: Coiby Xu
Cc: kexec, Andrew Morton, Baoquan He, Dave Young, Pratyush Yadav,
Mike Rapoport, Pasha Tatashin, open list
On 29/08/26 17:47, Coiby Xu wrote:
> On Sat, Aug 29, 2026 at 12:32:46PM +0530, Sourabh Jain wrote:
>>
>>
>> On 28/08/26 14:18, Coiby Xu wrote:
>>> If writing to the configfs group happens concurrently during
>>> kexec_file_load syscall, it may lead to the following issues,
>>> - buffer overflow if dm-crypt keys are added after allocation
>>> - stale total_keys if dm-crypt keys are removed during iteration
>>> - keys_header will not be freed if config/crash_dm_crypt_key/reuse is
>>> set true
>>>
>>> So hold config_keys_subsys.su_mutex for the entire sequence during the
>>> kexec_file_load syscall to ensure a consistent snapshot. To have serial
>>> access to config/crash_dm_crypt_key/reuse, use the kexec lock as we
>>> also
>>> need to access kexec_crash_image serially.
>>>
>>> Fixes: 479e58549b0f ("crash_dump: store dm crypt keys in kdump
>>> reserved memory")
>>> Suggested-by: Sourabh Jain <sourabhjain@linux.ibm.com>
>>> Signed-off-by: Coiby Xu <coiby.xu@gmail.com>
>>> ---
>>> kernel/crash_dump_dm_crypt.c | 28 ++++++++++++++++++++++++----
>>> 1 file changed, 24 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/kernel/crash_dump_dm_crypt.c
>>> b/kernel/crash_dump_dm_crypt.c
>>> index 4335b6cb1fc4..026c7de4ad85 100644
>>> --- a/kernel/crash_dump_dm_crypt.c
>>> +++ b/kernel/crash_dump_dm_crypt.c
>>> @@ -7,6 +7,7 @@
>>> #include <linux/configfs.h>
>>> #include <linux/module.h>
>>> #include <linux/sysfs.h>
>>> +#include "kexec_internal.h"
>>> #define KEY_NUM_MAX 128 /* maximum dm crypt keys */
>>> #define KEY_SIZE_MAX 256 /* maximum dm crypt key size */
>>> @@ -296,14 +297,20 @@ static ssize_t config_keys_reuse_store(struct
>>> config_item *item,
>>> bool val;
>>> int r;
>>> + if (!kexec_trylock()) {
>>> + r = -EBUSY;
>>> + goto unlock;
>>
>>
>> Are we unlocking a lock that we didn't acquire? How about returning
>> -EBUSY directly instead?
>
> Ah, thanks for catching my mistake! And also thanks for prioritizing
> reviewing my patch!
No worries at all! Happy to help, and thanks for the patch.
>
>>
>>
>>> + }
>>> +
>>> + r = -EINVAL;
>>> if (!kexec_crash_image ||
>>> !kexec_crash_image->dm_crypt_keys_addr) {
>>> kexec_dprintk(
>>> "dm-crypt keys haven't be saved to crash-reserved
>>> memory\n");
>>> - return -EINVAL;
>>> + goto unlock;
>>> }
>>> if (kstrtobool(page, &val) || !val)
>>> - return -EINVAL;
>>> + goto unlock;
>>> if (is_dm_key_reused) {
>>> pr_info("Already got dm-crypt keys, please continue with
>>> kexec_file_load syscall\n");
>>> @@ -311,12 +318,15 @@ static ssize_t config_keys_reuse_store(struct
>>> config_item *item,
>>> r = get_keys_from_kdump_reserved_memory();
>>> if (r) {
>>> pr_warn("Failed to get dm-crypt keys from reserved
>>> memory\n");
>>> - return r;
>>> + goto unlock;
>>> }
>>> is_dm_key_reused = true;
>> [...]
>>> }
>>> - return count;
>>> + r = count;
>>> +unlock:
>>> + kexec_unlock();
>>> + return r;
>>> }
>>> CONFIGFS_ATTR(config_keys_, reuse);
>>> @@ -421,6 +431,8 @@ static int build_keys_header(void)
>>> return 0;
>>> }
>>> +static bool mutex_acquired;
>>> +
>>> int crash_load_dm_crypt_keys(struct kimage *image)
>>> {
>>> struct kexec_buf kbuf = {
>>> @@ -432,6 +444,9 @@ int crash_load_dm_crypt_keys(struct kimage *image)
>>> };
>>> int r = 0;
>>> + mutex_lock(&config_keys_subsys.su_mutex);
>>> + mutex_acquired = true;
>>> +
>>> if (key_count <= 0) {
>>> kexec_dprintk("No dm-crypt keys\n");
>>> return 0;
>>> @@ -481,6 +496,11 @@ void
>>> kexec_file_post_load_cleanup_dm_crypt(struct kimage *image)
>>
>> I explored the kexec_file_load syscall entry path and noticed
>> that there is a path where the call to
>> kimage_file_post_load_cleanup() can be skipped.
>>
>> For example, if kexec_file_load is called and everything goes well
>> but kexec_post_load() fails, we skip
>> kimage_file_post_load_cleanup(), and consequently
>> kexec_file_post_load_cleanup_dm_crypt() as well.
>>
>> If that happens, the config_keys_subsys.su_mutex remains locked,
>> which could cause problems with the next kexec load, right?
>
> Thanks for exploring the kexec_file_load syscall entry path! I took a
> further look at it. Even though kimage_file_post_load_cleanup can be
> skipped, kimage_free will be called regardless which will in turn call
> kimage_file_post_load_cleanup.
Ah yes, I missed that. That said, we are calling
kimage_file_post_load_cleanup() twice for every kexec_file_load, so this
needs to be looked into separately.
> // kernel/kexec_core.c
> void kimage_free(struct kimage *image)
> {
> /*
> * Free up any temporary buffers allocated. This might hit if
> * error occurred much later after buffer allocation.
> */
> if (image->file_mode)
> kimage_file_post_load_cleanup(image);
> }
>
> But I realize by using kexec lock to ensure serial access to
> is_dm_key_reused, we can actually release the mutex lock at the end of
> crash_load_dm_crypt_keys function which can make the code simpler and
> potentially more robust. Thanks for inspiring me to find a better
> way!
That will be good. Lock ownership will be with just one function, which
will make
things easier to manage.
- Sourabh Jain
>>
>>> kfree_sensitive(keys_header);
>>> keys_header = NULL;
>>> }
>>> +
>>> + if (mutex_acquired) {
>>> + mutex_unlock(&config_keys_subsys.su_mutex);
>>> + mutex_acquired = false;
>>> + }
>>> }
>>> static int __init configfs_dmcrypt_keys_init(void)
>>
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v4 3/9] crash_dump: Read the number of dm-crypt keys from reserved memory
[not found] <20260828084900.1496839-1-coiby.xu@gmail.com>
2026-08-28 8:48 ` [PATCH v4 1/9] crash_dump: Fix potential double free and UAF of keys_header Coiby Xu
2026-08-28 8:48 ` [PATCH v4 2/9] crash_dump: Disallow writing to dm-crypt configfs during kexec_file_load syscall Coiby Xu
@ 2026-08-28 8:48 ` Coiby Xu
2026-08-30 7:19 ` Sourabh Jain
2026-08-28 8:48 ` [PATCH v4 4/9] crash_dump: Free temporary dm-crypt keys_header buffer in kdump kernel Coiby Xu
` (5 subsequent siblings)
8 siblings, 1 reply; 16+ messages in thread
From: Coiby Xu @ 2026-08-28 8:48 UTC (permalink / raw)
To: kexec
Cc: Andrew Morton, Sourabh Jain, Baoquan He, Dave Young,
Pratyush Yadav, Mike Rapoport, Pasha Tatashin, open list
In case user adds/deletes the keys by mistake, it's safer to read the
number of keys from reserved memory.
Fixes: 9ebfa8dcaea7 ("crash_dump: reuse saved dm crypt keys for CPU/memory hot-plugging")
Reported-and-Suggested-by: Sourabh Jain <sourabhjain@linux.ibm.com>
Signed-off-by: Coiby Xu <coiby.xu@gmail.com>
---
kernel/crash_dump_dm_crypt.c | 36 +++++++++++++++++++++++-------------
1 file changed, 23 insertions(+), 13 deletions(-)
diff --git a/kernel/crash_dump_dm_crypt.c b/kernel/crash_dump_dm_crypt.c
index 026c7de4ad85..0b9e09c60745 100644
--- a/kernel/crash_dump_dm_crypt.c
+++ b/kernel/crash_dump_dm_crypt.c
@@ -89,21 +89,31 @@ static int get_keys_from_kdump_reserved_memory(void)
{
struct keys_header *keys_header_loaded;
size_t keys_header_size;
-
- keys_header_size = get_keys_header_size(key_count);
- keys_header = kzalloc(keys_header_size, GFP_KERNEL);
- if (!keys_header)
- return -ENOMEM;
+ int r = 0;
arch_kexec_unprotect_crashkres();
keys_header_loaded = kmap_local_page(pfn_to_page(
kexec_crash_image->dm_crypt_keys_addr >> PAGE_SHIFT));
+ if (keys_header_loaded->total_keys <= 0 ||
+ keys_header_loaded->total_keys > KEY_NUM_MAX) {
+ pr_warn("keys_header saved to reserved memory may be corrupt\n");
+ r = -EINVAL;
+ goto kunmap;
+ }
+
+ keys_header_size = get_keys_header_size(keys_header_loaded->total_keys);
+ keys_header = kzalloc(keys_header_size, GFP_KERNEL);
+ if (!keys_header) {
+ r = -ENOMEM;
+ goto kunmap;
+ }
+
memcpy(keys_header, keys_header_loaded, keys_header_size);
+kunmap:
kunmap_local(keys_header_loaded);
arch_kexec_protect_crashkres();
-
- return 0;
+ return r;
}
static int restore_dm_crypt_keys_to_thread_keyring(void)
@@ -447,12 +457,12 @@ int crash_load_dm_crypt_keys(struct kimage *image)
mutex_lock(&config_keys_subsys.su_mutex);
mutex_acquired = true;
- if (key_count <= 0) {
- kexec_dprintk("No dm-crypt keys\n");
- return 0;
- }
-
if (!is_dm_key_reused) {
+ if (key_count <= 0) {
+ kexec_dprintk("No dm-crypt keys\n");
+ return 0;
+ }
+
r = build_keys_header();
if (r)
goto out;
@@ -463,7 +473,7 @@ int crash_load_dm_crypt_keys(struct kimage *image)
* cleaned up at the end of kexec_file_load syscall
*/
kbuf.buffer = keys_header;
- kbuf.bufsz = get_keys_header_size(key_count);
+ kbuf.bufsz = get_keys_header_size(keys_header->total_keys);
kbuf.memsz = kbuf.bufsz;
kbuf.buf_align = ELF_CORE_HEADER_ALIGN;
--
2.55.0
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH v4 3/9] crash_dump: Read the number of dm-crypt keys from reserved memory
2026-08-28 8:48 ` [PATCH v4 3/9] crash_dump: Read the number of dm-crypt keys from reserved memory Coiby Xu
@ 2026-08-30 7:19 ` Sourabh Jain
0 siblings, 0 replies; 16+ messages in thread
From: Sourabh Jain @ 2026-08-30 7:19 UTC (permalink / raw)
To: Coiby Xu, kexec
Cc: Andrew Morton, Baoquan He, Dave Young, Pratyush Yadav,
Mike Rapoport, Pasha Tatashin, open list
On 28/08/26 14:18, Coiby Xu wrote:
> In case user adds/deletes the keys by mistake, it's safer to read the
> number of keys from reserved memory.
>
> Fixes: 9ebfa8dcaea7 ("crash_dump: reuse saved dm crypt keys for CPU/memory hot-plugging")
> Reported-and-Suggested-by: Sourabh Jain <sourabhjain@linux.ibm.com>
> Signed-off-by: Coiby Xu <coiby.xu@gmail.com>
> ---
> kernel/crash_dump_dm_crypt.c | 36 +++++++++++++++++++++++-------------
> 1 file changed, 23 insertions(+), 13 deletions(-)
>
> diff --git a/kernel/crash_dump_dm_crypt.c b/kernel/crash_dump_dm_crypt.c
> index 026c7de4ad85..0b9e09c60745 100644
> --- a/kernel/crash_dump_dm_crypt.c
> +++ b/kernel/crash_dump_dm_crypt.c
> @@ -89,21 +89,31 @@ static int get_keys_from_kdump_reserved_memory(void)
> {
> struct keys_header *keys_header_loaded;
> size_t keys_header_size;
> -
> - keys_header_size = get_keys_header_size(key_count);
> - keys_header = kzalloc(keys_header_size, GFP_KERNEL);
> - if (!keys_header)
> - return -ENOMEM;
> + int r = 0;
>
> arch_kexec_unprotect_crashkres();
> keys_header_loaded = kmap_local_page(pfn_to_page(
> kexec_crash_image->dm_crypt_keys_addr >> PAGE_SHIFT));
>
> + if (keys_header_loaded->total_keys <= 0 ||
> + keys_header_loaded->total_keys > KEY_NUM_MAX) {
> + pr_warn("keys_header saved to reserved memory may be corrupt\n");
> + r = -EINVAL;
> + goto kunmap;
> + }
> +
> + keys_header_size = get_keys_header_size(keys_header_loaded->total_keys);
> + keys_header = kzalloc(keys_header_size, GFP_KERNEL);
> + if (!keys_header) {
> + r = -ENOMEM;
> + goto kunmap;
> + }
> +
> memcpy(keys_header, keys_header_loaded, keys_header_size);
> +kunmap:
> kunmap_local(keys_header_loaded);
> arch_kexec_protect_crashkres();
> -
> - return 0;
> + return r;
> }
>
> static int restore_dm_crypt_keys_to_thread_keyring(void)
> @@ -447,12 +457,12 @@ int crash_load_dm_crypt_keys(struct kimage *image)
> mutex_lock(&config_keys_subsys.su_mutex);
> mutex_acquired = true;
>
> - if (key_count <= 0) {
> - kexec_dprintk("No dm-crypt keys\n");
> - return 0;
> - }
> -
> if (!is_dm_key_reused) {
> + if (key_count <= 0) {
> + kexec_dprintk("No dm-crypt keys\n");
> + return 0;
> + }
> +
Not directly related to this patch, but I have a query.
Do we really need to take config_keys_subsys.su_mutex when keys are
reused? If not, how about moving the acquisition and release of
config_keys_subsys.su_mutex into build_keys_header()?
- Sourabh Jain
> r = build_keys_header();
> if (r)
> goto out;
> @@ -463,7 +473,7 @@ int crash_load_dm_crypt_keys(struct kimage *image)
> * cleaned up at the end of kexec_file_load syscall
> */
> kbuf.buffer = keys_header;
> - kbuf.bufsz = get_keys_header_size(key_count);
> + kbuf.bufsz = get_keys_header_size(keys_header->total_keys);
>
> kbuf.memsz = kbuf.bufsz;
> kbuf.buf_align = ELF_CORE_HEADER_ALIGN;
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v4 4/9] crash_dump: Free temporary dm-crypt keys_header buffer in kdump kernel
[not found] <20260828084900.1496839-1-coiby.xu@gmail.com>
` (2 preceding siblings ...)
2026-08-28 8:48 ` [PATCH v4 3/9] crash_dump: Read the number of dm-crypt keys from reserved memory Coiby Xu
@ 2026-08-28 8:48 ` Coiby Xu
2026-08-28 8:48 ` [PATCH v4 5/9] crash_dump: Only use kexec_dprintk during the kexec_file_load syscall Coiby Xu
` (4 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: Coiby Xu @ 2026-08-28 8:48 UTC (permalink / raw)
To: kexec
Cc: Andrew Morton, Sourabh Jain, Baoquan He, Dave Young,
Pratyush Yadav, Mike Rapoport, Pasha Tatashin, open list
Although we expect the system to reboot immediately after vmcore dumping
is finished, it's still good to free the temporary keys_header buffer.
Fixes: 62f17d9df692 ("crash_dump: retrieve dm crypt keys in kdump kernel")
Reported-by: Sourabh Jain <sourabhjain@linux.ibm.com>
Reviewed-by: Sourabh Jain <sourabhjain@linux.ibm.com>
Signed-off-by: Coiby Xu <coiby.xu@gmail.com>
---
kernel/crash_dump_dm_crypt.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/kernel/crash_dump_dm_crypt.c b/kernel/crash_dump_dm_crypt.c
index 0b9e09c60745..91b7a5413b62 100644
--- a/kernel/crash_dump_dm_crypt.c
+++ b/kernel/crash_dump_dm_crypt.c
@@ -118,6 +118,7 @@ static int get_keys_from_kdump_reserved_memory(void)
static int restore_dm_crypt_keys_to_thread_keyring(void)
{
+ struct keys_header *keys_header __free(kfree_sensitive) = NULL;
struct dm_crypt_key *key;
size_t keys_header_size;
key_ref_t keyring_ref;
--
2.55.0
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH v4 5/9] crash_dump: Only use kexec_dprintk during the kexec_file_load syscall
[not found] <20260828084900.1496839-1-coiby.xu@gmail.com>
` (3 preceding siblings ...)
2026-08-28 8:48 ` [PATCH v4 4/9] crash_dump: Free temporary dm-crypt keys_header buffer in kdump kernel Coiby Xu
@ 2026-08-28 8:48 ` Coiby Xu
2026-08-28 8:48 ` [PATCH v4 6/9] crash_dump: Improve readability of config_keys_restore_store Coiby Xu
` (3 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: Coiby Xu @ 2026-08-28 8:48 UTC (permalink / raw)
To: kexec
Cc: Andrew Morton, Sourabh Jain, Baoquan He, Dave Young,
Pratyush Yadav, Mike Rapoport, Pasha Tatashin, open list
kexec_dprintk will only be activated by "kexec -d" during
kexec_file_load syscall. So use pr_* outside of this syscall.
Fixes: 9ebfa8dcaea7 ("crash_dump: reuse saved dm crypt keys for CPU/memory hot-plugging")
Fixes: 62f17d9df692 ("crash_dump: retrieve dm crypt keys in kdump kernel")
Reviewed-by: Sourabh Jain <sourabhjain@linux.ibm.com>
Signed-off-by: Coiby Xu <coiby.xu@gmail.com>
---
kernel/crash_dump_dm_crypt.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/kernel/crash_dump_dm_crypt.c b/kernel/crash_dump_dm_crypt.c
index 91b7a5413b62..9ccc7b5320a3 100644
--- a/kernel/crash_dump_dm_crypt.c
+++ b/kernel/crash_dump_dm_crypt.c
@@ -76,10 +76,10 @@ static int add_key_to_keyring(struct dm_crypt_key *dm_key,
if (!IS_ERR(key_ref)) {
r = key_ref_to_ptr(key_ref)->serial;
key_ref_put(key_ref);
- kexec_dprintk("Success adding key %s", dm_key->key_desc);
+ pr_debug("Success adding key %s\n", dm_key->key_desc);
} else {
r = PTR_ERR(key_ref);
- kexec_dprintk("Error when adding key");
+ pr_warn("Error when adding key, ret=%d\n", r);
}
return r;
@@ -129,19 +129,19 @@ static int restore_dm_crypt_keys_to_thread_keyring(void)
keyring_ref =
lookup_user_key(KEY_SPEC_USER_KEYRING, 0x01, KEY_NEED_WRITE);
if (IS_ERR(keyring_ref)) {
- kexec_dprintk("Failed to get the user keyring\n");
+ pr_warn("Failed to get the user keyring\n");
return PTR_ERR(keyring_ref);
}
addr = dm_crypt_keys_addr;
dm_crypt_keys_read((char *)&key_count, sizeof(key_count), &addr);
if (key_count > KEY_NUM_MAX) {
- kexec_dprintk("Failed to read the number of dm-crypt keys\n");
+ pr_warn("Failed to read the number of dm-crypt keys\n");
ret = -1;
goto out;
}
- kexec_dprintk("There are %u keys\n", key_count);
+ pr_debug("There are %u keys\n", key_count);
addr = dm_crypt_keys_addr;
keys_header_size = get_keys_header_size(key_count);
@@ -155,7 +155,7 @@ static int restore_dm_crypt_keys_to_thread_keyring(void)
for (int i = 0; i < keys_header->total_keys; i++) {
key = &keys_header->keys[i];
- kexec_dprintk("Get key (size=%u)\n", key->key_size);
+ pr_debug("Get key (size=%u)\n", key->key_size);
add_key_to_keyring(key, keyring_ref);
}
@@ -315,8 +315,7 @@ static ssize_t config_keys_reuse_store(struct config_item *item,
r = -EINVAL;
if (!kexec_crash_image || !kexec_crash_image->dm_crypt_keys_addr) {
- kexec_dprintk(
- "dm-crypt keys haven't be saved to crash-reserved memory\n");
+ pr_debug("dm-crypt keys haven't be saved to crash-reserved memory\n");
goto unlock;
}
--
2.55.0
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH v4 6/9] crash_dump: Improve readability of config_keys_restore_store
[not found] <20260828084900.1496839-1-coiby.xu@gmail.com>
` (4 preceding siblings ...)
2026-08-28 8:48 ` [PATCH v4 5/9] crash_dump: Only use kexec_dprintk during the kexec_file_load syscall Coiby Xu
@ 2026-08-28 8:48 ` Coiby Xu
2026-08-28 8:48 ` [PATCH v4 7/9] crash_dump: Check the function return codes in restore_dm_crypt_keys_to_thread_keyring Coiby Xu
` (2 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: Coiby Xu @ 2026-08-28 8:48 UTC (permalink / raw)
To: kexec
Cc: Andrew Morton, Sourabh Jain, Baoquan He, Dave Young,
Pratyush Yadav, Mike Rapoport, Pasha Tatashin, open list
config_keys_restore_store currently doesn't validate the user input
before restoring dm-crypt keys. Although it's not necessary for the case
of vmcore dumping, it's better to do it for the sake of consistency and
code readability. Also check the return code of
restore_dm_crypt_keys_to_thread_keyring.
Fixes: 62f17d9df692 ("crash_dump: retrieve dm crypt keys in kdump kernel")
Reviewed-by: Sourabh Jain <sourabhjain@linux.ibm.com>
Signed-off-by: Coiby Xu <coiby.xu@gmail.com>
---
kernel/crash_dump_dm_crypt.c | 20 ++++++++++++++++----
1 file changed, 16 insertions(+), 4 deletions(-)
diff --git a/kernel/crash_dump_dm_crypt.c b/kernel/crash_dump_dm_crypt.c
index 9ccc7b5320a3..e82693df73fb 100644
--- a/kernel/crash_dump_dm_crypt.c
+++ b/kernel/crash_dump_dm_crypt.c
@@ -371,13 +371,25 @@ static ssize_t config_keys_restore_show(struct config_item *item, char *page)
static ssize_t config_keys_restore_store(struct config_item *item,
const char *page, size_t count)
{
- if (!restore)
- restore_dm_crypt_keys_to_thread_keyring();
+ bool val;
+ int r;
- if (kstrtobool(page, &restore))
+ if (kstrtobool(page, &val))
return -EINVAL;
- return count;
+ if (val) {
+ if (restore) {
+ pr_warn("dm-crypt keys already restored!\n");
+ return count;
+ }
+ r = restore_dm_crypt_keys_to_thread_keyring();
+ if (!r) {
+ restore = true;
+ r = count;
+ }
+ }
+
+ return r;
}
CONFIGFS_ATTR(config_keys_, restore);
--
2.55.0
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH v4 7/9] crash_dump: Check the function return codes in restore_dm_crypt_keys_to_thread_keyring
[not found] <20260828084900.1496839-1-coiby.xu@gmail.com>
` (5 preceding siblings ...)
2026-08-28 8:48 ` [PATCH v4 6/9] crash_dump: Improve readability of config_keys_restore_store Coiby Xu
@ 2026-08-28 8:48 ` Coiby Xu
2026-08-28 8:48 ` [PATCH v4 8/9] crash_dump: Disallow configfs/crash_dm_crypt_key/reuse if crash hotplug supported Coiby Xu
2026-08-28 8:48 ` [PATCH v4 9/9] Documentation: kdump: Add arm64 and ppc64le to encrypted dump target support list Coiby Xu
8 siblings, 0 replies; 16+ messages in thread
From: Coiby Xu @ 2026-08-28 8:48 UTC (permalink / raw)
To: kexec
Cc: Andrew Morton, Sourabh Jain, Baoquan He, Dave Young,
Pratyush Yadav, Mike Rapoport, Pasha Tatashin, open list
We should check the return codes so we can abort if keyring allocation
or reading old memory fails.
Note there is no need to refer a key add_key_to_keyring, so delete
related code.
Reviewed-by: Sourabh Jain <sourabhjain@linux.ibm.com>
Signed-off-by: Coiby Xu <coiby.xu@gmail.com>
---
kernel/crash_dump_dm_crypt.c | 23 ++++++++++++++++-------
1 file changed, 16 insertions(+), 7 deletions(-)
diff --git a/kernel/crash_dump_dm_crypt.c b/kernel/crash_dump_dm_crypt.c
index e82693df73fb..b7629174e4db 100644
--- a/kernel/crash_dump_dm_crypt.c
+++ b/kernel/crash_dump_dm_crypt.c
@@ -66,7 +66,7 @@ static int add_key_to_keyring(struct dm_crypt_key *dm_key,
key_ref_t keyring_ref)
{
key_ref_t key_ref;
- int r;
+ int r = 0;
/* create or update the requested key and add it to the target keyring */
key_ref = key_create_or_update(keyring_ref, "user", dm_key->key_desc,
@@ -74,8 +74,6 @@ static int add_key_to_keyring(struct dm_crypt_key *dm_key,
KEY_USR_ALL, KEY_ALLOC_IN_QUOTA);
if (!IS_ERR(key_ref)) {
- r = key_ref_to_ptr(key_ref)->serial;
- key_ref_put(key_ref);
pr_debug("Success adding key %s\n", dm_key->key_desc);
} else {
r = PTR_ERR(key_ref);
@@ -134,9 +132,14 @@ static int restore_dm_crypt_keys_to_thread_keyring(void)
}
addr = dm_crypt_keys_addr;
- dm_crypt_keys_read((char *)&key_count, sizeof(key_count), &addr);
+ ret = dm_crypt_keys_read((char *)&key_count, sizeof(key_count), &addr);
+ if (ret < 0) {
+ pr_err("Failed to read the number of dm-crypt keys\n");
+ goto out;
+ }
+
if (key_count > KEY_NUM_MAX) {
- pr_warn("Failed to read the number of dm-crypt keys\n");
+ pr_warn("Read %u dm-crypt keys (max=%u)\n", key_count, KEY_NUM_MAX);
ret = -1;
goto out;
}
@@ -151,12 +154,18 @@ static int restore_dm_crypt_keys_to_thread_keyring(void)
goto out;
}
- dm_crypt_keys_read((char *)keys_header, keys_header_size, &addr);
+ ret = dm_crypt_keys_read((char *)keys_header, keys_header_size, &addr);
+ if (ret < 0) {
+ pr_err("Failed to read dm-crypt keys\n");
+ goto out;
+ }
for (int i = 0; i < keys_header->total_keys; i++) {
key = &keys_header->keys[i];
pr_debug("Get key (size=%u)\n", key->key_size);
- add_key_to_keyring(key, keyring_ref);
+ ret = add_key_to_keyring(key, keyring_ref);
+ if (ret)
+ break;
}
out:
--
2.55.0
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH v4 8/9] crash_dump: Disallow configfs/crash_dm_crypt_key/reuse if crash hotplug supported
[not found] <20260828084900.1496839-1-coiby.xu@gmail.com>
` (6 preceding siblings ...)
2026-08-28 8:48 ` [PATCH v4 7/9] crash_dump: Check the function return codes in restore_dm_crypt_keys_to_thread_keyring Coiby Xu
@ 2026-08-28 8:48 ` Coiby Xu
2026-08-30 7:58 ` Sourabh Jain
2026-08-28 8:48 ` [PATCH v4 9/9] Documentation: kdump: Add arm64 and ppc64le to encrypted dump target support list Coiby Xu
8 siblings, 1 reply; 16+ messages in thread
From: Coiby Xu @ 2026-08-28 8:48 UTC (permalink / raw)
To: kexec
Cc: Andrew Morton, Sourabh Jain, Baoquan He, Dave Young,
Pratyush Yadav, Mike Rapoport, Pasha Tatashin, Jonathan Corbet,
Shuah Khan, Randy Dunlap, open list:DOCUMENTATION, open list
If crash hotplug is supported, dm-crypt keys saved to reserved memory
will be taken care of automatically. Thus it doesn't make sense to use
configfs/crash_dm_crypt_key/reuse. Not reserving
image->dm_crypt_keys_addr makes it implicitly to disallow using this
API. Currently x86_64 and ppc64le have implemented crash hotplug
feature.
Also update the doc accordingly. Note two doc issues are fixed as well.
Fixes: 9ebfa8dcaea7 ("crash_dump: reuse saved dm crypt keys for CPU/memory hot-plugging")
Signed-off-by: Coiby Xu <coiby.xu@gmail.com>
---
Documentation/admin-guide/kdump/kdump.rst | 16 ++++++++++------
kernel/crash_dump_dm_crypt.c | 13 +++++++++----
2 files changed, 19 insertions(+), 10 deletions(-)
diff --git a/Documentation/admin-guide/kdump/kdump.rst b/Documentation/admin-guide/kdump/kdump.rst
index 7587caadbae1..0bf2eb100a05 100644
--- a/Documentation/admin-guide/kdump/kdump.rst
+++ b/Documentation/admin-guide/kdump/kdump.rst
@@ -577,9 +577,10 @@ with /sys/kernel/config/crash_dm_crypt_keys for setup,
1. Tell the first kernel what logon keys are needed to unlock the disk volumes,
# Add key #1
- mkdir /sys/kernel/config/crash_dm_crypt_keys/7d26b7b4-e342-4d2d-b660-7426b0996720
+ VOL1_UUID=7d26b7b4-e342-4d2d-b660-7426b0996720
+ mkdir /sys/kernel/config/crash_dm_crypt_keys/$VOL1_UUID
# Add key #1's description
- echo cryptsetup:7d26b7b4-e342-4d2d-b660-7426b0996720 > /sys/kernel/config/crash_dm_crypt_keys/description
+ echo cryptsetup:$VOL1_UUID > /sys/kernel/config/crash_dm_crypt_keys/$VOL1_UUID/description
# how many keys do we have now?
cat /sys/kernel/config/crash_dm_crypt_keys/count
@@ -591,15 +592,18 @@ with /sys/kernel/config/crash_dm_crypt_keys for setup,
cat /sys/kernel/config/crash_dm_crypt_keys/count
2
- # To support CPU/memory hot-plugging, reuse keys already saved to reserved
- # memory
- echo true > /sys/kernel/config/crash_dm_crypt_key/reuse
-
2. Load the dump-capture kernel
3. After the dump-capture kerne get booted, restore the keys to user keyring
echo yes > /sys/kernel/crash_dm_crypt_keys/restore
+For CPU/memory hot-plugging, you can reuse keys already saved to reserved
+memory before reloading the kdump image,
+ echo true > /sys/kernel/config/crash_dm_crypt_keys/reuse
+
+Note if crash hotplug is supported, this API is totally unnecessary thus will
+be disabled automatically.
+
Contact
=======
diff --git a/kernel/crash_dump_dm_crypt.c b/kernel/crash_dump_dm_crypt.c
index b7629174e4db..3aaa0f9c3117 100644
--- a/kernel/crash_dump_dm_crypt.c
+++ b/kernel/crash_dump_dm_crypt.c
@@ -324,7 +324,7 @@ static ssize_t config_keys_reuse_store(struct config_item *item,
r = -EINVAL;
if (!kexec_crash_image || !kexec_crash_image->dm_crypt_keys_addr) {
- pr_debug("dm-crypt keys haven't be saved to crash-reserved memory\n");
+ pr_debug("dm-crypt keys haven't be saved to crash-reserved memory or crash hotplug supported\n");
goto unlock;
}
@@ -519,9 +519,9 @@ int crash_load_dm_crypt_keys(struct kimage *image)
void kexec_file_post_load_cleanup_dm_crypt(struct kimage *image)
{
/*
- * For CPU/memory hot-plugging, the kdump image will be reloaded. Prevent
- * keys_header from being cleaned up during unloading when
- * is_dm_key_reused=true
+ * For CPU/memory hot-plugging without CONFIG_CRASH_HOTPLUG, the whole kdump
+ * image will be reloaded. Prevent keys_header from being cleaned up during
+ * unloading when is_dm_key_reused=true
*/
if (!is_dm_key_reused) {
kfree_sensitive(keys_header);
@@ -532,6 +532,11 @@ void kexec_file_post_load_cleanup_dm_crypt(struct kimage *image)
mutex_unlock(&config_keys_subsys.su_mutex);
mutex_acquired = false;
}
+
+#ifdef CONFIG_CRASH_HOTPLUG
+ if (image->hotplug_support)
+ image->dm_crypt_keys_addr = 0;
+#endif
}
static int __init configfs_dmcrypt_keys_init(void)
--
2.55.0
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH v4 8/9] crash_dump: Disallow configfs/crash_dm_crypt_key/reuse if crash hotplug supported
2026-08-28 8:48 ` [PATCH v4 8/9] crash_dump: Disallow configfs/crash_dm_crypt_key/reuse if crash hotplug supported Coiby Xu
@ 2026-08-30 7:58 ` Sourabh Jain
0 siblings, 0 replies; 16+ messages in thread
From: Sourabh Jain @ 2026-08-30 7:58 UTC (permalink / raw)
To: Coiby Xu, kexec
Cc: Andrew Morton, Baoquan He, Dave Young, Pratyush Yadav,
Mike Rapoport, Pasha Tatashin, Jonathan Corbet, Shuah Khan,
Randy Dunlap, open list:DOCUMENTATION, open list
On 28/08/26 14:18, Coiby Xu wrote:
> If crash hotplug is supported, dm-crypt keys saved to reserved memory
> will be taken care of automatically. Thus it doesn't make sense to use
> configfs/crash_dm_crypt_key/reuse. Not reserving
> image->dm_crypt_keys_addr makes it implicitly to disallow using this
> API. Currently x86_64 and ppc64le have implemented crash hotplug
> feature.
>
> Also update the doc accordingly. Note two doc issues are fixed as well.
>
> Fixes: 9ebfa8dcaea7 ("crash_dump: reuse saved dm crypt keys for CPU/memory hot-plugging")
> Signed-off-by: Coiby Xu <coiby.xu@gmail.com>
> ---
> Documentation/admin-guide/kdump/kdump.rst | 16 ++++++++++------
> kernel/crash_dump_dm_crypt.c | 13 +++++++++----
> 2 files changed, 19 insertions(+), 10 deletions(-)
>
> diff --git a/Documentation/admin-guide/kdump/kdump.rst b/Documentation/admin-guide/kdump/kdump.rst
> index 7587caadbae1..0bf2eb100a05 100644
> --- a/Documentation/admin-guide/kdump/kdump.rst
> +++ b/Documentation/admin-guide/kdump/kdump.rst
> @@ -577,9 +577,10 @@ with /sys/kernel/config/crash_dm_crypt_keys for setup,
>
> 1. Tell the first kernel what logon keys are needed to unlock the disk volumes,
> # Add key #1
> - mkdir /sys/kernel/config/crash_dm_crypt_keys/7d26b7b4-e342-4d2d-b660-7426b0996720
> + VOL1_UUID=7d26b7b4-e342-4d2d-b660-7426b0996720
> + mkdir /sys/kernel/config/crash_dm_crypt_keys/$VOL1_UUID
> # Add key #1's description
> - echo cryptsetup:7d26b7b4-e342-4d2d-b660-7426b0996720 > /sys/kernel/config/crash_dm_crypt_keys/description
> + echo cryptsetup:$VOL1_UUID > /sys/kernel/config/crash_dm_crypt_keys/$VOL1_UUID/description
>
> # how many keys do we have now?
> cat /sys/kernel/config/crash_dm_crypt_keys/count
> @@ -591,15 +592,18 @@ with /sys/kernel/config/crash_dm_crypt_keys for setup,
> cat /sys/kernel/config/crash_dm_crypt_keys/count
> 2
>
> - # To support CPU/memory hot-plugging, reuse keys already saved to reserved
> - # memory
> - echo true > /sys/kernel/config/crash_dm_crypt_key/reuse
> -
> 2. Load the dump-capture kernel
>
> 3. After the dump-capture kerne get booted, restore the keys to user keyring
> echo yes > /sys/kernel/crash_dm_crypt_keys/restore
>
> +For CPU/memory hot-plugging, you can reuse keys already saved to reserved
> +memory before reloading the kdump image,
> + echo true > /sys/kernel/config/crash_dm_crypt_keys/reuse
> +
> +Note if crash hotplug is supported, this API is totally unnecessary thus will
> +be disabled automatically.
> +
> Contact
> =======
>
> diff --git a/kernel/crash_dump_dm_crypt.c b/kernel/crash_dump_dm_crypt.c
> index b7629174e4db..3aaa0f9c3117 100644
> --- a/kernel/crash_dump_dm_crypt.c
> +++ b/kernel/crash_dump_dm_crypt.c
> @@ -324,7 +324,7 @@ static ssize_t config_keys_reuse_store(struct config_item *item,
>
> r = -EINVAL;
> if (!kexec_crash_image || !kexec_crash_image->dm_crypt_keys_addr) {
> - pr_debug("dm-crypt keys haven't be saved to crash-reserved memory\n");
> + pr_debug("dm-crypt keys haven't be saved to crash-reserved memory or crash hotplug supported\n");
Nit: the above line is more than 100 characters. There is no
complaint from checkpatch, but I feel we should reduce it to
below 100 characters.
Also, I checked that we don't have pr_fmt defined for this file,
but we do have pr_debug and other pr_* calls. See if defining
pr_fmt helps reduce the character count in the above line.
But the overall idea of handling crash hotplug support with
crash dm-crypt looks good to me. So feel free to add:
Reviewed-by: Sourabh Jain sourabhjain@linux.ibm.com
Thanks,
Sourabh Jain
> goto unlock;
> }
>
> @@ -519,9 +519,9 @@ int crash_load_dm_crypt_keys(struct kimage *image)
> void kexec_file_post_load_cleanup_dm_crypt(struct kimage *image)
> {
> /*
> - * For CPU/memory hot-plugging, the kdump image will be reloaded. Prevent
> - * keys_header from being cleaned up during unloading when
> - * is_dm_key_reused=true
> + * For CPU/memory hot-plugging without CONFIG_CRASH_HOTPLUG, the whole kdump
> + * image will be reloaded. Prevent keys_header from being cleaned up during
> + * unloading when is_dm_key_reused=true
> */
> if (!is_dm_key_reused) {
> kfree_sensitive(keys_header);
> @@ -532,6 +532,11 @@ void kexec_file_post_load_cleanup_dm_crypt(struct kimage *image)
> mutex_unlock(&config_keys_subsys.su_mutex);
> mutex_acquired = false;
> }
> +
> +#ifdef CONFIG_CRASH_HOTPLUG
> + if (image->hotplug_support)
> + image->dm_crypt_keys_addr = 0;
> +#endif
> }
>
> static int __init configfs_dmcrypt_keys_init(void)
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v4 9/9] Documentation: kdump: Add arm64 and ppc64le to encrypted dump target support list
[not found] <20260828084900.1496839-1-coiby.xu@gmail.com>
` (7 preceding siblings ...)
2026-08-28 8:48 ` [PATCH v4 8/9] crash_dump: Disallow configfs/crash_dm_crypt_key/reuse if crash hotplug supported Coiby Xu
@ 2026-08-28 8:48 ` Coiby Xu
8 siblings, 0 replies; 16+ messages in thread
From: Coiby Xu @ 2026-08-28 8:48 UTC (permalink / raw)
To: kexec
Cc: Andrew Morton, Sourabh Jain, Baoquan He, Dave Young,
Pratyush Yadav, Mike Rapoport, Pasha Tatashin, Jonathan Corbet,
Shuah Khan, Randy Dunlap, Rob Herring (Arm),
open list:DOCUMENTATION, open list
The encrypted dump target support is now extended to arm64 and ppc64le.
Fixes: e3a84be1ec2f ("arm64,ppc64le/kdump: pass dm-crypt keys to kdump kernel")
Reported-by: Sourabh Jain <sourabhjain@linux.ibm.com>
Reviewed-by: Sourabh Jain <sourabhjain@linux.ibm.com>
Signed-off-by: Coiby Xu <coiby.xu@gmail.com>
---
Documentation/admin-guide/kdump/kdump.rst | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Documentation/admin-guide/kdump/kdump.rst b/Documentation/admin-guide/kdump/kdump.rst
index 0bf2eb100a05..36ad6125c670 100644
--- a/Documentation/admin-guide/kdump/kdump.rst
+++ b/Documentation/admin-guide/kdump/kdump.rst
@@ -572,8 +572,8 @@ Write the dump file to encrypted disk volume
============================================
CONFIG_CRASH_DM_CRYPT can be enabled to support saving the dump file to an
-encrypted disk volume (only x86_64 supported for now). User space can interact
-with /sys/kernel/config/crash_dm_crypt_keys for setup,
+encrypted disk volume (only x86_64, arm64, ppc64le supported for now). User
+space can interact with /sys/kernel/config/crash_dm_crypt_keys for setup,
1. Tell the first kernel what logon keys are needed to unlock the disk volumes,
# Add key #1
--
2.55.0
^ permalink raw reply [flat|nested] 16+ messages in thread