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

Reply via email to