Re: [2/6] uaccess: add probe_kernel_write()

Jan Kiszka
2008-02-10T18:54:57Z

Ingo Molnar wrote:
> From: Ingo Molnar <mingo@elte.hu>
>
> add probe_kernel_write() - copy & paste of the existing
> probe_kernel_access(), extended to writes.

Along Linus' suggestion to work on larger chunks in kgdb, here are
improved probe_kernel_read/write helpers that take a size argument.

I'm leaving the original probe_kernel_read as is for now, but maybe it
can be converted to probe_kernel_read (I don't want to dive into this as
well :) ).

Signed-off-by: Jan Kiszka <jan.kiszka@web.de>

---
uaccess.h | 38 +++++++++++++++++++++++++++++++-------
1 file changed, 31 insertions(+), 7 deletions(-)

diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h
index 98cfe02..ef75869 100644
--- a/include/linux/uaccess.h
+++ b/include/linux/uaccess.h
@@ -85,25 +85,49 @@ static inline unsigned long __copy_from_user_nocache(void *to,
})

/**
+ * probe_kernel_read(): safely attempt to read from a location
+ * @dst: pointer to the buffer that shall take the data
+ * @src: address to read from
+ * @size: size of the data chunk
+ *
+ * Safely read from address @src to the buffer at @dst. If a kernel fault
+ * happens, handle that and return -EFAULT.
+ */
+#define probe_kernel_read(dst, src, size) \
+ ({ \
+ long ret; \
+ mm_segment_t old_fs = get_fs(); \
+ \
+ set_fs(KERNEL_DS); \
+ pagefault_disable(); \
+ ret = __copy_from_user_inatomic((dst), \
+ (__force const void __user *)(src), (size)); \
+ pagefault_enable(); \
+ set_fs(old_fs); \
+ ret ? -EFAULT : 0; \
+ })
+
+/**
* probe_kernel_write(): safely attempt to write to a location
- * @addr: address to write to - its type is type typeof(rdval)*
- * @rdval: write to this variable
+ * @dst: address to write to
+ * @src: pointer to the data that shall be written
+ * @size: size of the data chunk
*
- * Safely write to address @addr from variable @rdval. If a kernel fault
+ * Safely write to address @dst from the buffer at @src. If a kernel fault
* happens, handle that and return -EFAULT.
*/
-#define probe_kernel_write(addr, rdval) \
+#define probe_kernel_write(dst, src, size) \
({ \
long ret; \
mm_segment_t old_fs = get_fs(); \
\
set_fs(KERNEL_DS); \
pagefault_disable(); \
- ret = __put_user(rdval, \
- (__force typeof(rdval) __user *)(addr)); \
+ ret = __copy_to_user_inatomic( \
+ (__force void __user *)(dst), (src), (size)); \
pagefault_enable(); \
set_fs(old_fs); \
- ret; \
+ ret ? -EFAULT : 0; \