From 684d263e75a6a7ede638afa60e35a238e24c12ba Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Tue, 26 Jan 2010 15:59:18 +0000 Subject: linux-moblin: Add 2.6.31.5 Signed-off-by: Richard Purdie --- .../linux-2.6.33-copy-checks.patch | 275 +++++++++++++++++++++ 1 file changed, 275 insertions(+) create mode 100644 meta-moblin/packages/linux/linux-moblin-2.6.31.5/linux-2.6.33-copy-checks.patch (limited to 'meta-moblin/packages/linux/linux-moblin-2.6.31.5/linux-2.6.33-copy-checks.patch') diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.31.5/linux-2.6.33-copy-checks.patch b/meta-moblin/packages/linux/linux-moblin-2.6.31.5/linux-2.6.33-copy-checks.patch new file mode 100644 index 000000000..720fda24e --- /dev/null +++ b/meta-moblin/packages/linux/linux-moblin-2.6.31.5/linux-2.6.33-copy-checks.patch @@ -0,0 +1,275 @@ +From 524a1da3c45683cec77480acc6cab1d33ae8d5cb Mon Sep 17 00:00:00 2001 +From: Arjan van de Ven +Date: Sat, 26 Sep 2009 12:36:21 +0200 +Subject: [PATCH] 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 +Reviewed-by: Ingo Molnar +--- + arch/x86/include/asm/uaccess_32.h | 19 ++++++++++++++++++- + arch/x86/include/asm/uaccess_64.h | 19 ++++++++++++++++++- + arch/x86/kernel/x8664_ksyms_64.c | 2 +- + arch/x86/lib/copy_user_64.S | 4 ++-- + arch/x86/lib/usercopy_32.c | 4 ++-- + include/linux/compiler-gcc4.h | 2 ++ + include/linux/compiler.h | 4 ++++ + 7 files changed, 47 insertions(+), 7 deletions(-) + +diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h +index 632fb44..582d6ae 100644 +--- a/arch/x86/include/asm/uaccess_32.h ++++ b/arch/x86/include/asm/uaccess_32.h +@@ -187,9 +187,26 @@ __copy_from_user_inatomic_nocache(void *to, const void __user *from, + + unsigned long __must_check copy_to_user(void __user *to, + const void *from, unsigned long n); +-unsigned long __must_check copy_from_user(void *to, ++unsigned long __must_check _copy_from_user(void *to, + const void __user *from, + unsigned long n); ++ ++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; ++} ++ + long __must_check strncpy_from_user(char *dst, const char __user *src, + long count); + long __must_check __strncpy_from_user(char *dst, +diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h +index db24b21..ce6fec7 100644 +--- a/arch/x86/include/asm/uaccess_64.h ++++ b/arch/x86/include/asm/uaccess_64.h +@@ -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) + { +diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c +index 3909e3b..a0cdd8c 100644 +--- a/arch/x86/kernel/x8664_ksyms_64.c ++++ b/arch/x86/kernel/x8664_ksyms_64.c +@@ -30,7 +30,7 @@ EXPORT_SYMBOL(__put_user_8); + + EXPORT_SYMBOL(copy_user_generic); + EXPORT_SYMBOL(__copy_user_nocache); +-EXPORT_SYMBOL(copy_from_user); ++EXPORT_SYMBOL(_copy_from_user); + EXPORT_SYMBOL(copy_to_user); + EXPORT_SYMBOL(__copy_from_user_inatomic); + +diff --git a/arch/x86/lib/copy_user_64.S b/arch/x86/lib/copy_user_64.S +index 6ba0f7b..4be3c41 100644 +--- a/arch/x86/lib/copy_user_64.S ++++ b/arch/x86/lib/copy_user_64.S +@@ -78,7 +78,7 @@ ENTRY(copy_to_user) + ENDPROC(copy_to_user) + + /* Standard copy_from_user with segment limit checking */ +-ENTRY(copy_from_user) ++ENTRY(_copy_from_user) + CFI_STARTPROC + GET_THREAD_INFO(%rax) + movq %rsi,%rcx +@@ -88,7 +88,7 @@ ENTRY(copy_from_user) + jae bad_from_user + ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string + CFI_ENDPROC +-ENDPROC(copy_from_user) ++ENDPROC(_copy_from_user) + + ENTRY(copy_user_generic) + CFI_STARTPROC +diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c +index 1f118d4..8498684 100644 +--- a/arch/x86/lib/usercopy_32.c ++++ b/arch/x86/lib/usercopy_32.c +@@ -874,7 +874,7 @@ EXPORT_SYMBOL(copy_to_user); + * data to the requested size using zero bytes. + */ + unsigned long +-copy_from_user(void *to, const void __user *from, unsigned long n) ++_copy_from_user(void *to, const void __user *from, unsigned long n) + { + if (access_ok(VERIFY_READ, from, n)) + n = __copy_from_user(to, from, n); +@@ -882,4 +882,4 @@ copy_from_user(void *to, const void __user *from, unsigned long n) + memset(to, 0, n); + return n; + } +-EXPORT_SYMBOL(copy_from_user); ++EXPORT_SYMBOL(_copy_from_user); +diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h +index 450fa59..a3aef5d 100644 +--- a/include/linux/compiler-gcc4.h ++++ b/include/linux/compiler-gcc4.h +@@ -37,3 +37,5 @@ + #define __cold __attribute__((__cold__)) + + #endif ++ ++#define __compiletime_object_size(obj) __builtin_object_size(obj, 0) +diff --git a/include/linux/compiler.h b/include/linux/compiler.h +index 9d4c4b0..9c42853 100644 +--- a/include/linux/compiler.h ++++ b/include/linux/compiler.h +@@ -185,6 +185,10 @@ extern void __chk_io_ptr(const volatile void __iomem *); + # define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) + #endif + ++/* Compile time object size, -1 for unknown */ ++#ifndef __compiletime_object_size ++# define __compiletime_object_size(obj) -1 ++#endif + /* + * Prevent the compiler from merging or refetching accesses. The compiler + * is also forbidden from reordering successive instances of ACCESS_ONCE(), +-- +1.6.0.6 + +From 350cf3cd513e6759ae6852946532a47249f25600 Mon Sep 17 00:00:00 2001 +From: Arjan van de Ven +Date: Wed, 30 Sep 2009 12:57:46 +0200 +Subject: [PATCH] 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. +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 +--- + arch/x86/include/asm/uaccess_32.h | 12 +++++++++--- + arch/x86/lib/usercopy_32.c | 6 ++++++ + include/linux/compiler-gcc4.h | 3 +++ + include/linux/compiler.h | 4 ++++ + 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 582d6ae..7826639 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, + 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; + } + +diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c +index 8498684..e218d5d 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) + 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); +diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h +index a3aef5d..f1709c1 100644 +--- a/include/linux/compiler-gcc4.h ++++ b/include/linux/compiler-gcc4.h +@@ -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 +diff --git a/include/linux/compiler.h b/include/linux/compiler.h +index 9c42853..241dfd8 100644 +--- a/include/linux/compiler.h ++++ b/include/linux/compiler.h +@@ -189,6 +189,10 @@ extern void __chk_io_ptr(const volatile void __iomem *); + #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(), +-- +1.6.2.5 + -- cgit v1.2.3