summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKees Cook <kees@ubuntu.com>2009-04-02 15:49:29 -0700
committerJames Morris <jmorris@namei.org>2009-04-03 11:47:11 +1100
commit3d43321b7015387cfebbe26436d0e9d299162ea1 (patch)
treebae6bd123c8f573e844a7af11c96eb5f6a73e0ee
parent8a6f83afd0c5355db6d11394a798e94950306239 (diff)
modules: sysctl to block module loading
Implement a sysctl file that disables module-loading system-wide since there is no longer a viable way to remove CAP_SYS_MODULE after the system bounding capability set was removed in 2.6.25. Value can only be set to "1", and is tested only if standard capability checks allow CAP_SYS_MODULE. Given existing /dev/mem protections, this should allow administrators a one-way method to block module loading after initial boot-time module loading has finished. Signed-off-by: Kees Cook <kees.cook@canonical.com> Acked-by: Serge Hallyn <serue@us.ibm.com> Signed-off-by: James Morris <jmorris@namei.org>
-rw-r--r--Documentation/sysctl/kernel.txt11
-rw-r--r--kernel/module.c7
-rw-r--r--kernel/sysctl.c12
3 files changed, 28 insertions, 2 deletions
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index a4ccdd1981c..02b13495627 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -30,6 +30,7 @@ show up in /proc/sys/kernel:
- kstack_depth_to_print [ X86 only ]
- l2cr [ PPC only ]
- modprobe ==> Documentation/debugging-modules.txt
+- modules_disabled
- msgmax
- msgmnb
- msgmni
@@ -179,6 +180,16 @@ kernel stack.
==============================================================
+modules_disabled:
+
+A toggle value indicating if modules are allowed to be loaded
+in an otherwise modular kernel. This toggle defaults to off
+(0), but can be set true (1). Once true, modules can be
+neither loaded nor unloaded, and the toggle cannot be set back
+to false.
+
+==============================================================
+
osrelease, ostype & version:
# cat osrelease
diff --git a/kernel/module.c b/kernel/module.c
index f77ac320d0b..eeb3f7b1383 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -778,6 +778,9 @@ static void wait_for_zero_refcount(struct module *mod)
mutex_lock(&module_mutex);
}
+/* Block module loading/unloading? */
+int modules_disabled = 0;
+
SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
unsigned int, flags)
{
@@ -785,7 +788,7 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
char name[MODULE_NAME_LEN];
int ret, forced = 0;
- if (!capable(CAP_SYS_MODULE))
+ if (!capable(CAP_SYS_MODULE) || modules_disabled)
return -EPERM;
if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0)
@@ -2349,7 +2352,7 @@ SYSCALL_DEFINE3(init_module, void __user *, umod,
int ret = 0;
/* Must have permission */
- if (!capable(CAP_SYS_MODULE))
+ if (!capable(CAP_SYS_MODULE) || modules_disabled)
return -EPERM;
/* Only one module load at a time, please */
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index c5ef44ff850..2fb4246d27d 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -113,6 +113,7 @@ static int ngroups_max = NGROUPS_MAX;
#ifdef CONFIG_MODULES
extern char modprobe_path[];
+extern int modules_disabled;
#endif
#ifdef CONFIG_CHR_DEV_SG
extern int sg_big_buff;
@@ -533,6 +534,17 @@ static struct ctl_table kern_table[] = {
.proc_handler = &proc_dostring,
.strategy = &sysctl_string,
},
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "modules_disabled",
+ .data = &modules_disabled,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ /* only handle a transition from default "0" to "1" */
+ .proc_handler = &proc_dointvec_minmax,
+ .extra1 = &one,
+ .extra2 = &one,
+ },
#endif
#if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET)
{