Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3d43321b authored by Kees Cook's avatar Kees Cook Committed by James Morris
Browse files

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: default avatarKees Cook <kees.cook@canonical.com>
Acked-by: default avatarSerge Hallyn <serue@us.ibm.com>
Signed-off-by: default avatarJames Morris <jmorris@namei.org>
parent 8a6f83af
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -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
+5 −2
Original line number Diff line number Diff line
@@ -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 */
+12 −0
Original line number Diff line number Diff line
@@ -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)
	{