Skip to content

Commit

Permalink
Harden module auto-loading
Browse files Browse the repository at this point in the history
This is modified from Brad Spengler/PaX Team's code in the last
public patch of grsecurity/PaX based on my understanding of the code. Changes
or omissions from the original code are mine and don't reflect the original
grsecurity/PaX code.

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.
  • Loading branch information
madaidan committed Jan 5, 2020
1 parent 0135feb commit df807e0
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 0 deletions.
15 changes: 15 additions & 0 deletions Documentation/admin-guide/sysctl/kernel.rst
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ show up in /proc/sys/kernel:
- kexec_load_disabled
- kptr_restrict
- l2cr [ PPC only ]
- modharden
- modprobe ==> Documentation/debugging-modules.txt
- modules_disabled
- msg_next_id [ sysv ipc ]
Expand Down Expand Up @@ -446,6 +447,20 @@ This flag controls the L2 cache of G3 processor boards. If
0, the cache is disabled. Enabled if nonzero.


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:
=================

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
7 changes: 7 additions & 0 deletions kernel/kmod.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ static int call_modprobe(char *module_name, int wait)
return -ENOMEM;
}

int modharden = IS_ENABLED(CONFIG_SECURITY_MODHARDEN);

/**
* __request_module - try to load a kernel module
* @wait: wait (or not) for the operation to complete
Expand Down Expand Up @@ -149,6 +151,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 @@ -736,6 +736,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 y
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.

Modification of init scripts will most likely be needed on
Ubuntu servers with encrypted home directory support enabled,
as the first non-root user logging in will cause the ecb(aes),
ecb(aes)-all, cbc(aes), and cbc(aes)-all modules to be loaded.

config SECURITY
bool "Enable different security models"
depends on SYSFS
Expand Down

0 comments on commit df807e0

Please sign in to comment.