linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH RFC] Restrictions on module loading
@ 2010-11-08  1:23 Dan Rosenberg
  2010-11-08  5:14 ` Kees Cook
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Dan Rosenberg @ 2010-11-08  1:23 UTC (permalink / raw)
  To: linux-kernel; +Cc: security

A significant portion of kernel vulnerabilities do not affect core code,
but rather individual modules.  Unfortunately, there is no global kernel
setting to restrict unprivileged users from triggering the automatic
loading of kernel modules, for example by creating a socket using a
packet family that is compiled as a module and not already loaded.  On
most distributions, this creates a significant attack surface, and
requires maintenance of blacklists and other inelegant solutions to a
general problem.

The below patch replaces the existing "modules_disable" sysctl with a
finer-grained "modules_restrict" sysctl.  By default, this is set at 0,
which results in no deviation from normal module loading behavior.  When
set to 1, unprivileged users cannot trigger the automatic loading of
modules.  This behavior is based on grsecurity's GRKERNSEC_MODHARDEN
setting.  The current check is against current_uid(), since several
distributions explicitly remove CAP_SYS_MODULE from root processes, some
of which incidentally cause (and rely on) the automatic loading of
modules.  I expect this to be a point of discussion.

When set to 2, modules may not be loaded or unloaded by anyone, and the
sysctl may not be changed from that point forward.  This is designed to
provide protection against kernel module rootkits.

Signed-off-by: Dan Rosenberg <drosenberg@vsecurity.com>
---
 Documentation/sysctl/kernel.txt |   16 +++++++++-------
 include/linux/module.h          |    5 ++++-
 kernel/kmod.c                   |    4 ++++
 kernel/module.c                 |   21 ++++++++++++++++++---
 kernel/sysctl.c                 |   11 +++++------
 5 files changed, 40 insertions(+), 17 deletions(-)

diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index 3894eaa..e000214 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -36,7 +36,7 @@ show up in /proc/sys/kernel:
 - kstack_depth_to_print       [ X86 only ]
 - l2cr                        [ PPC only ]
 - modprobe                    ==> Documentation/debugging-modules.txt
-- modules_disabled
+- modules_restrict
 - msgmax
 - msgmnb
 - msgmni
@@ -254,13 +254,15 @@ kernel stack.
 
 ==============================================================
 
-modules_disabled:
+modules_restrict:
 
-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.
+A value indicating if module loading is restricted in an 
+otherwise modular kernel.  This value defaults to off (0), 
+but can be set to (1) or (2).  If set to (1), modules cannot 
+be auto-loaded by non-root users, for example by creating a 
+socket using a packet family that is compiled as a module and 
+not already loaded.  If set to (2), modules can neither be 
+loaded nor unloaded, and the value can no longer be changed.
 
 ==============================================================
 
diff --git a/include/linux/module.h b/include/linux/module.h
index b29e745..869039a 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -175,7 +175,10 @@ struct notifier_block;
 
 #ifdef CONFIG_MODULES
 
-extern int modules_disabled; /* for sysctl */
+int module_proc_update_handler(struct ctl_table *table, int write,
+	void __user *buffer, size_t *length, loff_t *ppos);
+
+extern int modules_restrict; /* for sysctl */
 /* Get/put a kernel symbol (calls must be symmetric) */
 void *__symbol_get(const char *symbol);
 void *__symbol_get_gpl(const char *symbol);
diff --git a/kernel/kmod.c b/kernel/kmod.c
index 9cd0591..e2ab82b 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -90,6 +90,10 @@ int __request_module(bool wait, const char *fmt, ...)
 	if (ret)
 		return ret;
 
+	/* Can non-root users cause auto-loading of modules? */
+	if (current_uid() && modules_restrict)
+		return -EPERM;
+
 	/* If modprobe needs a service that is in a module, we get a recursive
 	 * loop.  Limit the number of running kmod threads to max_threads/2 or
 	 * MAX_KMOD_CONCURRENT, whichever is the smaller.  A cleaner method
diff --git a/kernel/module.c b/kernel/module.c
index 437a74a..cdc5c8c 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -56,6 +56,7 @@
 #include <linux/percpu.h>
 #include <linux/kmemleak.h>
 #include <linux/jump_label.h>
+#include <linux/sysctl.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/module.h>
@@ -88,7 +89,7 @@ struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */
 
 
 /* Block module loading/unloading? */
-int modules_disabled = 0;
+int modules_restrict = 0;
 
 /* Waiting for a module to finish initializing? */
 static DECLARE_WAIT_QUEUE_HEAD(module_wq);
@@ -125,6 +126,20 @@ struct load_info {
 	} index;
 };
 
+/* Proc update handler for modules_restrict sysctl */
+int module_proc_update_handler(struct ctl_table *table, int write,
+	void __user *buffer, size_t *length, loff_t *ppos)
+{
+
+	/* If module loading is entirely disabled, do not allow
+	 * it to be re-enabled. */
+	if (modules_restrict == 2)
+		return -EPERM;
+
+	return proc_dointvec_minmax(table, write, buffer, length, ppos);
+
+}
+
 /* We require a truly strong try_module_get(): 0 means failure due to
    ongoing or failed initialization etc. */
 static inline int strong_try_module_get(struct module *mod)
@@ -734,7 +749,7 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
 	char name[MODULE_NAME_LEN];
 	int ret, forced = 0;
 
-	if (!capable(CAP_SYS_MODULE) || modules_disabled)
+	if (!capable(CAP_SYS_MODULE) || (modules_restrict == 2))
 		return -EPERM;
 
 	if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0)
@@ -2699,7 +2714,7 @@ SYSCALL_DEFINE3(init_module, void __user *, umod,
 	int ret = 0;
 
 	/* Must have permission */
-	if (!capable(CAP_SYS_MODULE) || modules_disabled)
+	if (!capable(CAP_SYS_MODULE) || (modules_restrict == 2))
 		return -EPERM;
 
 	/* Do all the hard work */
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index c33a1ed..37b7964 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -552,14 +552,13 @@ static struct ctl_table kern_table[] = {
 		.proc_handler	= proc_dostring,
 	},
 	{
-		.procname	= "modules_disabled",
-		.data		= &modules_disabled,
+		.procname	= "modules_restrict",
+		.data		= &modules_restrict,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		/* only handle a transition from default "0" to "1" */
-		.proc_handler	= proc_dointvec_minmax,
-		.extra1		= &one,
-		.extra2		= &one,
+		.proc_handler	= module_proc_update_handler,
+		.extra1		= &zero,
+		.extra2		= &two,
 	},
 #endif
 #ifdef CONFIG_HOTPLUG



^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH RFC] Restrictions on module loading
  2010-11-08  1:23 [PATCH RFC] Restrictions on module loading Dan Rosenberg
@ 2010-11-08  5:14 ` Kees Cook
  2010-11-08 10:20 ` Alan Cox
  2010-11-09  5:42 ` [Security] " Eugene Teo
  2 siblings, 0 replies; 8+ messages in thread
From: Kees Cook @ 2010-11-08  5:14 UTC (permalink / raw)
  To: Dan Rosenberg; +Cc: linux-kernel, security

On Sun, Nov 07, 2010 at 08:23:59PM -0500, Dan Rosenberg wrote:
> A significant portion of kernel vulnerabilities do not affect core code,
> but rather individual modules.  Unfortunately, there is no global kernel
> setting to restrict unprivileged users from triggering the automatic
> loading of kernel modules, for example by creating a socket using a
> packet family that is compiled as a module and not already loaded.  On
> most distributions, this creates a significant attack surface, and
> requires maintenance of blacklists and other inelegant solutions to a
> general problem.
> 
> The below patch replaces the existing "modules_disable" sysctl with a
> finer-grained "modules_restrict" sysctl.  By default, this is set at 0,
> which results in no deviation from normal module loading behavior.  When
> set to 1, unprivileged users cannot trigger the automatic loading of
> modules.  This behavior is based on grsecurity's GRKERNSEC_MODHARDEN
> setting.  The current check is against current_uid(), since several
> distributions explicitly remove CAP_SYS_MODULE from root processes, some
> of which incidentally cause (and rely on) the automatic loading of
> modules.  I expect this to be a point of discussion.
> 
> When set to 2, modules may not be loaded or unloaded by anyone, and the
> sysctl may not be changed from that point forward.  This is designed to
> provide protection against kernel module rootkits.
> 
> Signed-off-by: Dan Rosenberg <drosenberg@vsecurity.com>

Acked-by: Kees Cook <kees.cook@canonical.com>

This looks great to me. There will be a small amount of pain for people
that are already using modules_disabled=1, but I think the audience is so
small that it won't be a problem to switch to modules_restrict=2.

-Kees

-- 
Kees Cook
Ubuntu Security Team

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH RFC] Restrictions on module loading
  2010-11-08  1:23 [PATCH RFC] Restrictions on module loading Dan Rosenberg
  2010-11-08  5:14 ` Kees Cook
@ 2010-11-08 10:20 ` Alan Cox
  2010-11-08 12:23   ` Dan Rosenberg
  2010-11-09  5:42 ` [Security] " Eugene Teo
  2 siblings, 1 reply; 8+ messages in thread
From: Alan Cox @ 2010-11-08 10:20 UTC (permalink / raw)
  To: Dan Rosenberg; +Cc: linux-kernel, security

> loading of kernel modules, for example by creating a socket using a
> packet family that is compiled as a module and not already loaded.  On
> most distributions, this creates a significant attack surface, and
> requires maintenance of blacklists and other inelegant solutions to a
> general problem.

Those inelegant solutions work rather better in a lot of situations
because most distributions will fall flat on their face if auto loading
isn't active and they are more flexible.

> The below patch replaces the existing "modules_disable" sysctl with a

NAK - Its a long standing ABI.

> When set to 2, modules may not be loaded or unloaded by anyone, and the
> sysctl may not be changed from that point forward.  This is designed to
> provide protection against kernel module rootkits.

I've no objection to modules_restrict although I doubt it'll ever get
used in the real world, but better to extend the meaning of the existing
interface, not remove stuff.

If you have "security" in your address the please think like a security
person - users with security relying upon writing to modules_disable are
*not* going to notice a one line log entry somewhere about unable to open
{filename that doesn't look important}.

So your change is actually *bad* for security in its current form, you
remove the facilities they rely upon.

Alan


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH RFC] Restrictions on module loading
  2010-11-08 10:20 ` Alan Cox
@ 2010-11-08 12:23   ` Dan Rosenberg
  2010-11-08 13:59     ` Alan Cox
  0 siblings, 1 reply; 8+ messages in thread
From: Dan Rosenberg @ 2010-11-08 12:23 UTC (permalink / raw)
  To: Alan Cox; +Cc: linux-kernel, security


> NAK - Its a long standing ABI.

As far as I can tell, modules_disabled was first included in 2.6.31, so
it's hardly what I'd call "long standing".  However, I see your point -
it's definitely not my intention to surprise anyone by changing security
features out from under them.

I do think merging the features makes sense in this case.  I'll rework
this to keep the "modules_disabled" name, where a value of "0" means
default behavior, a value of "1" means no loading or unloading (and no
changing it back), and the new value of "2" incorporates the
restrictions I'm intending to enforce.

> 
> I've no objection to modules_restrict although I doubt it'll ever get
> used in the real world, but better to extend the meaning of the existing
> interface, not remove stuff.
> 

There has been interest in improving the ease with which users can
enforce restrictions on automatic module loading.  No one is being
forced to use it.

-Dan



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH RFC] Restrictions on module loading
  2010-11-08 12:23   ` Dan Rosenberg
@ 2010-11-08 13:59     ` Alan Cox
  0 siblings, 0 replies; 8+ messages in thread
From: Alan Cox @ 2010-11-08 13:59 UTC (permalink / raw)
  To: Dan Rosenberg; +Cc: linux-kernel, security

> As far as I can tell, modules_disabled was first included in 2.6.31, so
> it's hardly what I'd call "long standing".  However, I see your point -

One year, two months, plus shipped in numerous major distributions.
That's long standing in the Linux world.

Alan

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Security] [PATCH RFC] Restrictions on module loading
  2010-11-08  1:23 [PATCH RFC] Restrictions on module loading Dan Rosenberg
  2010-11-08  5:14 ` Kees Cook
  2010-11-08 10:20 ` Alan Cox
@ 2010-11-09  5:42 ` Eugene Teo
  2 siblings, 0 replies; 8+ messages in thread
From: Eugene Teo @ 2010-11-09  5:42 UTC (permalink / raw)
  To: Dan Rosenberg; +Cc: linux-kernel, security

On Mon, Nov 8, 2010 at 9:23 AM, Dan Rosenberg <drosenberg@vsecurity.com> wrote:
[...]
> The below patch replaces the existing "modules_disable" sysctl with a
> finer-grained "modules_restrict" sysctl.  By default, this is set at 0,

I suggest that we either keep the existing "modules_disable" sysctl
variable and build on top of it, or use another sysctl variable.

Thanks, Eugene

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH RFC] Restrictions on module loading
  2010-11-08  8:30 ` Bodo Eggert
@ 2010-11-08 11:34   ` Andi Kleen
  0 siblings, 0 replies; 8+ messages in thread
From: Andi Kleen @ 2010-11-08 11:34 UTC (permalink / raw)
  To: 7eggert; +Cc: Dan Rosenberg, security, linux-kernel

Bodo Eggert <7eggert@web.de> writes:
>
> - What about task switches or work queues?

That's indeed a problem. All request_module()s would need auditing
and if there's any triggered from a workqueue a new interface
that passes the credentials around.

-Andi
-- 
ak@linux.intel.com -- Speaking for myself only.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH RFC] Restrictions on module loading
       [not found] <fMoIy-7gR-5@gated-at.bofh.it>
@ 2010-11-08  8:30 ` Bodo Eggert
  2010-11-08 11:34   ` Andi Kleen
  0 siblings, 1 reply; 8+ messages in thread
From: Bodo Eggert @ 2010-11-08  8:30 UTC (permalink / raw)
  To: Dan Rosenberg, security, linux-kernel

Dan Rosenberg <drosenberg@vsecurity.com> wrote:

> The below patch replaces the existing "modules_disable" sysctl with a
> finer-grained "modules_restrict" sysctl.  By default, this is set at 0,
> which results in no deviation from normal module loading behavior.  When
> set to 1, unprivileged users cannot trigger the automatic loading of
> modules.  This behavior is based on grsecurity's GRKERNSEC_MODHARDEN
> setting.  The current check is against current_uid(), since several
> distributions explicitly remove CAP_SYS_MODULE from root processes, some
> of which incidentally cause (and rely on) the automatic loading of
> modules.  I expect this to be a point of discussion.

- Why don't you offer both?

- What about task switches or work queues?

- It might be more like the expected behavior if you'd used:
 0: off, 1: modules completely disabled, 2: CAP_SYS_MODULE, 3: uid==0

 Many users will forget to look into the documentation or find the current,
 stale documentation or just assume a boolean value.


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2010-11-09  5:43 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-11-08  1:23 [PATCH RFC] Restrictions on module loading Dan Rosenberg
2010-11-08  5:14 ` Kees Cook
2010-11-08 10:20 ` Alan Cox
2010-11-08 12:23   ` Dan Rosenberg
2010-11-08 13:59     ` Alan Cox
2010-11-09  5:42 ` [Security] " Eugene Teo
     [not found] <fMoIy-7gR-5@gated-at.bofh.it>
2010-11-08  8:30 ` Bodo Eggert
2010-11-08 11:34   ` Andi Kleen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).