Add a new helper function, load_module_mem(), which can load a kernel module from a byte array in memory. Also add a new module loader flag, MODULE_INIT_MEM, signalling that a module was loaded in this way. When a module is loaded with load_module_mem(), we do a few things differently: - don't do signature verification - ignore vermagic - don't taint the kernel - keep the initial reference to the module until the caller wants to drop it These changes are necessary for having a bundled (but separately compiled) FIPS module. We may want to let distros carry patches to disable tainting separately so this information is not lost in case somebody builds a non-distro kernel using a FIPS module compiled for an incompatible version. Co-developed-by: Saeed Mirzamohammadi <saeed.mirzamohammadi@xxxxxxxxxx> Signed-off-by: Vegard Nossum <vegard.nossum@xxxxxxxxxx> --- include/linux/module.h | 2 + include/uapi/linux/module.h | 5 ++ kernel/module/main.c | 99 ++++++++++++++++++++++++++----------- 3 files changed, 77 insertions(+), 29 deletions(-) diff --git a/include/linux/module.h b/include/linux/module.h index 3319a5269d28..00d85602fb6a 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -586,6 +586,8 @@ struct module { #ifdef CONFIG_MODULES +extern int load_module_mem(const char *mem, size_t size); + /* Get/put a kernel symbol (calls must be symmetric) */ void *__symbol_get(const char *symbol); void *__symbol_get_gpl(const char *symbol); diff --git a/include/uapi/linux/module.h b/include/uapi/linux/module.h index 03a33ffffcba..5dcd24018be7 100644 --- a/include/uapi/linux/module.h +++ b/include/uapi/linux/module.h @@ -7,4 +7,9 @@ #define MODULE_INIT_IGNORE_VERMAGIC 2 #define MODULE_INIT_COMPRESSED_FILE 4 +#ifdef __KERNEL__ +/* Internal flags */ +#define MODULE_INIT_MEM 30 +#endif + #endif /* _UAPI_LINUX_MODULE_H */ diff --git a/kernel/module/main.c b/kernel/module/main.c index c66b26184936..12ce4bad29ca 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -2572,11 +2572,14 @@ static void module_augment_kernel_taints(struct module *mod, struct load_info *i static int check_modinfo(struct module *mod, struct load_info *info, int flags) { - const char *modmagic = get_modinfo(info, "vermagic"); + const char *modmagic = NULL; int err; - if (flags & MODULE_INIT_IGNORE_VERMAGIC) - modmagic = NULL; + if (flags & MODULE_INIT_MEM) + return 0; + + if (!(flags & MODULE_INIT_IGNORE_VERMAGIC)) + modmagic = get_modinfo(info, "vermagic"); /* This is allowed: modprobe --force will invalidate it. */ if (!modmagic) { @@ -3007,7 +3010,7 @@ module_param(async_probe, bool, 0644); * Keep it uninlined to provide a reliable breakpoint target, e.g. for the gdb * helper command 'lx-symbols'. */ -static noinline int do_init_module(struct module *mod) +static noinline int do_init_module(struct module *mod, int flags) { int ret = 0; struct mod_initfree *freeinit; @@ -3071,7 +3074,8 @@ static noinline int do_init_module(struct module *mod) mod->mem[MOD_INIT_TEXT].base + mod->mem[MOD_INIT_TEXT].size); mutex_lock(&module_mutex); /* Drop initial reference. */ - module_put(mod); + if (!(flags & MODULE_INIT_MEM)) + module_put(mod); trim_init_extable(mod); #ifdef CONFIG_KALLSYMS /* Switch to core kallsyms now init is done: kallsyms may be walking! */ @@ -3347,31 +3351,17 @@ static int early_mod_check(struct load_info *info, int flags) /* * Allocate and load the module: note that size of section 0 is always * zero, and we rely on this for optional sections. + * + * NOTE: module signature verification must have been done already. */ -static int load_module(struct load_info *info, const char __user *uargs, - int flags) +static int _load_module(struct load_info *info, const char __user *uargs, + int flags) { struct module *mod; bool module_allocated = false; long err = 0; char *after_dashes; - /* - * Do the signature check (if any) first. All that - * the signature check needs is info->len, it does - * not need any of the section info. That can be - * set up later. This will minimize the chances - * of a corrupt module causing problems before - * we even get to the signature check. - * - * The check will also adjust info->len by stripping - * off the sig length at the end of the module, making - * checks against info->len more correct. - */ - err = module_sig_check(info, flags); - if (err) - goto free_copy; - /* * Do basic sanity checks against the ELF header and * sections. Cache useful sections and set the @@ -3405,7 +3395,8 @@ static int load_module(struct load_info *info, const char __user *uargs, * We are tainting your kernel if your module gets into * the modules linked list somehow. */ - module_augment_kernel_taints(mod, info); + if (!(flags & MODULE_INIT_MEM)) + module_augment_kernel_taints(mod, info); /* To avoid stressing percpu allocator, do this once we're unique. */ err = percpu_modalloc(mod, info); @@ -3452,7 +3443,11 @@ static int load_module(struct load_info *info, const char __user *uargs, flush_module_icache(mod); /* Now copy in args */ - mod->args = strndup_user(uargs, ~0UL >> 1); + if ((flags & MODULE_INIT_MEM)) + mod->args = kstrdup("", GFP_KERNEL); + else + mod->args = strndup_user(uargs, ~0UL >> 1); + if (IS_ERR(mod->args)) { err = PTR_ERR(mod->args); goto free_arch_cleanup; @@ -3500,13 +3495,10 @@ static int load_module(struct load_info *info, const char __user *uargs, if (codetag_load_module(mod)) goto sysfs_cleanup; - /* Get rid of temporary copy. */ - free_copy(info, flags); - /* Done! */ trace_module_load(mod); - return do_init_module(mod); + return do_init_module(mod, flags); sysfs_cleanup: mod_sysfs_teardown(mod); @@ -3562,7 +3554,52 @@ static int load_module(struct load_info *info, const char __user *uargs, audit_log_kern_module(info->name ? info->name : "?"); mod_stat_bump_becoming(info, flags); } + return err; +} + +/* + * Load module from kernel memory without signature check. + */ +int load_module_mem(const char *mem, size_t size) +{ + int err; + struct load_info info = { }; + + info.sig_ok = true; + info.hdr = (Elf64_Ehdr *) mem; + info.len = size; + + err = _load_module(&info, NULL, MODULE_INIT_MEM); + if (0) + free_copy(&info, 0); + + return err; +} + +static int load_module(struct load_info *info, const char __user *uargs, + int flags) +{ + int err; + + /* + * Do the signature check (if any) first. All that + * the signature check needs is info->len, it does + * not need any of the section info. That can be + * set up later. This will minimize the chances + * of a corrupt module causing problems before + * we even get to the signature check. + * + * The check will also adjust info->len by stripping + * off the sig length at the end of the module, making + * checks against info->len more correct. + */ + err = module_sig_check(info, flags); + if (!err) + err = _load_module(info, uargs, flags); + + /* Get rid of temporary copy. */ free_copy(info, flags); + return err; } @@ -3728,6 +3765,10 @@ SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags) pr_debug("finit_module: fd=%d, uargs=%p, flags=%i\n", fd, uargs, flags); + /* + * Deliberately omitting MODULE_INIT_MEM as it is for internal use + * only. + */ if (flags & ~(MODULE_INIT_IGNORE_MODVERSIONS |MODULE_INIT_IGNORE_VERMAGIC |MODULE_INIT_COMPRESSED_FILE)) -- 2.39.3