Skip to content

Commit e59ce66

Browse files
Peter Zijlstramcgrof
authored andcommitted
module: Strict per-modname namespaces
Hi, I've been wanting $topic for a while, and having just stumbled into the whole namespace thing by accident, I figured I'd give it a go, most if the hard parts seem to have already been done. It reserves and disallows imports on any "MODULE_${name}" namespace, while it implicitly adds the same namespace to every module. This allows exports targeted at specific modules and no others -- one random example included. I've hated the various kvm exports we've had for a while, and strictly limiting them to the kvm module helps alleviate some abuse potential.
1 parent 32ccd9d commit e59ce66

3 files changed

Lines changed: 47 additions & 12 deletions

File tree

arch/x86/kernel/fpu/core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ int fpu_swap_kvm_fpstate(struct fpu_guest *guest_fpu, bool enter_guest)
366366
fpregs_unlock();
367367
return 0;
368368
}
369-
EXPORT_SYMBOL_GPL(fpu_swap_kvm_fpstate);
369+
EXPORT_SYMBOL_NS_GPL(fpu_swap_kvm_fpstate, MODULE_kvm);
370370

371371
void fpu_copy_guest_fpstate_to_uabi(struct fpu_guest *gfpu, void *buf,
372372
unsigned int size, u64 xfeatures, u32 pkru)

kernel/module/main.c

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,13 @@ static int verify_namespace_is_imported(const struct load_info *info,
11021102

11031103
namespace = kernel_symbol_namespace(sym);
11041104
if (namespace && namespace[0]) {
1105+
/*
1106+
* Implicitly import MODULE_${mod->name} namespace.
1107+
*/
1108+
if (strncmp(namespace, "MODULE_", 7) == 0 &&
1109+
strcmp(namespace+7, mod->name) == 0)
1110+
return 0;
1111+
11051112
for_each_modinfo_entry(imported_namespace, info, "import_ns") {
11061113
if (strcmp(namespace, imported_namespace) == 0)
11071114
return 0;
@@ -1645,15 +1652,30 @@ static void module_license_taint_check(struct module *mod, const char *license)
16451652
}
16461653
}
16471654

1648-
static void setup_modinfo(struct module *mod, struct load_info *info)
1655+
static int setup_modinfo(struct module *mod, struct load_info *info)
16491656
{
16501657
struct module_attribute *attr;
1658+
char *imported_namespace;
16511659
int i;
16521660

16531661
for (i = 0; (attr = modinfo_attrs[i]); i++) {
16541662
if (attr->setup)
16551663
attr->setup(mod, get_modinfo(info, attr->attr.name));
16561664
}
1665+
1666+
for_each_modinfo_entry(imported_namespace, info, "import_ns") {
1667+
/*
1668+
* 'MODULE_' prefixed namespaces are implicit, disallow
1669+
* explicit imports.
1670+
*/
1671+
if (strstarts(imported_namespace, "MODULE_")) {
1672+
pr_err("%s: module tries to import module namespace: %s\n",
1673+
mod->name, imported_namespace);
1674+
return -EPERM;
1675+
}
1676+
}
1677+
1678+
return 0;
16571679
}
16581680

16591681
static void free_modinfo(struct module *mod)
@@ -3210,7 +3232,9 @@ static int load_module(struct load_info *info, const char __user *uargs,
32103232
goto free_unload;
32113233

32123234
/* Set up MODINFO_ATTR fields */
3213-
setup_modinfo(mod, info);
3235+
err = setup_modinfo(mod, info);
3236+
if (err)
3237+
goto free_modinfo;
32143238

32153239
/* Fix up syms, so that st_value is a pointer to location. */
32163240
err = simplify_symbols(mod, info);

scripts/mod/modpost.c

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1553,8 +1553,19 @@ static void mod_set_crcs(struct module *mod)
15531553
free(buf);
15541554
}
15551555

1556+
static const char *mod_basename(const char *modname)
1557+
{
1558+
const char *basename = strrchr(modname, '/');
1559+
if (basename)
1560+
basename++;
1561+
else
1562+
basename = modname;
1563+
return basename;
1564+
}
1565+
15561566
static void read_symbols(const char *modname)
15571567
{
1568+
char module_namespace[MODULE_NAME_LEN + 8];
15581569
const char *symname;
15591570
char *version;
15601571
char *license;
@@ -1586,12 +1597,16 @@ static void read_symbols(const char *modname)
15861597
license = get_next_modinfo(&info, "license", license);
15871598
}
15881599

1589-
namespace = get_modinfo(&info, "import_ns");
1590-
while (namespace) {
1600+
for (namespace = get_modinfo(&info, "import_ns"); namespace;
1601+
namespace = get_next_modinfo(&info, "import_ns", namespace)) {
1602+
if (strstarts(namespace, "MODULE_"))
1603+
error("importing implicit module namespace: %s\n", namespace);
1604+
15911605
add_namespace(&mod->imported_namespaces, namespace);
1592-
namespace = get_next_modinfo(&info, "import_ns",
1593-
namespace);
15941606
}
1607+
snprintf(module_namespace, sizeof(module_namespace), "MODULE_%s",
1608+
mod_basename(mod->name));
1609+
add_namespace(&mod->imported_namespaces, module_namespace);
15951610

15961611
if (extra_warn && !get_modinfo(&info, "description"))
15971612
warn("missing MODULE_DESCRIPTION() in %s\n", modname);
@@ -1700,11 +1715,7 @@ static void check_exports(struct module *mod)
17001715
s->crc_valid = exp->crc_valid;
17011716
s->crc = exp->crc;
17021717

1703-
basename = strrchr(mod->name, '/');
1704-
if (basename)
1705-
basename++;
1706-
else
1707-
basename = mod->name;
1718+
basename = mod_basename(mod->name);
17081719

17091720
if (!contains_namespace(&mod->imported_namespaces, exp->namespace)) {
17101721
modpost_log(!allow_missing_ns_imports,

0 commit comments

Comments
 (0)