diff options
author | David Howells <dhowells@redhat.com> | 2019-08-19 17:17:55 -0700 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2019-08-19 21:54:16 -0700 |
commit | 20657f66ef52e5005369e4ef539d4cbf01eab10d (patch) | |
tree | f5f50d1c2f61821f69e41f1237cdafb446af8e5b | |
parent | 794edf30ee6cd088d5f4079b1d4a4cfe5371203e (diff) |
lockdown: Lock down module params that specify hardware parameters (eg. ioport)
Provided an annotation for module parameters that specify hardware
parameters (such as io ports, iomem addresses, irqs, dma channels, fixed
dma buffers and other types).
Suggested-by: Alan Cox <gnomes@lxorguk.ukuu.org.uk>
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Matthew Garrett <mjg59@google.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Cc: Jessica Yu <jeyu@kernel.org>
Signed-off-by: James Morris <jmorris@namei.org>
-rw-r--r-- | include/linux/security.h | 1 | ||||
-rw-r--r-- | kernel/params.c | 21 | ||||
-rw-r--r-- | security/lockdown/lockdown.c | 1 |
3 files changed, 18 insertions, 5 deletions
diff --git a/include/linux/security.h b/include/linux/security.h index b4a85badb03a..1a3404f9c060 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -113,6 +113,7 @@ enum lockdown_reason { LOCKDOWN_ACPI_TABLES, LOCKDOWN_PCMCIA_CIS, LOCKDOWN_TIOCSSERIAL, + LOCKDOWN_MODULE_PARAMETERS, LOCKDOWN_INTEGRITY_MAX, LOCKDOWN_CONFIDENTIALITY_MAX, }; diff --git a/kernel/params.c b/kernel/params.c index cf448785d058..8e56f8b12d8f 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -12,6 +12,7 @@ #include <linux/err.h> #include <linux/slab.h> #include <linux/ctype.h> +#include <linux/security.h> #ifdef CONFIG_SYSFS /* Protects all built-in parameters, modules use their own param_lock */ @@ -96,13 +97,19 @@ bool parameq(const char *a, const char *b) return parameqn(a, b, strlen(a)+1); } -static void param_check_unsafe(const struct kernel_param *kp) +static bool param_check_unsafe(const struct kernel_param *kp) { + if (kp->flags & KERNEL_PARAM_FL_HWPARAM && + security_locked_down(LOCKDOWN_MODULE_PARAMETERS)) + return false; + if (kp->flags & KERNEL_PARAM_FL_UNSAFE) { pr_notice("Setting dangerous option %s - tainting kernel\n", kp->name); add_taint(TAINT_USER, LOCKDEP_STILL_OK); } + + return true; } static int parse_one(char *param, @@ -132,8 +139,10 @@ static int parse_one(char *param, pr_debug("handling %s with %p\n", param, params[i].ops->set); kernel_param_lock(params[i].mod); - param_check_unsafe(¶ms[i]); - err = params[i].ops->set(val, ¶ms[i]); + if (param_check_unsafe(¶ms[i])) + err = params[i].ops->set(val, ¶ms[i]); + else + err = -EPERM; kernel_param_unlock(params[i].mod); return err; } @@ -553,8 +562,10 @@ static ssize_t param_attr_store(struct module_attribute *mattr, return -EPERM; kernel_param_lock(mk->mod); - param_check_unsafe(attribute->param); - err = attribute->param->ops->set(buf, attribute->param); + if (param_check_unsafe(attribute->param)) + err = attribute->param->ops->set(buf, attribute->param); + else + err = -EPERM; kernel_param_unlock(mk->mod); if (!err) return len; diff --git a/security/lockdown/lockdown.c b/security/lockdown/lockdown.c index 771c77f9c04a..0fa434294667 100644 --- a/security/lockdown/lockdown.c +++ b/security/lockdown/lockdown.c @@ -28,6 +28,7 @@ static char *lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1] = { [LOCKDOWN_ACPI_TABLES] = "modifying ACPI tables", [LOCKDOWN_PCMCIA_CIS] = "direct PCMCIA CIS storage", [LOCKDOWN_TIOCSSERIAL] = "reconfiguration of serial port IO", + [LOCKDOWN_MODULE_PARAMETERS] = "unsafe module parameters", [LOCKDOWN_INTEGRITY_MAX] = "integrity", [LOCKDOWN_CONFIDENTIALITY_MAX] = "confidentiality", }; |