path: root/kernel/compat.c
diff options
authorH. Peter Anvin <>2010-09-07 16:16:18 -0700
committerH. Peter Anvin <>2010-09-14 16:08:45 -0700
commitc41d68a513c71e35a14f66d71782d27a79a81ea6 (patch)
tree2729377678b4f0fa516404eec6c3a87a4fd7c823 /kernel/compat.c
parentbfa88ea7ee9e6b4fd673e45a8cc0a8e0b7ef4761 (diff)
compat: Make compat_alloc_user_space() incorporate the access_ok()
compat_alloc_user_space() expects the caller to independently call access_ok() to verify the returned area. A missing call could introduce problems on some architectures. This patch incorporates the access_ok() check into compat_alloc_user_space() and also adds a sanity check on the length. The existing compat_alloc_user_space() implementations are renamed arch_compat_alloc_user_space() and are used as part of the implementation of the new global function. This patch assumes NULL will cause __get_user()/__put_user() to either fail or access userspace on all architectures. This should be followed by checking the return value of compat_access_user_space() for NULL in the callers, at which time the access_ok() in the callers can also be removed. Reported-by: Ben Hawkes <> Signed-off-by: H. Peter Anvin <> Acked-by: Benjamin Herrenschmidt <> Acked-by: Chris Metcalf <> Acked-by: David S. Miller <> Acked-by: Ingo Molnar <> Acked-by: Thomas Gleixner <> Acked-by: Tony Luck <> Cc: Andrew Morton <> Cc: Arnd Bergmann <> Cc: Fenghua Yu <> Cc: H. Peter Anvin <> Cc: Heiko Carstens <> Cc: Helge Deller <> Cc: James Bottomley <> Cc: Kyle McMartin <> Cc: Martin Schwidefsky <> Cc: Paul Mackerras <> Cc: Ralf Baechle <> Cc: <>
Diffstat (limited to 'kernel/compat.c')
1 files changed, 21 insertions, 0 deletions
diff --git a/kernel/compat.c b/kernel/compat.c
index e167efce8423..c9e2ec0b34a8 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -1126,3 +1126,24 @@ compat_sys_sysinfo(struct compat_sysinfo __user *info)
return 0;
+ * Allocate user-space memory for the duration of a single system call,
+ * in order to marshall parameters inside a compat thunk.
+ */
+void __user *compat_alloc_user_space(unsigned long len)
+ void __user *ptr;
+ /* If len would occupy more than half of the entire compat space... */
+ if (unlikely(len > (((compat_uptr_t)~0) >> 1)))
+ return NULL;
+ ptr = arch_compat_alloc_user_space(len);
+ if (unlikely(!access_ok(VERIFY_WRITE, ptr, len)))
+ return NULL;
+ return ptr;