Re: [PATCH V40 12/29] x86: Lock down IO port access when the kernel is locked down
From: Kai-Heng Feng <hidden>
Date: 2022-01-05 06:25:58
Also in:
linux-api, lkml
Hi Matthew, On Tue, Aug 20, 2019 at 8:20 AM Matthew Garrett [off-list ref] wrote:
From: Matthew Garrett <mjg59@srcf.ucam.org> 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 <redacted> Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-by: Kees Cook <redacted> cc: x86@kernel.org Signed-off-by: James Morris <jmorris@namei.org>
This patch breaks ioperm() usage from userspace programs with CAP_SYS_RAWIO cap. I wonder if it's possible to revert this commit? Kai-Heng
quoted hunk ↗ jump to hunk
--- arch/x86/kernel/ioport.c | 7 +++++-- include/linux/security.h | 1 + security/lockdown/lockdown.c | 1 + 3 files changed, 7 insertions(+), 2 deletions(-)diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c index 0fe1c8782208..61a89d3c0382 100644 --- a/arch/x86/kernel/ioport.c +++ b/arch/x86/kernel/ioport.c@@ -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) |diff --git a/include/linux/security.h b/include/linux/security.h index 2b763f0ee352..cd93fa5d3c6d 100644 --- a/include/linux/security.h +++ b/include/linux/security.h@@ -108,6 +108,7 @@ enum lockdown_reason { LOCKDOWN_KEXEC, LOCKDOWN_HIBERNATION, LOCKDOWN_PCI_ACCESS, + LOCKDOWN_IOPORT, LOCKDOWN_INTEGRITY_MAX, LOCKDOWN_CONFIDENTIALITY_MAX, };diff --git a/security/lockdown/lockdown.c b/security/lockdown/lockdown.c index 410e90eda848..8b7d65dbb086 100644 --- a/security/lockdown/lockdown.c +++ b/security/lockdown/lockdown.c@@ -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", }; --2.23.0.rc1.153.gdeed80330f-goog