Skip to content

Commit

Permalink
module: add flags arg to sys_finit_module()
Browse files Browse the repository at this point in the history
Thanks to Michael Kerrisk for keeping us honest.  These flags are actually
useful for eliminating the only case where kmod has to mangle a module's
internals: for overriding module versioning.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Acked-by: Lucas De Marchi <lucas.demarchi@profusion.mobi>
Acked-by: Kees Cook <keescook@chromium.org>
  • Loading branch information
Rusty Russell committed Dec 14, 2012
1 parent 34e1169 commit 2f3238a
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 15 deletions.
2 changes: 1 addition & 1 deletion include/linux/syscalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -868,5 +868,5 @@ asmlinkage long sys_process_vm_writev(pid_t pid,

asmlinkage long sys_kcmp(pid_t pid1, pid_t pid2, int type,
unsigned long idx1, unsigned long idx2);
asmlinkage long sys_finit_module(int fd, const char __user *uargs);
asmlinkage long sys_finit_module(int fd, const char __user *uargs, int flags);
#endif
8 changes: 8 additions & 0 deletions include/uapi/linux/module.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef _UAPI_LINUX_MODULE_H
#define _UAPI_LINUX_MODULE_H

/* Flags for sys_finit_module: */
#define MODULE_INIT_IGNORE_MODVERSIONS 1
#define MODULE_INIT_IGNORE_VERMAGIC 2

#endif /* _UAPI_LINUX_MODULE_H */
40 changes: 26 additions & 14 deletions kernel/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
#include <linux/pfn.h>
#include <linux/bsearch.h>
#include <linux/fips.h>
#include <uapi/linux/module.h>
#include "module-internal.h"

#define CREATE_TRACE_POINTS
Expand Down Expand Up @@ -2553,7 +2554,7 @@ static void free_copy(struct load_info *info)
vfree(info->hdr);
}

static int rewrite_section_headers(struct load_info *info)
static int rewrite_section_headers(struct load_info *info, int flags)
{
unsigned int i;

Expand Down Expand Up @@ -2581,7 +2582,10 @@ static int rewrite_section_headers(struct load_info *info)
}

/* Track but don't keep modinfo and version sections. */
info->index.vers = find_sec(info, "__versions");
if (flags & MODULE_INIT_IGNORE_MODVERSIONS)
info->index.vers = 0; /* Pretend no __versions section! */
else
info->index.vers = find_sec(info, "__versions");
info->index.info = find_sec(info, ".modinfo");
info->sechdrs[info->index.info].sh_flags &= ~(unsigned long)SHF_ALLOC;
info->sechdrs[info->index.vers].sh_flags &= ~(unsigned long)SHF_ALLOC;
Expand All @@ -2596,7 +2600,7 @@ static int rewrite_section_headers(struct load_info *info)
* Return the temporary module pointer (we'll replace it with the final
* one when we move the module sections around).
*/
static struct module *setup_load_info(struct load_info *info)
static struct module *setup_load_info(struct load_info *info, int flags)
{
unsigned int i;
int err;
Expand All @@ -2607,7 +2611,7 @@ static struct module *setup_load_info(struct load_info *info)
info->secstrings = (void *)info->hdr
+ info->sechdrs[info->hdr->e_shstrndx].sh_offset;

err = rewrite_section_headers(info);
err = rewrite_section_headers(info, flags);
if (err)
return ERR_PTR(err);

Expand Down Expand Up @@ -2645,11 +2649,14 @@ static struct module *setup_load_info(struct load_info *info)
return mod;
}

static int check_modinfo(struct module *mod, struct load_info *info)
static int check_modinfo(struct module *mod, struct load_info *info, int flags)
{
const char *modmagic = get_modinfo(info, "vermagic");
int err;

if (flags & MODULE_INIT_IGNORE_VERMAGIC)
modmagic = NULL;

/* This is allowed: modprobe --force will invalidate it. */
if (!modmagic) {
err = try_to_force_load(mod, "bad vermagic");
Expand Down Expand Up @@ -2885,18 +2892,18 @@ int __weak module_frob_arch_sections(Elf_Ehdr *hdr,
return 0;
}

static struct module *layout_and_allocate(struct load_info *info)
static struct module *layout_and_allocate(struct load_info *info, int flags)
{
/* Module within temporary copy. */
struct module *mod;
Elf_Shdr *pcpusec;
int err;

mod = setup_load_info(info);
mod = setup_load_info(info, flags);
if (IS_ERR(mod))
return mod;

err = check_modinfo(mod, info);
err = check_modinfo(mod, info, flags);
if (err)
return ERR_PTR(err);

Expand Down Expand Up @@ -3078,7 +3085,8 @@ static int may_init_module(void)

/* Allocate and load the module: note that size of section 0 is always
zero, and we rely on this for optional sections. */
static int load_module(struct load_info *info, const char __user *uargs)
static int load_module(struct load_info *info, const char __user *uargs,
int flags)
{
struct module *mod, *old;
long err;
Expand All @@ -3092,7 +3100,7 @@ static int load_module(struct load_info *info, const char __user *uargs)
goto free_copy;

/* Figure out module layout, and allocate all the memory. */
mod = layout_and_allocate(info);
mod = layout_and_allocate(info, flags);
if (IS_ERR(mod)) {
err = PTR_ERR(mod);
goto free_copy;
Expand Down Expand Up @@ -3241,10 +3249,10 @@ SYSCALL_DEFINE3(init_module, void __user *, umod,
if (err)
return err;

return load_module(&info, uargs);
return load_module(&info, uargs, 0);
}

SYSCALL_DEFINE2(finit_module, int, fd, const char __user *, uargs)
SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags)
{
int err;
struct load_info info = { };
Expand All @@ -3253,13 +3261,17 @@ SYSCALL_DEFINE2(finit_module, int, fd, const char __user *, uargs)
if (err)
return err;

pr_debug("finit_module: fd=%d, uargs=%p\n", fd, uargs);
pr_debug("finit_module: fd=%d, uargs=%p, flags=%i\n", fd, uargs, flags);

if (flags & ~(MODULE_INIT_IGNORE_MODVERSIONS
|MODULE_INIT_IGNORE_VERMAGIC))
return -EINVAL;

err = copy_module_from_fd(fd, &info);
if (err)
return err;

return load_module(&info, uargs);
return load_module(&info, uargs, flags);
}

static inline int within(unsigned long addr, void *start, unsigned long size)
Expand Down

0 comments on commit 2f3238a

Please sign in to comment.