Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 334304
b: refs/heads/master
c: 106a4ee
h: refs/heads/master
v: v3
  • Loading branch information
Rusty Russell committed Oct 10, 2012
1 parent 863e255 commit 7221692
Show file tree
Hide file tree
Showing 8 changed files with 158 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c26fd69fa00916a31a47f5f096fd7be924106df8
refs/heads/master: 106a4ee258d14818467829bf0e12aeae14c16cd7
6 changes: 6 additions & 0 deletions trunk/Documentation/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1582,6 +1582,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
log everything. Information is printed at KERN_DEBUG
so loglevel=8 may also need to be specified.

module.sig_enforce
[KNL] When CONFIG_MODULE_SIG is set, this means that
modules without (valid) signatures will fail to load.
Note that if CONFIG_MODULE_SIG_ENFORCE is set, that
is always true, so this option does nothing.

mousedev.tap_time=
[MOUSE] Maximum time between finger touching and
leaving touchpad surface for touch to be considered
Expand Down
8 changes: 8 additions & 0 deletions trunk/include/linux/module.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
#include <linux/percpu.h>
#include <asm/module.h>

/* In stripped ARM and x86-64 modules, ~ is surprisingly rare. */
#define MODULE_SIG_STRING "~Module signature appended~\n"

/* Not Yet Implemented */
#define MODULE_SUPPORTED_DEVICE(name)

Expand Down Expand Up @@ -260,6 +263,11 @@ struct module
const unsigned long *unused_gpl_crcs;
#endif

#ifdef CONFIG_MODULE_SIG
/* Signature was verified. */
bool sig_ok;
#endif

/* symbols that will be GPL-only in the near future. */
const struct kernel_symbol *gpl_future_syms;
const unsigned long *gpl_future_crcs;
Expand Down
14 changes: 14 additions & 0 deletions trunk/init/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1585,6 +1585,20 @@ config MODULE_SRCVERSION_ALL
the version). With this option, such a "srcversion" field
will be created for all modules. If unsure, say N.

config MODULE_SIG
bool "Module signature verification"
depends on MODULES
help
Check modules for valid signatures upon load: the signature
is simply appended to the module. For more information see
Documentation/module-signing.txt.

config MODULE_SIG_FORCE
bool "Require modules to be validly signed"
depends on MODULE_SIG
help
Reject unsigned modules or signed modules for which we don't have a
key. Without this, such modules will simply taint the kernel.
endif # MODULES

config INIT_ALL_POSSIBLE
Expand Down
1 change: 1 addition & 0 deletions trunk/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o
obj-$(CONFIG_PROVE_LOCKING) += spinlock.o
obj-$(CONFIG_UID16) += uid16.o
obj-$(CONFIG_MODULES) += module.o
obj-$(CONFIG_MODULE_SIG) += module_signing.o
obj-$(CONFIG_KALLSYMS) += kallsyms.o
obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
obj-$(CONFIG_KEXEC) += kexec.o
Expand Down
13 changes: 13 additions & 0 deletions trunk/kernel/module-internal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/* Module internals
*
* Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public Licence
* as published by the Free Software Foundation; either version
* 2 of the Licence, or (at your option) any later version.
*/

extern int mod_verify_sig(const void *mod, unsigned long modlen,
const void *sig, unsigned long siglen);
93 changes: 92 additions & 1 deletion trunk/kernel/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
#include <linux/jump_label.h>
#include <linux/pfn.h>
#include <linux/bsearch.h>
#include "module-internal.h"

#define CREATE_TRACE_POINTS
#include <trace/events/module.h>
Expand Down Expand Up @@ -102,6 +103,43 @@ static LIST_HEAD(modules);
struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */
#endif /* CONFIG_KGDB_KDB */

#ifdef CONFIG_MODULE_SIG
#ifdef CONFIG_MODULE_SIG_FORCE
static bool sig_enforce = true;
#else
static bool sig_enforce = false;

static int param_set_bool_enable_only(const char *val,
const struct kernel_param *kp)
{
int err;
bool test;
struct kernel_param dummy_kp = *kp;

dummy_kp.arg = &test;

err = param_set_bool(val, &dummy_kp);
if (err)
return err;

/* Don't let them unset it once it's set! */
if (!test && sig_enforce)
return -EROFS;

if (test)
sig_enforce = true;
return 0;
}

static const struct kernel_param_ops param_ops_bool_enable_only = {
.set = param_set_bool_enable_only,
.get = param_get_bool,
};
#define param_check_bool_enable_only param_check_bool

module_param(sig_enforce, bool_enable_only, 0644);
#endif /* !CONFIG_MODULE_SIG_FORCE */
#endif /* CONFIG_MODULE_SIG */

/* Block module loading/unloading? */
int modules_disabled = 0;
Expand Down Expand Up @@ -136,6 +174,7 @@ struct load_info {
unsigned long symoffs, stroffs;
struct _ddebug *debug;
unsigned int num_debug;
bool sig_ok;
struct {
unsigned int sym, str, mod, vers, info, pcpu;
} index;
Expand Down Expand Up @@ -2379,7 +2418,49 @@ static inline void kmemleak_load_module(const struct module *mod,
}
#endif

/* Sets info->hdr and info->len. */
#ifdef CONFIG_MODULE_SIG
static int module_sig_check(struct load_info *info,
const void *mod, unsigned long *len)
{
int err = -ENOKEY;
const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;
const void *p = mod, *end = mod + *len;

/* Poor man's memmem. */
while ((p = memchr(p, MODULE_SIG_STRING[0], end - p))) {
if (p + markerlen > end)
break;

if (memcmp(p, MODULE_SIG_STRING, markerlen) == 0) {
const void *sig = p + markerlen;
/* Truncate module up to signature. */
*len = p - mod;
err = mod_verify_sig(mod, *len, sig, end - sig);
break;
}
p++;
}

if (!err) {
info->sig_ok = true;
return 0;
}

/* Not having a signature is only an error if we're strict. */
if (err == -ENOKEY && !sig_enforce)
err = 0;

return err;
}
#else /* !CONFIG_MODULE_SIG */
static int module_sig_check(struct load_info *info,
void *mod, unsigned long *len)
{
return 0;
}
#endif /* !CONFIG_MODULE_SIG */

/* Sets info->hdr, info->len and info->sig_ok. */
static int copy_and_check(struct load_info *info,
const void __user *umod, unsigned long len,
const char __user *uargs)
Expand All @@ -2399,6 +2480,10 @@ static int copy_and_check(struct load_info *info,
goto free_hdr;
}

err = module_sig_check(info, hdr, &len);
if (err)
goto free_hdr;

/* Sanity checks against insmoding binaries or wrong arch,
weird elf version */
if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0
Expand Down Expand Up @@ -2884,6 +2969,12 @@ static struct module *load_module(void __user *umod,
goto free_copy;
}

#ifdef CONFIG_MODULE_SIG
mod->sig_ok = info.sig_ok;
if (!mod->sig_ok)
add_taint_module(mod, TAINT_FORCED_MODULE);
#endif

/* Now module is in final location, initialize linked lists, etc. */
err = module_unload_init(mod);
if (err)
Expand Down
23 changes: 23 additions & 0 deletions trunk/kernel/module_signing.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/* Module signature checker
*
* Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public Licence
* as published by the Free Software Foundation; either version
* 2 of the Licence, or (at your option) any later version.
*/

#include <linux/kernel.h>
#include <linux/err.h>
#include "module-internal.h"

/*
* Verify the signature on a module.
*/
int mod_verify_sig(const void *mod, unsigned long modlen,
const void *sig, unsigned long siglen)
{
return -ENOKEY;
}

0 comments on commit 7221692

Please sign in to comment.