History

module: expose imported namespaces via sysfs

Add /sys/module/*/import_ns to expose imported namespaces for currently loaded modules. The file contains one namespace per line and only exists for modules that import at least one namespace. Previously, the only way for userspace to inspect the symbol namespaces a module imports is to locate the .ko on disk and invoke modinfo(8) to decompress/parse the metadata. The kernel validated namespaces at load time, but it was otherwise discarded. Exposing this data via sysfs provides a runtime mechanism to verify which namespaces are being used by modules. For example, this allows userspace to audit driver API access in Android GKI, which uses symbol namespaces to restrict vendor drivers from using specific kernel interfaces (e.g., direct filesystem access).

Nicholas Sielicki committed 8 months ago

Commit 3fe1dcb1 parent 44a063c3 files · +78 −1Browse files

Unified · Split

3 files
  1. Documentation/ABI/testing/sysfs-module +9 −0
  2. include/linux/module.h +1 −0
  3. kernel/module/main.c +68 −1
Documentation/ABI/testing/sysfs-module+9−0
@@ -48,6 +48,15 @@ Contact: Kay Sievers <kay.sievers@vrfy.org> · 47 unmodified lines
48Description: Show the initialization state(live, coming, going) of48Description: Show the initialization state(live, coming, going) of
49 the module.49 the module.
50 50
51What: /sys/module/*/import_ns
52Date: January 2026
53KernelVersion: 7.1
54Contact: linux-modules@vger.kernel.org
55Description: List of symbol namespaces imported by this module via
56 MODULE_IMPORT_NS(). Each namespace appears on a separate line.
57 This file only exists for modules that import at least one
58 namespace.
59
51What: /sys/module/*/taint60What: /sys/module/*/taint
52Date: Jan 201261Date: Jan 2012
53KernelVersion: 3.362KernelVersion: 3.3
include/linux/module.h+1−0
@@ -413,6 +413,7 @@ struct module { · 412 unmodified lines
413 struct module_attribute *modinfo_attrs;413 struct module_attribute *modinfo_attrs;
414 const char *version;414 const char *version;
415 const char *srcversion;415 const char *srcversion;
416 const char *imported_namespaces;
416 struct kobject *holders_dir;417 struct kobject *holders_dir;
417 418
418 /* Exported symbols */419 /* Exported symbols */
kernel/module/main.c+68−1
@@ -607,6 +607,36 @@ static const struct module_attribute modinfo_##field = { \ · 606 unmodified lines
607MODINFO_ATTR(version);607MODINFO_ATTR(version);
608MODINFO_ATTR(srcversion);608MODINFO_ATTR(srcversion);
609 609
610static void setup_modinfo_import_ns(struct module *mod, const char *s)
611{
612 mod->imported_namespaces = NULL;
613}
614
615static ssize_t show_modinfo_import_ns(const struct module_attribute *mattr,
616 struct module_kobject *mk, char *buffer)
617{
618 return sysfs_emit(buffer, "%s\n", mk->mod->imported_namespaces);
619}
620
621static int modinfo_import_ns_exists(struct module *mod)
622{
623 return mod->imported_namespaces != NULL;
624}
625
626static void free_modinfo_import_ns(struct module *mod)
627{
628 kfree(mod->imported_namespaces);
629 mod->imported_namespaces = NULL;
630}
631
632static const struct module_attribute modinfo_import_ns = {
633 .attr = { .name = "import_ns", .mode = 0444 },
634 .show = show_modinfo_import_ns,
635 .setup = setup_modinfo_import_ns,
636 .test = modinfo_import_ns_exists,
637 .free = free_modinfo_import_ns,
638};
639
610static struct {640static struct {
611 char name[MODULE_NAME_LEN];641 char name[MODULE_NAME_LEN];
612 char taints[MODULE_FLAGS_BUF_SIZE];642 char taints[MODULE_FLAGS_BUF_SIZE];
@@ -1058,6 +1088,7 @@ const struct module_attribute *const modinfo_attrs[] = { · 445 unmodified lines
1058 &module_uevent,1088 &module_uevent,
1059 &modinfo_version,1089 &modinfo_version,
1060 &modinfo_srcversion,1090 &modinfo_srcversion,
1091 &modinfo_import_ns,
1061 &modinfo_initstate,1092 &modinfo_initstate,
1062 &modinfo_coresize,1093 &modinfo_coresize,
1063#ifdef CONFIG_ARCH_WANTS_MODULES_DATA_IN_VMALLOC1094#ifdef CONFIG_ARCH_WANTS_MODULES_DATA_IN_VMALLOC
@@ -1760,11 +1791,43 @@ static void module_license_taint_check(struct module *mod, const char *license) · 696 unmodified lines
1760 }1791 }
1761}1792}
1762 1793
1794static int copy_modinfo_import_ns(struct module *mod, struct load_info *info)
1795{
1796 char *ns;
1797 size_t len, total_len = 0;
1798 char *buf, *p;
1799
1800 for_each_modinfo_entry(ns, info, "import_ns")
1801 total_len += strlen(ns) + 1;
1802
1803 if (!total_len) {
1804 mod->imported_namespaces = NULL;
1805 return 0;
1806 }
1807
1808 buf = kmalloc(total_len, GFP_KERNEL);
1809 if (!buf)
1810 return -ENOMEM;
1811
1812 p = buf;
1813 for_each_modinfo_entry(ns, info, "import_ns") {
1814 len = strlen(ns);
1815 memcpy(p, ns, len);
1816 p += len;
1817 *p++ = '\n';
1818 }
1819 /* Replace trailing newline with null terminator. */
1820 *(p - 1) = '\0';
1821
1822 mod->imported_namespaces = buf;
1823 return 0;
1824}
1825
1763static int setup_modinfo(struct module *mod, struct load_info *info)1826static int setup_modinfo(struct module *mod, struct load_info *info)
1764{1827{
1765 const struct module_attribute *attr;1828 const struct module_attribute *attr;
1766 char *imported_namespace;1829 char *imported_namespace;
1767 int i;1830 int i, err;
1768 1831
1769 for (i = 0; (attr = modinfo_attrs[i]); i++) {1832 for (i = 0; (attr = modinfo_attrs[i]); i++) {
1770 if (attr->setup)1833 if (attr->setup)
@@ -1783,6 +1846,10 @@ static int setup_modinfo(struct module *mod, struct load_info *info) · 12 unmodified lines
1783 }1846 }
1784 }1847 }
1785 1848
1849 err = copy_modinfo_import_ns(mod, info);
1850 if (err)
1851 return err;
1852
1786 return 0;1853 return 0;
1787}1854}
1788 1855

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t