/dev/mem: Add bounce buffer for copy-out
Subsystems (2)
PATCH 1/1 /dev/mem: Add bounce buffer for copy-out
As done for /proc/kcore in
commit df04abfd181a ("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.
--- drivers/char/mem.c | 27 ++++++++++++++++++++++----- security/Kconfig | 1 + 2 files changed, 23 insertions(+), 5 deletions(-)
drivers/char/mem.c +22 -5
@@ -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,
security/Kconfig +1 -0
@@ -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
Signature · 6 lines
2.7.4 -- Kees Cook Pixel Security