aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArjan van de Ven <arjan@infradead.org>2009-09-30 07:05:23 -0400
committerIngo Molnar <mingo@elte.hu>2009-10-01 05:31:04 -0400
commit4a3127693001c61a21d1ce680db6340623f52e93 (patch)
tree380f5f64098926e8b3f64785580cfdac1b8b3b96
parentff60fab71bb3b4fdbf8caf57ff3739ffd0887396 (diff)
x86: Turn the copy_from_user check into an (optional) compile time warning
A previous patch added the buffer size check to copy_from_user(). One of the things learned from analyzing the result of the previous patch is that in general, gcc is really good at proving that the code contains sufficient security checks to not need to do a runtime check. But that for those cases where gcc could not prove this, there was a relatively high percentage of real security issues. This patch turns the case of "gcc cannot prove" into a compile time warning, as long as a sufficiently new gcc is in use that supports this. The objective is that these warnings will trigger developers checking new cases out before a security hole enters a linux kernel release. Signed-off-by: Arjan van de Ven <arjan@linux.intel.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: "David S. Miller" <davem@davemloft.net> Cc: James Morris <jmorris@namei.org> Cc: Jan Beulich <jbeulich@novell.com> LKML-Reference: <20090930130523.348ae6c4@infradead.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--arch/x86/include/asm/uaccess_32.h12
-rw-r--r--arch/x86/lib/usercopy_32.c6
-rw-r--r--include/linux/compiler-gcc4.h3
-rw-r--r--include/linux/compiler.h4
4 files changed, 22 insertions, 3 deletions
diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h
index 582d6aef741..952f9e793c3 100644
--- a/arch/x86/include/asm/uaccess_32.h
+++ b/arch/x86/include/asm/uaccess_32.h
@@ -191,6 +191,13 @@ unsigned long __must_check _copy_from_user(void *to,
191 const void __user *from, 191 const void __user *from,
192 unsigned long n); 192 unsigned long n);
193 193
194
195extern void copy_from_user_overflow(void)
196#ifdef CONFIG_DEBUG_STACKOVERFLOW
197 __compiletime_warning("copy_from_user() buffer size is not provably correct")
198#endif
199;
200
194static inline unsigned long __must_check copy_from_user(void *to, 201static inline unsigned long __must_check copy_from_user(void *to,
195 const void __user *from, 202 const void __user *from,
196 unsigned long n) 203 unsigned long n)
@@ -200,10 +207,9 @@ static inline unsigned long __must_check copy_from_user(void *to,
200 207
201 if (likely(sz == -1 || sz >= n)) 208 if (likely(sz == -1 || sz >= n))
202 ret = _copy_from_user(to, from, n); 209 ret = _copy_from_user(to, from, n);
203#ifdef CONFIG_DEBUG_VM
204 else 210 else
205 WARN(1, "Buffer overflow detected!\n"); 211 copy_from_user_overflow();
206#endif 212
207 return ret; 213 return ret;
208} 214}
209 215
diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c
index 8498684e45b..e218d5df85f 100644
--- a/arch/x86/lib/usercopy_32.c
+++ b/arch/x86/lib/usercopy_32.c
@@ -883,3 +883,9 @@ _copy_from_user(void *to, const void __user *from, unsigned long n)
883 return n; 883 return n;
884} 884}
885EXPORT_SYMBOL(_copy_from_user); 885EXPORT_SYMBOL(_copy_from_user);
886
887void copy_from_user_overflow(void)
888{
889 WARN(1, "Buffer overflow detected!\n");
890}
891EXPORT_SYMBOL(copy_from_user_overflow);
diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h
index a3aef5d55db..f1709c1f9ea 100644
--- a/include/linux/compiler-gcc4.h
+++ b/include/linux/compiler-gcc4.h
@@ -39,3 +39,6 @@
39#endif 39#endif
40 40
41#define __compiletime_object_size(obj) __builtin_object_size(obj, 0) 41#define __compiletime_object_size(obj) __builtin_object_size(obj, 0)
42#if __GNUC_MINOR__ >= 4
43#define __compiletime_warning(message) __attribute__((warning(message)))
44#endif
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 8e54108688f..950356311f1 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -270,6 +270,10 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect);
270#ifndef __compiletime_object_size 270#ifndef __compiletime_object_size
271# define __compiletime_object_size(obj) -1 271# define __compiletime_object_size(obj) -1
272#endif 272#endif
273#ifndef __compiletime_warning
274# define __compiletime_warning(message)
275#endif
276
273/* 277/*
274 * Prevent the compiler from merging or refetching accesses. The compiler 278 * Prevent the compiler from merging or refetching accesses. The compiler
275 * is also forbidden from reordering successive instances of ACCESS_ONCE(), 279 * is also forbidden from reordering successive instances of ACCESS_ONCE(),