anolis: module: introduce the sig_enforce_subsys param

ANBZ: #9703

Introduce the sig_enforce_subsys module parameter to allow users to
control the enforcement of signature verification for a specific
subsystem module.
Now we support gpu, block and net subsys.

Signed-off-by: Guixin Liu <kanie@linux.alibaba.com>
Reviewed-by: Xunlei Pang <xlpang@linux.alibaba.com>
Link: https://gitee.com/anolis/cloud-kernel/pulls/3662
This commit is contained in:
Guixin Liu 2024-08-05 18:44:52 +08:00
parent 85d5e42cc3
commit 2f4c516abd
3 changed files with 81 additions and 1 deletions

View File

@ -3061,6 +3061,13 @@
Note that if CONFIG_MODULE_SIG_FORCE is set, that
is always true, so this option does nothing.
module.sig_enforce_subsys
[KNL] When CONFIG_MODULE_SIG is set, this means that
modules the user set without (valid) signatures will
fail to load. Note that CONFIG_MODULE_SIG_FORCE is set,
that is always true, so this option does nothing.
Now we support gpu, block and net.
module_blacklist= [KNL] Do not load a comma-separated list of
modules. Useful for debugging problem modules.

View File

@ -26,6 +26,8 @@ struct load_info {
struct {
unsigned int sym, str, mod, vers, info, pcpu;
} index;
unsigned long subsys;
};
extern int mod_verify_sig(const void *mod, struct load_info *info);

View File

@ -68,6 +68,72 @@
#define ARCH_SHF_SMALL 0
#endif
#ifdef CONFIG_MODULE_SIG
static char *sig_enforce_subsys = "";
module_param(sig_enforce_subsys, charp, 0644);
MODULE_PARM_DESC(sig_enforce_subsys, "Enforce subsys modules signature check");
enum modules_subsys {
MODULE_SUBSYS_GPU,
MODULE_SUBSYS_BLOCK,
MODULE_SUBSYS_NET,
};
static void set_module_subsys(struct load_info *info, const char *name)
{
char *key_intf_blk = "device_add_disk";
char *key_intf_scsi = "scsi_host_alloc";
char *key_intf_net = "register_netdev";
char *key_intf_gpu = "drm_";
if (info->subsys)
return;
if (!strncmp(name, key_intf_gpu, strlen(key_intf_gpu)))
set_bit(MODULE_SUBSYS_GPU, &info->subsys);
if (!strncmp(name, key_intf_blk, strlen(key_intf_blk)) ||
!strncmp(name, key_intf_scsi, strlen(key_intf_scsi)))
set_bit(MODULE_SUBSYS_BLOCK, &info->subsys);
/* register_netdev or register_netdevice */
if (!strncmp(name, key_intf_net, strlen(key_intf_net)))
set_bit(MODULE_SUBSYS_NET, &info->subsys);
}
static int force_subsys_sig_check(struct load_info *info)
{
if (info->sig_ok)
return 0;
if (test_bit(MODULE_SUBSYS_GPU, &info->subsys) &&
parse_option_str(sig_enforce_subsys, "gpu"))
goto err;
if (test_bit(MODULE_SUBSYS_BLOCK, &info->subsys) &&
parse_option_str(sig_enforce_subsys, "block"))
goto err;
if (test_bit(MODULE_SUBSYS_NET, &info->subsys) &&
parse_option_str(sig_enforce_subsys, "net"))
goto err;
return 0;
err:
pr_notice("%s: Loading is rejected, because of wrong signature or key missing!\n",
info->name);
return -EKEYREJECTED;
}
#else
static void set_module_subsys(struct load_info *info, const char *name) {}
static int force_subsys_sig_check(struct load_info *info)
{
return 0;
}
#endif
/*
* Modules' sections will be aligned on page boundaries
* to ensure complete separation of code and data, but
@ -2491,7 +2557,7 @@ static bool ignore_undef_symbol(Elf_Half emachine, const char *name)
}
/* Change all symbols so that st_value encodes the pointer directly. */
static int simplify_symbols(struct module *mod, const struct load_info *info)
static int simplify_symbols(struct module *mod, struct load_info *info)
{
Elf_Shdr *symsec = &info->sechdrs[info->index.sym];
Elf_Sym *sym = (void *)symsec->sh_addr;
@ -2531,6 +2597,7 @@ static int simplify_symbols(struct module *mod, const struct load_info *info)
ksym = resolve_symbol_wait(mod, info, name);
/* Ok if resolved. */
if (ksym && !IS_ERR(ksym)) {
set_module_subsys(info, name);
sym[i].st_value = kernel_symbol_value(ksym);
break;
}
@ -4186,6 +4253,10 @@ static int load_module(struct load_info *info, const char __user *uargs,
if (err < 0)
goto free_modinfo;
err = force_subsys_sig_check(info);
if (err < 0)
goto free_modinfo;
err = apply_relocations(mod, info);
if (err < 0)
goto free_modinfo;