Commit 22ec1a2a authored by Kees Cook's avatar Kees Cook Committed by Greg Kroah-Hartman

/dev/mem: Add bounce buffer for copy-out

As done for /proc/kcore in

  commit df04abfd ("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
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: default avatarMichael Holzheu <>
Fixes: f5509cc1 ("mm: Hardened usercopy")
Signed-off-by: default avatarKees Cook <>
Signed-off-by: default avatarGreg Kroah-Hartman <>
parent d9cc5a0e
......@@ -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,
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;
*ppos += read;
return read;
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"
select BUG
This option checks for obviously wrong memory regions when
copying memory to/from the kernel (via copy_to_user() and
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment