summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Morton <akpm@osdl.org>2006-09-27 01:51:14 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2006-09-27 08:26:20 -0700
commit1b79e5513d52e8533a08af35a3595dad80c74d1f (patch)
tree01d69b3e5e9fca89fc44b462bfe24cb06243ac0f
parentaafe6c2a2b6bce5a3a4913ce5c07e85ea143144d (diff)
[PATCH] add probe_kernel_address()
Add a version of __get_user() which is safe to call inside mmap_sem. Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--include/linux/uaccess.h22
1 files changed, 22 insertions, 0 deletions
diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h
index 391e7ed1eb3..a48d7f11c7b 100644
--- a/include/linux/uaccess.h
+++ b/include/linux/uaccess.h
@@ -19,4 +19,26 @@ static inline unsigned long __copy_from_user_nocache(void *to,
#endif /* ARCH_HAS_NOCACHE_UACCESS */
+/**
+ * probe_kernel_address(): safely attempt to read from a location
+ * @addr: address to read from - its type is type typeof(retval)*
+ * @retval: read into this variable
+ *
+ * Safely read from address @addr into variable @revtal. If a kernel fault
+ * happens, handle that and return -EFAULT.
+ * We ensure that the __get_user() is executed in atomic context so that
+ * do_page_fault() doesn't attempt to take mmap_sem. This makes
+ * probe_kernel_address() suitable for use within regions where the caller
+ * already holds mmap_sem, or other locks which nest inside mmap_sem.
+ */
+#define probe_kernel_address(addr, retval) \
+ ({ \
+ long ret; \
+ \
+ inc_preempt_count(); \
+ ret = __get_user(retval, addr); \
+ dec_preempt_count(); \
+ ret; \
+ })
+
#endif /* __LINUX_UACCESS_H__ */