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 0fe1c87..61a89d3 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 2b763f0..cd93fa5 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 410e90e..8b7d65d 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",
 };