x86: Lock down IO port access when the kernel is locked down
authorMatthew Garrett <mjg59@srcf.ucam.org>
Tue, 20 Aug 2019 00:17:48 +0000 (17:17 -0700)
committerJames Morris <jmorris@namei.org>
Tue, 20 Aug 2019 04:54:16 +0000 (21:54 -0700)
IO port access would permit users to gain access to PCI configuration
registers, which in turn (on a lot of hardware) give access to MMIO
register space. This would potentially permit root to trigger arbitrary
DMA, so lock it down by default.

This also implicitly locks down the KDADDIO, KDDELIO, KDENABIO and
KDDISABIO console ioctls.

Signed-off-by: Matthew Garrett <mjg59@google.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
cc: x86@kernel.org
Signed-off-by: James Morris <jmorris@namei.org>
arch/x86/kernel/ioport.c
include/linux/security.h
security/lockdown/lockdown.c

index 0fe1c8782208753082f645129f25f1476f7d63ac..61a89d3c0382b947713fd9d779f1680e28a651ee 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/ioport.h>
+#include <linux/security.h>
 #include <linux/smp.h>
 #include <linux/stddef.h>
 #include <linux/slab.h>
@@ -31,7 +32,8 @@ long ksys_ioperm(unsigned long from, unsigned long num, int turn_on)
 
        if ((from + num <= from) || (from + num > IO_BITMAP_BITS))
                return -EINVAL;
-       if (turn_on && !capable(CAP_SYS_RAWIO))
+       if (turn_on && (!capable(CAP_SYS_RAWIO) ||
+                       security_locked_down(LOCKDOWN_IOPORT)))
                return -EPERM;
 
        /*
@@ -126,7 +128,8 @@ SYSCALL_DEFINE1(iopl, unsigned int, level)
                return -EINVAL;
        /* Trying to gain more privileges? */
        if (level > old) {
-               if (!capable(CAP_SYS_RAWIO))
+               if (!capable(CAP_SYS_RAWIO) ||
+                   security_locked_down(LOCKDOWN_IOPORT))
                        return -EPERM;
        }
        regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) |
index 2b763f0ee35272ab53daeb759d4bb684510f243e..cd93fa5d3c6d34f6aac5f0b7dde849e1ad4a1865 100644 (file)
@@ -108,6 +108,7 @@ enum lockdown_reason {
        LOCKDOWN_KEXEC,
        LOCKDOWN_HIBERNATION,
        LOCKDOWN_PCI_ACCESS,
+       LOCKDOWN_IOPORT,
        LOCKDOWN_INTEGRITY_MAX,
        LOCKDOWN_CONFIDENTIALITY_MAX,
 };
index 410e90eda848adc76be71b82808bec7a0396294e..8b7d65dbb0866080e5dab9c45b690c35fdf8c7e2 100644 (file)
@@ -23,6 +23,7 @@ static char *lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1] = {
        [LOCKDOWN_KEXEC] = "kexec of unsigned images",
        [LOCKDOWN_HIBERNATION] = "hibernation",
        [LOCKDOWN_PCI_ACCESS] = "direct PCI access",
+       [LOCKDOWN_IOPORT] = "raw io port access",
        [LOCKDOWN_INTEGRITY_MAX] = "integrity",
        [LOCKDOWN_CONFIDENTIALITY_MAX] = "confidentiality",
 };