From: Cong Wang Add a dedicated /proc/kimage file to provide read-only access to all loaded kernel images in the system, for both regular kexec kernel images and multikernel images. The interface displays kernel images in a tabular format showing: - Type: kexec type (default, crash, multikernel) - Start Address: entry point in hexadecimal format - Segments: number of memory segments This interface is particularly useful for inspecting kimages, debugging kexec, and verifying that kernel images are loaded correctly. Signed-off-by: Cong Wang --- kernel/kexec_core.c | 63 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c index ed5c97b4531e..7db755e64dd6 100644 --- a/kernel/kexec_core.c +++ b/kernel/kexec_core.c @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include #include #include @@ -1214,6 +1216,52 @@ struct kimage *kexec_image; struct kimage *kexec_crash_image; static int kexec_load_disabled; +/* + * Proc interface for /proc/kimage + */ +static int kimage_proc_show(struct seq_file *m, void *v) +{ + struct kimage *image; + const char *type_names[] = { + [KEXEC_TYPE_DEFAULT] = "default", + [KEXEC_TYPE_CRASH] = "crash", + [KEXEC_TYPE_MULTIKERNEL] = "multikernel" + }; + + seq_printf(m, "MK_ID Type Start Address Segments\n"); + seq_printf(m, "----- ---------- -------------- --------\n"); + + kimage_list_lock(); + if (list_empty(&kexec_image_list)) { + seq_printf(m, "No kimages loaded\n"); + } else { + list_for_each_entry(image, &kexec_image_list, list) { + const char *type_name = "unknown"; + + if (image->type < ARRAY_SIZE(type_names) && type_names[image->type]) + type_name = type_names[image->type]; + + seq_printf(m, "%5d %-10s 0x%012lx %8lu\n", + image->mk_id, type_name, image->start, image->nr_segments); + } + } + kimage_list_unlock(); + + return 0; +} + +static int kimage_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, kimage_proc_show, NULL); +} + +static const struct proc_ops kimage_proc_ops = { + .proc_open = kimage_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, +}; + #ifdef CONFIG_SYSCTL static int kexec_limit_handler(const struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos) @@ -1285,6 +1333,21 @@ static int __init kexec_core_sysctl_init(void) late_initcall(kexec_core_sysctl_init); #endif +static int __init kimage_proc_init(void) +{ + struct proc_dir_entry *entry; + + entry = proc_create("kimage", 0444, NULL, &kimage_proc_ops); + if (!entry) { + pr_err("Failed to create /proc/kimage\n"); + return -ENOMEM; + } + + pr_debug("Created /proc/kimage interface\n"); + return 0; +} +late_initcall(kimage_proc_init); + bool kexec_load_permitted(int kexec_image_type) { struct kexec_load_limit *limit; -- 2.34.1