]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
x86: Turn the copy_from_user check into an (optional) compile time warning
authorArjan van de Ven <arjan@infradead.org>
Wed, 30 Sep 2009 11:05:23 +0000 (13:05 +0200)
committerIngo Molnar <mingo@elte.hu>
Thu, 1 Oct 2009 09:31:04 +0000 (11:31 +0200)
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>
arch/x86/include/asm/uaccess_32.h
arch/x86/lib/usercopy_32.c
include/linux/compiler-gcc4.h
include/linux/compiler.h

index 582d6aef7417e8de12af450afc278e182d5093ef..952f9e793c3e011580069563016ca6eb958cc8ac 100644 (file)
@@ -191,6 +191,13 @@ unsigned long __must_check _copy_from_user(void *to,
                                          const void __user *from,
                                          unsigned long n);
 
+
+extern void copy_from_user_overflow(void)
+#ifdef CONFIG_DEBUG_STACKOVERFLOW
+       __compiletime_warning("copy_from_user() buffer size is not provably correct")
+#endif
+;
+
 static inline unsigned long __must_check copy_from_user(void *to,
                                          const void __user *from,
                                          unsigned long n)
@@ -200,10 +207,9 @@ static inline unsigned long __must_check copy_from_user(void *to,
 
        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
+               copy_from_user_overflow();
+
        return ret;
 }
 
index 8498684e45b0d0864b490a2673daffdc0db01241..e218d5df85ff23445c277c2fe89d611dcab433ae 100644 (file)
@@ -883,3 +883,9 @@ _copy_from_user(void *to, const void __user *from, unsigned long n)
        return n;
 }
 EXPORT_SYMBOL(_copy_from_user);
+
+void copy_from_user_overflow(void)
+{
+       WARN(1, "Buffer overflow detected!\n");
+}
+EXPORT_SYMBOL(copy_from_user_overflow);
index a3aef5d55dba58e9d8567387b884db85e106de8a..f1709c1f9eae99ea57f0c9b42d4f5dd149fcb169 100644 (file)
@@ -39,3 +39,6 @@
 #endif
 
 #define __compiletime_object_size(obj) __builtin_object_size(obj, 0)
+#if __GNUC_MINOR__ >= 4
+#define __compiletime_warning(message) __attribute__((warning(message)))
+#endif
index 8e54108688f94eb7d98ce3c45356e96dc7b08049..950356311f12d28207cb1df798c9e856fd3144a4 100644 (file)
@@ -270,6 +270,10 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect);
 #ifndef __compiletime_object_size
 # define __compiletime_object_size(obj) -1
 #endif
+#ifndef __compiletime_warning
+# define __compiletime_warning(message)
+#endif
+
 /*
  * Prevent the compiler from merging or refetching accesses.  The compiler
  * is also forbidden from reordering successive instances of ACCESS_ONCE(),