On Fri, Jun 21, 2019 at 05:03:34PM -0700, Matthew Garrett wrote: > From: Matthew Garrett <mjg59@xxxxxxxxxxxxx> > > Allowing users to read and write to core kernel memory makes it possible > for the kernel to be subverted, avoiding module loading restrictions, and > also to steal cryptographic information. > > Disallow /dev/mem and /dev/kmem from being opened this when the kernel has > been locked down to prevent this. > > Also disallow /dev/port from being opened to prevent raw ioport access and > thus DMA from being used to accomplish the same thing. > > Signed-off-by: David Howells <dhowells@xxxxxxxxxx> > Signed-off-by: Matthew Garrett <mjg59@xxxxxxxxxx> > Cc: x86@xxxxxxxxxx > --- > drivers/char/mem.c | 6 +++++- > include/linux/security.h | 1 + > security/lockdown/lockdown.c | 1 + > 3 files changed, 7 insertions(+), 1 deletion(-) > > diff --git a/drivers/char/mem.c b/drivers/char/mem.c > index b08dc50f9f26..93c02493f0fa 100644 > --- a/drivers/char/mem.c > +++ b/drivers/char/mem.c > @@ -29,8 +29,8 @@ > #include <linux/export.h> > #include <linux/io.h> > #include <linux/uio.h> > - > #include <linux/uaccess.h> > +#include <linux/security.h> > > #ifdef CONFIG_IA64 > # include <linux/efi.h> > @@ -786,6 +786,10 @@ static loff_t memory_lseek(struct file *file, loff_t offset, int orig) > > static int open_port(struct inode *inode, struct file *filp) > { > + int ret = security_locked_down(LOCKDOWN_DEV_MEM); > + > + if (ret) > + return ret; > return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; Usually the ordering for LSM tests tends to follow capable checks, which allows for things like audit to generate logs for capability rejections, etc. I'd expect this to be: if (!capable(CAP_SYS_RAWIO)) return -EPERM; return security_locked_down(LOCKDOWN_DEV_MEM) With that fixed: Reviewed-by: Kees Cook <keescook@xxxxxxxxxxxx> -Kees > } > > diff --git a/include/linux/security.h b/include/linux/security.h > index 46d85cd63b06..200175c8605a 100644 > --- a/include/linux/security.h > +++ b/include/linux/security.h > @@ -83,6 +83,7 @@ enum lsm_event { > enum lockdown_reason { > LOCKDOWN_NONE, > LOCKDOWN_MODULE_SIGNATURE, > + LOCKDOWN_DEV_MEM, > LOCKDOWN_INTEGRITY_MAX, > LOCKDOWN_CONFIDENTIALITY_MAX, > }; > diff --git a/security/lockdown/lockdown.c b/security/lockdown/lockdown.c > index 25a3a5b0aa9c..565c87451f0f 100644 > --- a/security/lockdown/lockdown.c > +++ b/security/lockdown/lockdown.c > @@ -19,6 +19,7 @@ static enum lockdown_reason kernel_locked_down; > static char *lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1] = { > [LOCKDOWN_NONE] = "none", > [LOCKDOWN_MODULE_SIGNATURE] = "unsigned module loading", > + [LOCKDOWN_DEV_MEM] = "/dev/mem,kmem,port", > [LOCKDOWN_INTEGRITY_MAX] = "integrity", > [LOCKDOWN_CONFIDENTIALITY_MAX] = "confidentiality", > }; > -- > 2.22.0.410.gd8fdbe21b5-goog > -- Kees Cook