Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Harden module auto-loading #23

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Documentation/admin-guide/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2902,6 +2902,10 @@
log everything. Information is printed at KERN_DEBUG
so loglevel=8 may also need to be specified.

modharden= [SECURITY]
on - Restrict module auto-loading to CAP_SYS_MODULE
off - Don't restrict module auto-loading

module.sig_enforce
[KNL] When CONFIG_MODULE_SIG is set, this means that
modules without (valid) signatures will fail to load.
Expand Down
18 changes: 16 additions & 2 deletions Documentation/admin-guide/sysctl/kernel.rst
Original file line number Diff line number Diff line change
Expand Up @@ -510,8 +510,22 @@ then the configured static usermode helper overrides this sysctl,
except that the empty string is still accepted to completely disable
module autoloading as described above.

modules_disabled
================
modharden:
==========

This toggle indicates whether unprivileged users are allowed to
auto-load kernel modules.

When modharden is set to (0) there are no restrictions. When
modharden is set to (1), only users with ``CAP_SYS_MODULE`` are
permitted to load kernel modules

The kernel config option ``CONFIG_SECURITY_MODHARDEN`` sets the
default value of modharden.


modules_disabled:
=================

A toggle value indicating if modules are allowed to be loaded
in an otherwise modular kernel. This toggle defaults to off
Expand Down
1 change: 1 addition & 0 deletions include/linux/kmod.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ extern char modprobe_path[]; /* for sysctl */
* usually useless though. */
extern __printf(2, 3)
int __request_module(bool wait, const char *name, ...);
extern int modharden;
#define request_module(mod...) __request_module(true, mod)
#define request_module_nowait(mod...) __request_module(false, mod)
#define try_then_request_module(x, mod...) \
Expand Down
24 changes: 24 additions & 0 deletions kernel/kmod.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,25 @@ static int call_modprobe(char *module_name, int wait)
return -ENOMEM;
}

int modharden __read_mostly = IS_ENABLED(CONFIG_SECURITY_MODHARDEN);


static int __init enable_modharden(char *level)
{
if (!level)
return -EINVAL;

if (strcmp(level, "on") == 0)
modharden = 1;
else if (strcmp(level, "off") == 0)
modharden = 0;
else
return -EINVAL;

return 0;
}
early_param("modharden", enable_modharden);

/**
* __request_module - try to load a kernel module
* @wait: wait (or not) for the operation to complete
Expand Down Expand Up @@ -148,6 +167,11 @@ int __request_module(bool wait, const char *fmt, ...)
if (ret)
return ret;

if (modharden && !capable(CAP_SYS_MODULE)) {
printk(KERN_ALERT "denied attempt to auto-load module %s\n", module_name);
return -EPERM;
}

if (atomic_dec_if_positive(&kmod_concurrent_max) < 0) {
pr_warn_ratelimited("request_module: kmod_concurrent_max (%u) close to 0 (max_modprobes: %u), for module %s, throttling...",
atomic_read(&kmod_concurrent_max),
Expand Down
9 changes: 9 additions & 0 deletions kernel/sysctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -2111,6 +2111,15 @@ static struct ctl_table kern_table[] = {
.extra1 = SYSCTL_ONE,
.extra2 = SYSCTL_ONE,
},
{
.procname = "modharden",
.data = &modharden,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
.extra1 = SYSCTL_ZERO,
.extra2 = SYSCTL_ONE,
},
#endif
#ifdef CONFIG_UEVENT_HELPER
{
Expand Down
22 changes: 22 additions & 0 deletions security/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,28 @@ config SECURITY_TIOCSTI_RESTRICT

If you are unsure how to answer this question, answer N.

config SECURITY_MODHARDEN
bool "Harden module auto-loading"
default n
depends on MODULES
help
If you say Y here, module auto-loading in response to use of some
feature implemented by an unloaded module will be restricted to
CAP_SYS_MODULE. Enabling this option helps defend against attacks
by unprivileged users who abuse the auto-loading behavior to
cause a vulnerable module to load that is then exploited.

If this option prevents a legitimate use of auto-loading for a
non-root user, the administrator can execute modprobe manually
with the exact name of the module mentioned in the alert log.
Alternatively, the administrator can add the module to the list
of modules loaded at boot by modifying init scripts.

This setting can be overridden at runtime via the
kernel.modharden sysctl.

If unsure say N.

madaidan marked this conversation as resolved.
Show resolved Hide resolved
config SECURITY
bool "Enable different security models"
depends on SYSFS
Expand Down