/dev/mem: Add bounce buffer for copy-out
As done for /proc/kcore in commitdf04abfd18
("fs/proc/kcore.c: Add bounce buffer for ktext data") this adds a bounce buffer when reading memory via /dev/mem. This is needed to allow kernel text memory to be read out when built with CONFIG_HARDENED_USERCOPY (which refuses to read out kernel text) and without CONFIG_STRICT_DEVMEM (which would have refused to read any RAM contents at all). Since this build configuration isn't common (most systems with CONFIG_HARDENED_USERCOPY also have CONFIG_STRICT_DEVMEM), this also tries to inform Kconfig about the recommended settings. This patch is modified from Brad Spengler/PaX Team's changes to /dev/mem code in the last public patch of grsecurity/PaX based on my understanding of the code. Changes or omissions from the original code are mine and don't reflect the original grsecurity/PaX code. Reported-by: Michael Holzheu <holzheu@linux.vnet.ibm.com> Fixes:f5509cc18d
("mm: Hardened usercopy") Signed-off-by: Kees Cook <keescook@chromium.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
d9cc5a0edb
commit
22ec1a2aea
|
@ -107,6 +107,8 @@ static ssize_t read_mem(struct file *file, char __user *buf,
|
|||
phys_addr_t p = *ppos;
|
||||
ssize_t read, sz;
|
||||
void *ptr;
|
||||
char *bounce;
|
||||
int err;
|
||||
|
||||
if (p != *ppos)
|
||||
return 0;
|
||||
|
@ -129,15 +131,22 @@ static ssize_t read_mem(struct file *file, char __user *buf,
|
|||
}
|
||||
#endif
|
||||
|
||||
bounce = kmalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
if (!bounce)
|
||||
return -ENOMEM;
|
||||
|
||||
while (count > 0) {
|
||||
unsigned long remaining;
|
||||
int allowed;
|
||||
|
||||
sz = size_inside_page(p, count);
|
||||
|
||||
err = -EPERM;
|
||||
allowed = page_is_allowed(p >> PAGE_SHIFT);
|
||||
if (!allowed)
|
||||
return -EPERM;
|
||||
goto failed;
|
||||
|
||||
err = -EFAULT;
|
||||
if (allowed == 2) {
|
||||
/* Show zeros for restricted memory. */
|
||||
remaining = clear_user(buf, sz);
|
||||
|
@ -149,24 +158,32 @@ static ssize_t read_mem(struct file *file, char __user *buf,
|
|||
*/
|
||||
ptr = xlate_dev_mem_ptr(p);
|
||||
if (!ptr)
|
||||
return -EFAULT;
|
||||
|
||||
remaining = copy_to_user(buf, ptr, sz);
|
||||
goto failed;
|
||||
|
||||
err = probe_kernel_read(bounce, ptr, sz);
|
||||
unxlate_dev_mem_ptr(p, ptr);
|
||||
if (err)
|
||||
goto failed;
|
||||
|
||||
remaining = copy_to_user(buf, bounce, sz);
|
||||
}
|
||||
|
||||
if (remaining)
|
||||
return -EFAULT;
|
||||
goto failed;
|
||||
|
||||
buf += sz;
|
||||
p += sz;
|
||||
count -= sz;
|
||||
read += sz;
|
||||
}
|
||||
kfree(bounce);
|
||||
|
||||
*ppos += read;
|
||||
return read;
|
||||
|
||||
failed:
|
||||
kfree(bounce);
|
||||
return err;
|
||||
}
|
||||
|
||||
static ssize_t write_mem(struct file *file, const char __user *buf,
|
||||
|
|
|
@ -143,6 +143,7 @@ config HARDENED_USERCOPY
|
|||
bool "Harden memory copies between kernel and userspace"
|
||||
depends on HAVE_HARDENED_USERCOPY_ALLOCATOR
|
||||
select BUG
|
||||
imply STRICT_DEVMEM
|
||||
help
|
||||
This option checks for obviously wrong memory regions when
|
||||
copying memory to/from the kernel (via copy_to_user() and
|
||||
|
|
Loading…
Reference in New Issue