Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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).

Signed-off-by: Nicholas Sielicki <linux@opensource.nslick.com>
[Sami: Updated the commit message to explain motivation.]
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>

authored by

Nicholas Sielicki and committed by
Sami Tolvanen
3fe1dcbc 44a063c0

+78 -1
+9
Documentation/ABI/testing/sysfs-module
··· 48 48 Description: Show the initialization state(live, coming, going) of 49 49 the module. 50 50 51 + What: /sys/module/*/import_ns 52 + Date: January 2026 53 + KernelVersion: 7.1 54 + Contact: linux-modules@vger.kernel.org 55 + Description: 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 + 51 60 What: /sys/module/*/taint 52 61 Date: Jan 2012 53 62 KernelVersion: 3.3
+1
include/linux/module.h
··· 413 413 struct module_attribute *modinfo_attrs; 414 414 const char *version; 415 415 const char *srcversion; 416 + const char *imported_namespaces; 416 417 struct kobject *holders_dir; 417 418 418 419 /* Exported symbols */
+68 -1
kernel/module/main.c
··· 607 607 MODINFO_ATTR(version); 608 608 MODINFO_ATTR(srcversion); 609 609 610 + static void setup_modinfo_import_ns(struct module *mod, const char *s) 611 + { 612 + mod->imported_namespaces = NULL; 613 + } 614 + 615 + static 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 + 621 + static int modinfo_import_ns_exists(struct module *mod) 622 + { 623 + return mod->imported_namespaces != NULL; 624 + } 625 + 626 + static void free_modinfo_import_ns(struct module *mod) 627 + { 628 + kfree(mod->imported_namespaces); 629 + mod->imported_namespaces = NULL; 630 + } 631 + 632 + static 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 + 610 640 static struct { 611 641 char name[MODULE_NAME_LEN]; 612 642 char taints[MODULE_FLAGS_BUF_SIZE]; ··· 1088 1058 &module_uevent, 1089 1059 &modinfo_version, 1090 1060 &modinfo_srcversion, 1061 + &modinfo_import_ns, 1091 1062 &modinfo_initstate, 1092 1063 &modinfo_coresize, 1093 1064 #ifdef CONFIG_ARCH_WANTS_MODULES_DATA_IN_VMALLOC ··· 1791 1760 } 1792 1761 } 1793 1762 1763 + static int copy_modinfo_import_ns(struct module *mod, struct load_info *info) 1764 + { 1765 + char *ns; 1766 + size_t len, total_len = 0; 1767 + char *buf, *p; 1768 + 1769 + for_each_modinfo_entry(ns, info, "import_ns") 1770 + total_len += strlen(ns) + 1; 1771 + 1772 + if (!total_len) { 1773 + mod->imported_namespaces = NULL; 1774 + return 0; 1775 + } 1776 + 1777 + buf = kmalloc(total_len, GFP_KERNEL); 1778 + if (!buf) 1779 + return -ENOMEM; 1780 + 1781 + p = buf; 1782 + for_each_modinfo_entry(ns, info, "import_ns") { 1783 + len = strlen(ns); 1784 + memcpy(p, ns, len); 1785 + p += len; 1786 + *p++ = '\n'; 1787 + } 1788 + /* Replace trailing newline with null terminator. */ 1789 + *(p - 1) = '\0'; 1790 + 1791 + mod->imported_namespaces = buf; 1792 + return 0; 1793 + } 1794 + 1794 1795 static int setup_modinfo(struct module *mod, struct load_info *info) 1795 1796 { 1796 1797 const struct module_attribute *attr; 1797 1798 char *imported_namespace; 1798 - int i; 1799 + int i, err; 1799 1800 1800 1801 for (i = 0; (attr = modinfo_attrs[i]); i++) { 1801 1802 if (attr->setup) ··· 1845 1782 return -EPERM; 1846 1783 } 1847 1784 } 1785 + 1786 + err = copy_modinfo_import_ns(mod, info); 1787 + if (err) 1788 + return err; 1848 1789 1849 1790 return 0; 1850 1791 }