On Wed, Jul 08, 2026 at 09:06:52AM +0100, Lorenzo Stoakes wrote: > On Wed, Jul 08, 2026 at 12:38:09PM +0530, Mukesh Ojha wrote: > > From: Eugen Hristev <[email protected]> > > > > With this driver, the registered regions are copied to a shared memory > > zone at register time. The shared memory zone is supplied via OF. This > > driver will select only regions that are of interest, and keep only > > addresses. The format of the list is Kinfo compatible, with devices like > > Google Pixel phone. The firmware is only interested in some symbols' > > addresses. > > > > Signed-off-by: Eugen Hristev <[email protected]> > > Signed-off-by: Mukesh Ojha <[email protected]> > > Hang on, this is a driver that exposes internal kernel symbol information in a > shared memory region for anybody who wants to access it? >
Yes, this was one of the others we could find in the Android kernel, which could be another use case of the meminspect backend. https://android.googlesource.com/kernel/common/+/refs/heads/android-mainline/drivers/android/debug_kinfo.c -Mukesh > This doesn't really seem sane? > > Looking through the code it seems you are only exposing things that are > already > otherwise exposed, so maybe it's not so bad, but it seems as if a registered > meminfo driver could in any case get access to things they shouldn't? > > > --- > > MAINTAINERS | 1 + > > drivers/of/platform.c | 1 + > > kernel/meminspect/Kconfig | 11 ++ > > kernel/meminspect/Makefile | 1 + > > kernel/meminspect/kinfo.c | 257 +++++++++++++++++++++++++++++++++++++ > > 5 files changed, 271 insertions(+) > > create mode 100644 kernel/meminspect/kinfo.c > > > > diff --git a/MAINTAINERS b/MAINTAINERS > > index 2d816d783024..d805ff9fedac 100644 > > --- a/MAINTAINERS > > +++ b/MAINTAINERS > > @@ -16906,6 +16906,7 @@ M: Eugen Hristev <[email protected]> > > M: Mukesh Ojha <[email protected]> > > S: Maintained > > F: > > Documentation/devicetree/bindings/reserved-memory/google,debug-kinfo.yaml > > +F: kernel/meminspect/kinfo.c > > > > MEMBLOCK AND MEMORY MANAGEMENT INITIALIZATION > > M: Mike Rapoport <[email protected]> > > diff --git a/drivers/of/platform.c b/drivers/of/platform.c > > index 53bca8c6f781..f80bd25fc481 100644 > > --- a/drivers/of/platform.c > > +++ b/drivers/of/platform.c > > @@ -494,6 +494,7 @@ static const struct of_device_id reserved_mem_matches[] > > = { > > { .compatible = "qcom,smem" }, > > { .compatible = "ramoops" }, > > { .compatible = "nvmem-rmem" }, > > + { .compatible = "google,debug-kinfo" }, > > { .compatible = "google,open-dice" }, > > {} > > }; > > diff --git a/kernel/meminspect/Kconfig b/kernel/meminspect/Kconfig > > index 18ff511ad4cf..7f6436c3344b 100644 > > --- a/kernel/meminspect/Kconfig > > +++ b/kernel/meminspect/Kconfig > > @@ -16,3 +16,14 @@ config MEMINSPECT > > > > Note that modules using this feature must be rebuilt if this > > option changes. > > + > > +config MEMINSPECT_KINFO > > + tristate "Shared memory KInfo compatible driver" > > + depends on MEMINSPECT > > + help > > + Say y here to enable the Shared memory KInfo compatible driver. > > + With this driver, the registered regions are copied to a shared > > + memory zone at register time. > > + The shared memory zone is supplied via OF. > > + This driver will select only regions that are of interest, > > + and keep only addresses. The format of the list is Kinfo compatible. > > diff --git a/kernel/meminspect/Makefile b/kernel/meminspect/Makefile > > index 09fd55e6d9cf..283604d892e5 100644 > > --- a/kernel/meminspect/Makefile > > +++ b/kernel/meminspect/Makefile > > @@ -1,3 +1,4 @@ > > # SPDX-License-Identifier: GPL-2.0 > > > > obj-$(CONFIG_MEMINSPECT) += meminspect.o > > +obj-$(CONFIG_MEMINSPECT_KINFO) += kinfo.o > > diff --git a/kernel/meminspect/kinfo.c b/kernel/meminspect/kinfo.c > > new file mode 100644 > > index 000000000000..7451c13bc316 > > --- /dev/null > > +++ b/kernel/meminspect/kinfo.c > > @@ -0,0 +1,257 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > +/* > > + * > > + * Copyright 2002 Rusty Russell <[email protected]> IBM Corporation > > + * Copyright 2021 Google LLC > > + * Copyright 2025 Linaro Ltd. Eugen Hristev <[email protected]> > > + */ > > +#include <linux/container_of.h> > > +#include <linux/kallsyms.h> > > +#include <linux/meminspect.h> > > +#include <linux/module.h> > > +#include <linux/of.h> > > +#include <linux/of_reserved_mem.h> > > +#include <linux/platform_device.h> > > +#include <linux/utsname.h> > > + > > +#define BUILD_INFO_LEN 256 > > +#define DEBUG_KINFO_MAGIC 0xcceeddff > > + > > +/* > > + * Header structure must be byte-packed, since the table is provided to > > + * bootloader. > > + */ > > +struct kernel_info { > > + /* For kallsyms */ > > + u8 enabled_all; > > + u8 enabled_base_relative; > > + u8 enabled_absolute_percpu; > > + u8 enabled_cfi_clang; > > + u32 num_syms; > > + u16 name_len; > > + u16 bit_per_long; > > + u16 module_name_len; > > + u16 symbol_len; > > + u64 _relative_pa; > > + u64 _text_pa; > > + u64 _stext_pa; > > + u64 _etext_pa; > > + u64 _sinittext_pa; > > + u64 _einittext_pa; > > + u64 _end_pa; > > + u64 _offsets_pa; > > + u64 _names_pa; > > + u64 _token_table_pa; > > + u64 _token_index_pa; > > + u64 _markers_pa; > > + u64 _seqs_of_names_pa; > > + > > + /* For frame pointer */ > > + u32 thread_size; > > + > > + /* For virt_to_phys */ > > + u64 swapper_pg_dir_pa; > > + > > + /* For linux banner */ > > + u8 last_uts_release[__NEW_UTS_LEN]; > > + > > + /* For module kallsyms */ > > + u32 enabled_modules_tree_lookup; > > + u32 mod_mem_offset; > > + u32 mod_kallsyms_offset; > > +} __packed; > > + > > +struct kernel_all_info { > > + u32 magic_number; > > + u32 combined_checksum; > > + struct kernel_info info; > > +} __packed; > > + > > +struct debug_kinfo { > > + struct device *dev; > > + void *all_info_addr; > > + size_t all_info_size; > > + struct notifier_block nb; > > +}; > > + > > +static void update_kernel_all_info(struct kernel_all_info *all_info) > > +{ > > + struct kernel_info *info; > > + u32 *checksum_info; > > + int index; > > + > > + all_info->magic_number = DEBUG_KINFO_MAGIC; > > + all_info->combined_checksum = 0; > > + > > + info = &all_info->info; > > + checksum_info = (u32 *)info; > > + for (index = 0; index < sizeof(*info) / sizeof(u32); index++) > > + all_info->combined_checksum ^= checksum_info[index]; > > +} > > + > > +static void __maybe_unused register_kinfo_region(void *priv, > > + const struct inspect_entry *e) > > +{ > > + struct debug_kinfo *kinfo = priv; > > + struct kernel_all_info *all_info = kinfo->all_info_addr; > > + struct kernel_info *info = &all_info->info; > > + struct uts_namespace *uts; > > + u64 paddr; > > + > > + if (e->pa) > > + paddr = e->pa; > > + else > > + paddr = __pa(e->va); > > + > > + switch (e->id) { > > + case MEMINSPECT_ID__sinittext: > > + info->_sinittext_pa = paddr; > > + break; > > + case MEMINSPECT_ID__einittext: > > + info->_einittext_pa = paddr; > > + break; > > + case MEMINSPECT_ID__end: > > + info->_end_pa = paddr; > > + break; > > + case MEMINSPECT_ID__text: > > + info->_text_pa = paddr; > > + break; > > + case MEMINSPECT_ID__stext: > > + info->_stext_pa = paddr; > > + break; > > + case MEMINSPECT_ID__etext: > > + info->_etext_pa = paddr; > > + break; > > + case MEMINSPECT_ID_kallsyms_num_syms: > > + info->num_syms = *(__u32 *)e->va; > > + break; > > + case MEMINSPECT_ID_kallsyms_offsets: > > + info->_offsets_pa = paddr; > > + break; > > + case MEMINSPECT_ID_kallsyms_names: > > + info->_names_pa = paddr; > > + break; > > + case MEMINSPECT_ID_kallsyms_token_table: > > + info->_token_table_pa = paddr; > > + break; > > + case MEMINSPECT_ID_kallsyms_token_index: > > + info->_token_index_pa = paddr; > > + break; > > + case MEMINSPECT_ID_kallsyms_markers: > > + info->_markers_pa = paddr; > > + break; > > + case MEMINSPECT_ID_kallsyms_seqs_of_names: > > + info->_seqs_of_names_pa = paddr; > > + break; > > + case MEMINSPECT_ID_swapper_pg_dir: > > + info->swapper_pg_dir_pa = paddr; > > + break; > > + case MEMINSPECT_ID_init_uts_ns: > > + if (!e->va) > > + return; > > + uts = e->va; > > + strscpy(info->last_uts_release, uts->name.release, > > __NEW_UTS_LEN); > > + break; > > + default: > > + break; > > + }; > > + > > + update_kernel_all_info(all_info); > > +} > > + > > +static int kinfo_notifier_cb(struct notifier_block *nb, > > + unsigned long code, void *entry) > > +{ > > + struct debug_kinfo *kinfo = container_of(nb, struct debug_kinfo, nb); > > + > > + if (code == MEMINSPECT_NOTIFIER_ADD) > > + register_kinfo_region(kinfo, entry); > > + > > + return NOTIFY_DONE; > > +} > > + > > +static int debug_kinfo_probe(struct platform_device *pdev) > > +{ > > + struct kernel_all_info *all_info; > > + struct device *dev = &pdev->dev; > > + struct reserved_mem *rmem; > > + struct debug_kinfo *kinfo; > > + struct kernel_info *info; > > + > > + rmem = of_reserved_mem_lookup(dev->of_node); > > + if (!rmem) > > + return dev_err_probe(dev, -ENODEV, "no such reserved mem of > > node name %s\n", > > + dev->of_node->name); > > + > > + /* Need to wait for reserved memory to be mapped */ > > + if (!rmem->priv) > > + return -EPROBE_DEFER; > > + > > + if (!rmem->base || !rmem->size) > > + dev_err_probe(dev, -EINVAL, "unexpected reserved memory\n"); > > + > > + if (rmem->size < sizeof(struct kernel_all_info)) > > + dev_err_probe(dev, -EINVAL, "reserved memory size too small\n"); > > + > > + kinfo = devm_kzalloc(dev, sizeof(*kinfo), GFP_KERNEL); > > + if (!kinfo) > > + return -ENOMEM; > > + > > + platform_set_drvdata(pdev, kinfo); > > + > > + kinfo->dev = dev; > > + kinfo->all_info_addr = rmem->priv; > > + kinfo->all_info_size = rmem->size; > > + > > + all_info = kinfo->all_info_addr; > > + > > + memset(all_info, 0, sizeof(struct kernel_all_info)); > > + info = &all_info->info; > > + info->enabled_all = IS_ENABLED(CONFIG_KALLSYMS_ALL); > > + info->enabled_absolute_percpu = > > IS_ENABLED(CONFIG_KALLSYMS_ABSOLUTE_PERCPU); > > + info->enabled_base_relative = IS_ENABLED(CONFIG_KALLSYMS_BASE_RELATIVE); > > + info->enabled_cfi_clang = IS_ENABLED(CONFIG_CFI_CLANG); > > + info->name_len = KSYM_NAME_LEN; > > + info->bit_per_long = BITS_PER_LONG; > > + info->module_name_len = MODULE_NAME_LEN; > > + info->symbol_len = KSYM_SYMBOL_LEN; > > + info->thread_size = THREAD_SIZE; > > + info->enabled_modules_tree_lookup = > > IS_ENABLED(CONFIG_MODULES_TREE_LOOKUP); > > + info->mod_mem_offset = offsetof(struct module, mem); > > + info->mod_kallsyms_offset = offsetof(struct module, kallsyms); > > + > > + kinfo->nb.notifier_call = kinfo_notifier_cb; > > + > > + meminspect_notifier_register(&kinfo->nb); > > + meminspect_lock_traverse(kinfo, register_kinfo_region); > > + > > + return 0; > > +} > > + > > +static void debug_kinfo_remove(struct platform_device *pdev) > > +{ > > + struct debug_kinfo *kinfo = platform_get_drvdata(pdev); > > + > > + meminspect_notifier_unregister(&kinfo->nb); > > +} > > + > > +static const struct of_device_id debug_kinfo_of_match[] = { > > + { .compatible = "google,debug-kinfo" }, > > + {}, > > +}; > > +MODULE_DEVICE_TABLE(of, debug_kinfo_of_match); > > + > > +static struct platform_driver debug_kinfo_driver = { > > + .probe = debug_kinfo_probe, > > + .remove = debug_kinfo_remove, > > + .driver = { > > + .name = "debug-kinfo", > > + .of_match_table = debug_kinfo_of_match, > > + }, > > +}; > > +module_platform_driver(debug_kinfo_driver); > > + > > +MODULE_AUTHOR("Eugen Hristev <[email protected]>"); > > +MODULE_AUTHOR("Jone Chou <[email protected]>"); > > +MODULE_DESCRIPTION("meminspect Kinfo Driver"); > > +MODULE_LICENSE("GPL"); > > -- > > 2.53.0 > > -- -Mukesh Ojha

