Re: [PATCH v5 next 3/5] modules:capabilities: automatic module loading restriction
On Thu, Nov 30, 2017 at 2:23 AM, Luis R. Rodriguez wrote: > On Mon, Nov 27, 2017 at 06:18:36PM +0100, Djalal Harouni wrote: >> diff --git a/include/linux/module.h b/include/linux/module.h >> index 5cbb239..c36aed8 100644 >> --- a/include/linux/module.h >> +++ b/include/linux/module.h >> @@ -261,7 +261,16 @@ struct notifier_block; >> >> #ifdef CONFIG_MODULES >> >> -extern int modules_disabled; /* for sysctl */ >> +enum { >> + MODULES_AUTOLOAD_ALLOWED= 0, >> + MODULES_AUTOLOAD_PRIVILEGED = 1, >> + MODULES_AUTOLOAD_DISABLED = 2, >> +}; >> + > > Can you kdocify these and add a respective rst doc file? Maybe stuff your > extensive docs which you are currently adding to > Documentation/sysctl/kernel.txt to this new file and in kernel.txt just refer > to it. This way this can be also nicely visibly documented on the web with the > new sphinx. > > This way you can take advantage of the kdocs you are already adding and refer > to them. Alright I'll do it in the next series next week, we'll change the semantics as requested by Linus and Kees here: http://www.openwall.com/lists/kernel-hardening/2017/11/29/38 To block the privilege escalation through the usermod helper. >> diff --git a/kernel/sysctl.c b/kernel/sysctl.c >> index 2fb4e27..0b6f0c8 100644 >> --- a/kernel/sysctl.c >> +++ b/kernel/sysctl.c >> @@ -683,6 +688,15 @@ static struct ctl_table kern_table[] = { >> .extra1 = &one, >> .extra2 = &one, >> }, >> + { >> + .procname = "modules_autoload_mode", >> + .data = &modules_autoload_mode, >> + .maxlen = sizeof(int), >> + .mode = 0644, >> + .proc_handler = modules_autoload_dointvec_minmax, > > It would seem this is a unint ... so why not reflect that? > >> @@ -2499,6 +2513,20 @@ static int proc_dointvec_minmax_sysadmin(struct >> ctl_table *table, int write, >> } >> #endif >> >> +#ifdef CONFIG_MODULES >> +static int modules_autoload_dointvec_minmax(struct ctl_table *table, int >> write, >> + void __user *buffer, size_t *lenp, loff_t >> *ppos) >> +{ >> + /* >> + * Only CAP_SYS_MODULE in init user namespace are allowed to change >> this >> + */ >> + if (write && !capable(CAP_SYS_MODULE)) >> + return -EPERM; >> + >> + return proc_dointvec_minmax(table, write, buffer, lenp, ppos); >> +} >> +#endif > > We now have proc_douintvec_minmax(). > Yes, however in that same response by Linus it was suggested to drop the sysctl completely, so next iterations will not have this code. Thank you for the review! -- tixxdz
Re: [PATCH v5 next 3/5] modules:capabilities: automatic module loading restriction
On Mon, Nov 27, 2017 at 06:18:36PM +0100, Djalal Harouni wrote: > diff --git a/include/linux/module.h b/include/linux/module.h > index 5cbb239..c36aed8 100644 > --- a/include/linux/module.h > +++ b/include/linux/module.h > @@ -261,7 +261,16 @@ struct notifier_block; > > #ifdef CONFIG_MODULES > > -extern int modules_disabled; /* for sysctl */ > +enum { > + MODULES_AUTOLOAD_ALLOWED= 0, > + MODULES_AUTOLOAD_PRIVILEGED = 1, > + MODULES_AUTOLOAD_DISABLED = 2, > +}; > + Can you kdocify these and add a respective rst doc file? Maybe stuff your extensive docs which you are currently adding to Documentation/sysctl/kernel.txt to this new file and in kernel.txt just refer to it. This way this can be also nicely visibly documented on the web with the new sphinx. This way you can take advantage of the kdocs you are already adding and refer to them. > diff --git a/kernel/sysctl.c b/kernel/sysctl.c > index 2fb4e27..0b6f0c8 100644 > --- a/kernel/sysctl.c > +++ b/kernel/sysctl.c > @@ -683,6 +688,15 @@ static struct ctl_table kern_table[] = { > .extra1 = &one, > .extra2 = &one, > }, > + { > + .procname = "modules_autoload_mode", > + .data = &modules_autoload_mode, > + .maxlen = sizeof(int), > + .mode = 0644, > + .proc_handler = modules_autoload_dointvec_minmax, It would seem this is a unint ... so why not reflect that? > @@ -2499,6 +2513,20 @@ static int proc_dointvec_minmax_sysadmin(struct > ctl_table *table, int write, > } > #endif > > +#ifdef CONFIG_MODULES > +static int modules_autoload_dointvec_minmax(struct ctl_table *table, int > write, > + void __user *buffer, size_t *lenp, loff_t *ppos) > +{ > + /* > + * Only CAP_SYS_MODULE in init user namespace are allowed to change this > + */ > + if (write && !capable(CAP_SYS_MODULE)) > + return -EPERM; > + > + return proc_dointvec_minmax(table, write, buffer, lenp, ppos); > +} > +#endif We now have proc_douintvec_minmax(). Luis
[PATCH v5 next 3/5] modules:capabilities: automatic module loading restriction
Currently, an explicit call to load or unload kernel modules require CAP_SYS_MODULE capability. However unprivileged users have always been able to load some modules using the implicit auto-load operation. An automatic module loading happens when programs request a kernel feature from a module that is not loaded. In order to satisfy userspace, the kernel then automatically load all these required modules. Historically, the kernel was always able to automatically load modules if they are not blacklisted. This is one of the most important and transparent operations of Linux, it allows to provide numerous other features as they are needed which is crucial for a better user experience. However, as Linux is popular now and used for different appliances some of these may need to control such operations. For such systems, recent needs showed that in some cases allowing to control automatic module loading is as important as the operation itself. Restricting unprivileged programs or attackers that abuse this feature to load unused modules or modules that contain bugs is a significant security measure. This allows administrators or some special programs to have the appropriate time to update and deny module autoloading in advance, then blacklist the corresponding ones. Not doing so may affect the global state of the machine, especially containers where some apps are moved from one context to another and not having such mechanisms may allow to expose and exploit the vulnerable parts to escape the container sandbox. Embedded or IoT devices also started to ship as containers using generic distros, some vendors do not have the appropriate time to make their own OS, hence, using base images is getting popular. These setups may include unnecessary modules that the final applications will not need. Untrusted access may abuse the module auto-load feature to expose vulnerabilities. As every code contains bugs or vulnerabilties, the following vulnerabilities that affected some features that are often compiled as modules could have been completely blocked, by restricting autoloading modules if the system does not need them. Past months: * DCCP use after free CVE-2017-6074 [1] [2] Unprivileged to local root. * XFRM framework CVE-2017-7184 [3] As advertised it seems it was used to break Ubuntu on a security contest. * n_hldc CVE-2017-2636 [4] [5] Local privilege escalation. * L2TPv3 CVE-2016-10200 The list is longer. To improve the current status, this patch introduces "modules_autoload_mode" kernel sysctl flag. The flag controls modules auto-load feature and complements "modules_disabled" which apply to all modules operations. This new flag allows to control only automatic module loading and if it is allowed or not, aligning in the process the implicit operation with the explicit one where both now are covered by capabilities checks. The three modes that "modules_autoload_mode" support allow to provide restrictions on automatic module loading without breaking user experience. The sysctl flag is available at "/proc/sys/kernel/modules_autoload_mode" When modules_autoload_mode is set to (0), the default, there are no restrictions. When modules_autoload_mode is set to (1), processes must have CAP_SYS_MODULE to be able to trigger a module auto-load operation, or CAP_NET_ADMIN for modules with a 'netdev-%s' alias, or other capabilities for specific aliased modules. When modules_autoload_mode is set to (2), automatic module loading is disabled for all. Notes on relation between "modules_disabled=0" and "modules_autoload_mode=2": 1) Once "modules_disabled=1" set, it needs a reboot to undo the setting. 2) Restricting automatic module loading does not interfere with explicit module load or unload operations. 3) New features provided by modules can be made available without rebooting the system. 4) A bad version of a module can be unloaded and replaced with a better one without rebooting the system. The idea of module auto-load restriction was inspired from grsecurity 'GRKERNSEC_MODHARDEN' config option. Upstream Linux implementation is more focused on the run-time behavior with a three mode switch. Testing --- Example 1) Before: $ lsmod | grep ipip - $ sudo ip tunnel add mytun mode ipip remote 10.0.2.100 local 10.0.2.15 ttl 255 $ lsmod | grep ipip - ipip 16384 0 tunnel416384 1 ipip ip_tunnel 28672 1 ipip $ cat /proc/sys/kernel/modules_autoload_mode 0 After: $ lsmod | grep ipip - $ sudo ip tunnel add mytun mode ipip remote 10.0.2.100 local 10.0.2.15 ttl 255 add tunnel "tunl0" failed: No such device $ dmesg ... [ 1876.378389] module: automatic module loading of netdev-tunl0 by "ip"[1453] was denied [ 1876.380994] module: automatic module loading of tunl0 by "ip"[1453] was denied ... $ lsmod | grep ipip - $ Example 2) DCCP use after free CVE-2017-6074: The code path can be triggered by unprivileged, using the trigger.c program for DCCP use after free [