x86: Use __builtin_object_size() to validate the buffer size for copy_from_user()
gcc (4.x) supports the __builtin_object_size() builtin, which reports the size of an object that a pointer point to, when known at compile time. If the buffer size is not known at compile time, a constant -1 is returned. This patch uses this feature to add a sanity check to copy_from_user(); if the target buffer is known to be smaller than the copy size, the copy is aborted and a WARNing is emitted in memory debug mode. These extra checks compile away when the object size is not known, or if both the buffer size and the copy length are constants. Signed-off-by: Arjan van de Ven <arjan@linux.intel.com> LKML-Reference: <20090926143301.2c396b94@infradead.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:

committed by
Ingo Molnar

parent
704daf55c7
commit
9f0cf4adb6
@@ -21,10 +21,27 @@ copy_user_generic(void *to, const void *from, unsigned len);
|
||||
__must_check unsigned long
|
||||
copy_to_user(void __user *to, const void *from, unsigned len);
|
||||
__must_check unsigned long
|
||||
copy_from_user(void *to, const void __user *from, unsigned len);
|
||||
_copy_from_user(void *to, const void __user *from, unsigned len);
|
||||
__must_check unsigned long
|
||||
copy_in_user(void __user *to, const void __user *from, unsigned len);
|
||||
|
||||
static inline unsigned long __must_check copy_from_user(void *to,
|
||||
const void __user *from,
|
||||
unsigned long n)
|
||||
{
|
||||
int sz = __compiletime_object_size(to);
|
||||
int ret = -EFAULT;
|
||||
|
||||
if (likely(sz == -1 || sz >= n))
|
||||
ret = _copy_from_user(to, from, n);
|
||||
#ifdef CONFIG_DEBUG_VM
|
||||
else
|
||||
WARN(1, "Buffer overflow detected!\n");
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static __always_inline __must_check
|
||||
int __copy_from_user(void *dst, const void __user *src, unsigned size)
|
||||
{
|
||||
|
Reference in New Issue
Block a user