* experimental kernel patch for FORTIFY_SOURCE in kernel space
@ 2005-05-19 9:56 Arjan van de Ven
2005-05-23 8:57 ` David Woodhouse
0 siblings, 1 reply; 2+ messages in thread
From: Arjan van de Ven @ 2005-05-19 9:56 UTC (permalink / raw)
To: linuxppc-dev
Hi,
There is a gcc patch in development (posted to the patches list several
times now and getting close to done) that allows gcc to track the size of
objects at compile time. The idea is that for code like
void func(char *str)
{
char buf[20];
strcpy(buf, str);
}
gcc keeps track of "buf" being 20 bytes in size and then (together with
glibc) cause that strcpy() to be replaced by a special strcpy that gets "20"
as extra parameter and will cause an abort rather than a buffer overflow if
more than 20 bytes get copied.
This works great in Fedora Core 4 for userland (the technology is there in
RHEL4 and FC3 as well but not used for everything), and recently I started
"porting" this to the kernel.
There is somewhat of an architecture impact so before submitting it on lkml
I'd want to ask feedback from more arches than just x86...
Greetings,
Arjan van de Ven
diff -purN linux-2.6.12-rc4/Makefile linux-fortify/Makefile
--- linux-2.6.12-rc4/Makefile 2005-05-14 14:41:18.000000000 +0200
+++ linux-fortify/Makefile 2005-05-15 15:26:33.000000000 +0200
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 12
-EXTRAVERSION =-rc4
+EXTRAVERSION =-rc4-fortify
NAME=Woozy Numbat
# *DOCUMENTATION*
diff -purN linux-2.6.12-rc4/arch/i386/Kconfig.debug linux-fortify/arch/i386/Kconfig.debug
--- linux-2.6.12-rc4/arch/i386/Kconfig.debug 2005-05-14 14:41:19.000000000 +0200
+++ linux-fortify/arch/i386/Kconfig.debug 2005-05-15 15:26:33.000000000 +0200
@@ -59,6 +59,14 @@ config 4KSTACKS
on the VM subsystem for higher order allocations. This option
will also use IRQ stacks to compensate for the reduced stackspace.
+config FORTIFY_SOURCE
+ bool "Enable limited buffer overflow checking"
+ help
+ If you say Y here the kernel will use a recent gcc feature that
+ allows several key kernel primitives to check for buffer overflows
+ when dealing with static buffers. Do not enable this feature unless
+ you have a very recent gcc (version 4.1 or gccs from FC3, FC4, RHEL4)
+
config X86_FIND_SMP_CONFIG
bool
depends on X86_LOCAL_APIC || X86_VOYAGER
diff -purN linux-2.6.12-rc4/include/asm-i386/string.h linux-fortify/include/asm-i386/string.h
--- linux-2.6.12-rc4/include/asm-i386/string.h 2005-05-14 14:41:21.000000000 +0200
+++ linux-fortify/include/asm-i386/string.h 2005-05-15 17:03:06.000000000 +0200
@@ -23,11 +23,14 @@
* consider these trivial functions to be PD.
*/
+
/* AK: in fact I bet it would be better to move this stuff all out of line.
+ * Arjan: .. or just straight use the gcc built-in versions
*/
+
#define __HAVE_ARCH_STRCPY
-static inline char * strcpy(char * dest,const char *src)
+extern inline char * strcpy(char * dest,const char *src)
{
int d0, d1, d2;
__asm__ __volatile__(
@@ -41,7 +44,7 @@ return dest;
}
#define __HAVE_ARCH_STRNCPY
-static inline char * strncpy(char * dest,const char *src,size_t count)
+extern inline char * strncpy(char * dest,const char *src,size_t count)
{
int d0, d1, d2, d3;
__asm__ __volatile__(
@@ -60,7 +63,7 @@ return dest;
}
#define __HAVE_ARCH_STRCAT
-static inline char * strcat(char * dest,const char * src)
+extern inline char * strcat(char * dest,const char * src)
{
int d0, d1, d2, d3;
__asm__ __volatile__(
@@ -77,7 +80,7 @@ return dest;
}
#define __HAVE_ARCH_STRNCAT
-static inline char * strncat(char * dest,const char * src,size_t count)
+extern inline char * strncat(char * dest,const char * src,size_t count)
{
int d0, d1, d2, d3;
__asm__ __volatile__(
diff -purN linux-2.6.12-rc4/include/asm-i386/uaccess.h linux-fortify/include/asm-i386/uaccess.h
--- linux-2.6.12-rc4/include/asm-i386/uaccess.h 2005-05-14 14:41:21.000000000 +0200
+++ linux-fortify/include/asm-i386/uaccess.h 2005-05-15 15:26:33.000000000 +0200
@@ -9,6 +9,7 @@
#include <linux/thread_info.h>
#include <linux/prefetch.h>
#include <linux/string.h>
+#include <linux/compiler.h>
#include <asm/page.h>
#define VERIFY_READ 0
@@ -507,10 +508,6 @@ __copy_from_user(void *to, const void __
might_sleep();
return __copy_from_user_inatomic(to, from, n);
}
-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,
- const void __user *from, unsigned long n);
long __must_check strncpy_from_user(char *dst, const char __user *src,
long count);
long __must_check __strncpy_from_user(char *dst,
@@ -536,4 +533,40 @@ long strnlen_user(const char __user *str
unsigned long __must_check clear_user(void __user *mem, unsigned long len);
unsigned long __must_check __clear_user(void __user *mem, unsigned long len);
+
+unsigned long __must_check copy_to_user(void __user *to,
+ const void *from, unsigned long n);
+
+#ifdef CONFIG_FORTIFY_SOURCE
+
+extern void __chk_fail(void);
+
+/*
+ * the inline function with the check wants to call the non-inlined function
+ * with the same name for the actual work. The easiest way to do this is to make
+ * an alias of the real function and just call this alias from the inline.
+ */
+extern int __c_f_u_alias(void *to, const void __user *from, unsigned long __nbytes) __asm__ ("" "copy_from_user");
+
+
+extern unsigned long __always_inline __must_check
+copy_from_user (void *to, const void __user *from, unsigned long __nbytes)
+{
+ /*
+ * if we know the size of "to" then we can validate that we don't overrun the buffer.
+ * note that if __nbytes is known at compiletime this check is nicely optimized out
+ */
+ if (__bos0 (to) != (size_t) -1 && __nbytes > __bos0 (to))
+ __chk_fail();
+ return __c_f_u_alias (to, from, __nbytes);
+}
+
+#else
+
+unsigned long __must_check copy_to_user(void __user *to,
+ const void *from, unsigned long n);
+
+#endif
+
+
#endif /* __i386_UACCESS_H */
diff -purN linux-2.6.12-rc4/include/linux/compiler-gcc3.h linux-fortify/include/linux/compiler-gcc3.h
--- linux-2.6.12-rc4/include/linux/compiler-gcc3.h 2005-05-14 14:41:21.000000000 +0200
+++ linux-fortify/include/linux/compiler-gcc3.h 2005-05-15 15:26:33.000000000 +0200
@@ -30,3 +30,8 @@
#define __must_check __attribute__((warn_unused_result))
#endif
+
+#if defined(__GNUC_RH_RELEASE__) && __GNUC_MINOR__ >= 4 && __GNUC_PATCHLEVEL__ >=2
+#define __bos(ptr) __builtin_object_size (ptr, 1)
+#define __bos0(ptr) __builtin_object_size (ptr, 0)
+#endif
diff -purN linux-2.6.12-rc4/include/linux/compiler-gcc4.h linux-fortify/include/linux/compiler-gcc4.h
--- linux-2.6.12-rc4/include/linux/compiler-gcc4.h 2005-05-14 14:41:21.000000000 +0200
+++ linux-fortify/include/linux/compiler-gcc4.h 2005-05-15 15:26:33.000000000 +0200
@@ -14,3 +14,7 @@
#define __must_check __attribute__((warn_unused_result))
#define __compiler_offsetof(a,b) __builtin_offsetof(a,b)
+#if defined(__GNUC_RH_RELEASE__) || __GNUC_MINOR__ >= 1
+#define __bos(ptr) __builtin_object_size (ptr, 1)
+#define __bos0(ptr) __builtin_object_size (ptr, 0)
+#endif
diff -purN linux-2.6.12-rc4/include/linux/compiler.h linux-fortify/include/linux/compiler.h
--- linux-2.6.12-rc4/include/linux/compiler.h 2005-05-14 14:41:21.000000000 +0200
+++ linux-fortify/include/linux/compiler.h 2005-05-15 15:26:33.000000000 +0200
@@ -155,4 +155,13 @@ extern void __chk_io_ptr(void __iomem *)
#define __always_inline inline
#endif
+#ifndef __bos
+#define __bos(x) -1
+#endif
+
+#ifndef __bos0
+#define __bos0(x) -1
+#endif
+
+
#endif /* __LINUX_COMPILER_H */
diff -purN linux-2.6.12-rc4/include/linux/slab.h linux-fortify/include/linux/slab.h
--- linux-2.6.12-rc4/include/linux/slab.h 2005-05-14 14:41:21.000000000 +0200
+++ linux-fortify/include/linux/slab.h 2005-05-15 15:26:33.000000000 +0200
@@ -73,9 +73,9 @@ struct cache_sizes {
kmem_cache_t *cs_dmacachep;
};
extern struct cache_sizes malloc_sizes[];
-extern void *__kmalloc(size_t, unsigned int __nocast);
+extern __attribute__((malloc)) void *__kmalloc(size_t, unsigned int __nocast);
-static inline void *kmalloc(size_t size, unsigned int __nocast flags)
+static inline __attribute__((malloc)) void *kmalloc(size_t size, unsigned int __nocast flags)
{
if (__builtin_constant_p(size)) {
int i = 0;
diff -purN linux-2.6.12-rc4/include/linux/string.h linux-fortify/include/linux/string.h
--- linux-2.6.12-rc4/include/linux/string.h 2005-03-02 08:38:07.000000000 +0100
+++ linux-fortify/include/linux/string.h 2005-05-15 17:12:16.000000000 +0200
@@ -88,6 +88,96 @@ extern int memcmp(const void *,const voi
extern void * memchr(const void *,int,__kernel_size_t);
#endif
+
+#ifdef CONFIG_FORTIFY_SOURCE
+
+/*
+ * "fortified" variants of some of these functions that for certain cases make
+ * gcc emit code that checks for buffer overflows.
+ */
+
+#undef strcpy
+#undef __HAVE_ARCH_STRCPY
+#define strcpy(dest, src) \
+ ((__bos (dest) != (size_t) -1) \
+ ? __builtin___strcpy_chk (dest, src, __bos (dest)) \
+ : __strcpy_ichk (dest, src))
+static __always_inline char *
+__strcpy_ichk (char * __dest, const char * __src)
+{
+ return __builtin___strcpy_chk (__dest, __src, __bos (__dest));
+}
+
+#undef strncpy
+#undef __HAVE_ARCH_STRNCPY
+#define strncpy(dest, src, len) \
+ ((__bos (dest) != (size_t) -1) \
+ ? __builtin___strncpy_chk (dest, src, len, __bos (dest)) \
+ : __strncpy_ichk (dest, src, len))
+static __always_inline char *
+__strncpy_ichk (char * __dest, const char * __src, size_t __len)
+{
+ return __builtin___strncpy_chk (__dest, __src, __len, __bos (__dest));
+}
+
+#undef strcat
+#undef __HAVE_ARCH_STRCAT
+#define strcat(dest, src) \
+ ((__bos (dest) != (size_t) -1) \
+ ? __builtin___strcat_chk (dest, src, __bos (dest)) \
+ : __strcat_ichk (dest, src))
+static __always_inline char *
+__strcat_ichk (char * __dest, const char * __src)
+{
+ return __builtin___strcat_chk (__dest, __src, __bos (__dest));
+}
+
+#undef strncat
+#undef __HAVE_ARCH_STRNCAT
+#define strncat(dest, src, len) \
+ ((__bos (dest) != (size_t) -1) \
+ ? __builtin___strncat_chk (dest, src, len, __bos (dest)) \
+ : __strncat_ichk (dest, src, len))
+static __always_inline char *
+__strncat_ichk (char * __dest, const char * __src, size_t __len)
+{
+ return __builtin___strncat_chk (__dest, __src, __len, __bos (__dest));
+}
+
+#undef memcpy
+#define memcpy(dest, src, len) \
+ ((__bos0 (dest) != (size_t) -1) \
+ ? __builtin___memcpy_chk (dest, src, len, __bos0 (dest)) \
+ : __memcpy_ichk (dest, src, len))
+static __always_inline void *
+__memcpy_ichk (void * __dest, const void *__src, size_t __len)
+{
+ return __builtin___memcpy_chk (__dest, __src, __len, __bos0 (__dest));
+}
+
+/* memset(x,y,0) is a common typo; this dummy non-existent function is
+ * there to create a linker error in that case
+ */
+extern void __warn_memset_zero_len(void);
+
+#undef memset
+#define memset(dest, ch, len) \
+ (__builtin_constant_p (len) && (len) == 0 && (!__builtin_constant_p(ch) || ((ch)!=0)) \
+ ? (__warn_memset_zero_len (), (void) (ch), (void) (len), (void *) (dest)) \
+ : ((__bos0 (dest) != (size_t) -1) \
+ ? __builtin___memset_chk (dest, ch, len, __bos0 (dest)) \
+ : __memset_ichk (dest, ch, len)))
+
+static __always_inline void *
+__memset_ichk (void *__dest, int __ch, size_t __len)
+{
+ return __builtin___memset_chk (__dest, __ch, __len, __bos0 (__dest));
+}
+
+
+#endif
+
+
#ifdef __cplusplus
}
#endif
diff -purN linux-2.6.12-rc4/lib/Makefile linux-fortify/lib/Makefile
--- linux-2.6.12-rc4/lib/Makefile 2005-05-14 14:41:21.000000000 +0200
+++ linux-fortify/lib/Makefile 2005-05-15 15:26:33.000000000 +0200
@@ -18,6 +18,7 @@ endif
lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o
+lib-$(CONFIG_FORTIFY_SOURCE) += fortify.o
obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o
ifneq ($(CONFIG_HAVE_DEC_LOCK),y)
diff -purN linux-2.6.12-rc4/lib/fortify.c linux-fortify/lib/fortify.c
--- linux-2.6.12-rc4/lib/fortify.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-fortify/lib/fortify.c 2005-05-15 16:29:15.000000000 +0200
@@ -0,0 +1,292 @@
+/*
+ * Copyright (C) 1991, 1997, 2003, 2004 Free Software Foundation, Inc.
+ * Portions Copyright (C) 2005 Red Hat, Inc.
+ * Portions Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * (Several of these functions were copied from various FSF projects)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/module.h>
+
+
+void __chk_fail(void)
+{
+ printk("** kernel buffer overflow detected via application %s ***\n", current->comm);
+ panic("Aborting!\n");
+}
+EXPORT_SYMBOL_GPL(__chk_fail);
+
+void * __memcpy_chk (void *dstpp, const void* srcpp, size_t len, size_t dstlen)
+{
+ char *d = (char *) dstpp, *s = (char *) srcpp;
+
+ if (unlikely(dstlen < len))
+ __chk_fail ();
+
+ while (len--)
+ *d++ = *s++;
+
+ return d;
+}
+
+EXPORT_SYMBOL_GPL(__memcpy_chk);
+
+void * __memset_chk (void *dst, const int c, size_t len, size_t dstlen)
+{
+ char *d = (char *) dst;
+
+ if (unlikely(dstlen < len))
+ __chk_fail ();
+
+ while (len--)
+ *d++ = c;
+
+ return d;
+}
+
+EXPORT_SYMBOL_GPL(__memset_chk);
+
+/* Copy SRC to DEST with checking of destination buffer overflow. */
+char * __strcpy_chk (char *dest, const char *src, size_t destlen)
+{
+ char c;
+ char *s = (char *) src;
+ const ptrdiff_t off = dest - s;
+
+ while (__builtin_expect (destlen >= 4, 0))
+ {
+ c = s[0];
+ s[off] = c;
+ if (c == '\0')
+ return dest;
+ c = s[1];
+ s[off + 1] = c;
+ if (c == '\0')
+ return dest;
+ c = s[2];
+ s[off + 2] = c;
+ if (c == '\0')
+ return dest;
+ c = s[3];
+ s[off + 3] = c;
+ if (c == '\0')
+ return dest;
+ destlen -= 4;
+ s += 4;
+ }
+
+ do
+ {
+ if (__builtin_expect (destlen-- == 0, 0))
+ __chk_fail ();
+ c = *s;
+ *(s++ + off) = c;
+ }
+ while (c != '\0');
+
+ return dest;
+}
+
+EXPORT_SYMBOL_GPL(__strcpy_chk);
+
+
+char * __strcat_chk (char *dest, const char *src, size_t destlen)
+{
+ char *s1 = dest;
+ const char *s2 = src;
+ char c;
+
+ /* Find the end of the string. */
+ do
+ {
+ if (__builtin_expect (destlen-- == 0, 0))
+ __chk_fail ();
+ c = *s1++;
+ }
+ while (c != '\0');
+
+ /* Make S1 point before the next character, so we can increment
+ it while memory is read (wins on pipelined cpus). */
+ ++destlen;
+ s1 -= 2;
+
+ do
+ {
+ if (__builtin_expect (destlen-- == 0, 0))
+ __chk_fail ();
+ c = *s2++;
+ *++s1 = c;
+ }
+ while (c != '\0');
+
+ return dest;
+}
+
+EXPORT_SYMBOL_GPL(__strcat_chk);
+
+char * __strncat_chk (char *s1, const char *s2, size_t n, size_t s1len)
+{
+ char c;
+ char *s = s1;
+
+ /* Find the end of S1. */
+ do
+ {
+ if (__builtin_expect (s1len-- == 0, 0))
+ __chk_fail ();
+ c = *s1++;
+ }
+ while (c != '\0');
+
+ /* Make S1 point before next character, so we can increment
+ it while memory is read (wins on pipelined cpus). */
+ ++s1len;
+ s1 -= 2;
+
+ if (n >= 4)
+ {
+ size_t n4 = n >> 2;
+ do
+ {
+ if (__builtin_expect (s1len-- == 0, 0))
+ __chk_fail ();
+ c = *s2++;
+ *++s1 = c;
+ if (c == '\0')
+ return s;
+ if (__builtin_expect (s1len-- == 0, 0))
+ __chk_fail ();
+ c = *s2++;
+ *++s1 = c;
+ if (c == '\0')
+ return s;
+ if (__builtin_expect (s1len-- == 0, 0))
+ __chk_fail ();
+ c = *s2++;
+ *++s1 = c;
+ if (c == '\0')
+ return s;
+ if (__builtin_expect (s1len-- == 0, 0))
+ __chk_fail ();
+ c = *s2++;
+ *++s1 = c;
+ if (c == '\0')
+ return s;
+ } while (--n4 > 0);
+ n &= 3;
+ }
+
+ while (n > 0)
+ {
+ if (__builtin_expect (s1len-- == 0, 0))
+ __chk_fail ();
+ c = *s2++;
+ *++s1 = c;
+ if (c == '\0')
+ return s;
+ n--;
+ }
+
+ if (c != '\0')
+ {
+ if (__builtin_expect (s1len-- == 0, 0))
+ __chk_fail ();
+ *++s1 = '\0';
+ }
+
+ return s;
+}
+
+EXPORT_SYMBOL_GPL(__strncat_chk);
+
+
+char * __strncpy_chk (char *s1, const char *s2, size_t n, size_t s1len)
+{
+ char c;
+ char *s = s1;
+
+ if (__builtin_expect (s1len < n, 0))
+ __chk_fail ();
+
+ --s1;
+
+ if (n >= 4)
+ {
+ size_t n4 = n >> 2;
+
+ for (;;)
+ {
+ c = *s2++;
+ *++s1 = c;
+ if (c == '\0')
+ break;
+ c = *s2++;
+ *++s1 = c;
+ if (c == '\0')
+ break;
+ c = *s2++;
+ *++s1 = c;
+ if (c == '\0')
+ break;
+ c = *s2++;
+ *++s1 = c;
+ if (c == '\0')
+ break;
+ if (--n4 == 0)
+ goto last_chars;
+ }
+ n = n - (s1 - s) - 1;
+ if (n == 0)
+ return s;
+ goto zero_fill;
+ }
+
+ last_chars:
+ n &= 3;
+ if (n == 0)
+ return s;
+
+ do
+ {
+ c = *s2++;
+ *++s1 = c;
+ if (--n == 0)
+ return s;
+ }
+ while (c != '\0');
+
+ zero_fill:
+ do
+ *++s1 = '\0';
+ while (--n > 0);
+
+ return s;
+}
+
+EXPORT_SYMBOL_GPL(__strncpy_chk);
+
+
+void dummy(int n)
+{
+ char buf1[20];
+ char buf2[30];
+ memcpy(buf1, buf2, 30);
+ memcpy(buf1, buf2, n);
+}
diff -purN linux-2.6.12-rc4/lib/string.c linux-fortify/lib/string.c
--- linux-2.6.12-rc4/lib/string.c 2005-05-14 14:41:21.000000000 +0200
+++ linux-fortify/lib/string.c 2005-05-15 16:46:05.000000000 +0200
@@ -91,6 +91,7 @@ EXPORT_SYMBOL(strcpy);
* count, the remainder of @dest will be padded with %NUL.
*
*/
+#undef strncpy
char * strncpy(char * dest,const char *src,size_t count)
{
char *tmp = dest;
@@ -162,6 +163,7 @@ EXPORT_SYMBOL(strcat);
* Note that in contrast to strncpy, strncat ensures the result is
* terminated.
*/
+#undef strncat
char * strncat(char *dest, const char *src, size_t count)
{
char *tmp = dest;
@@ -449,6 +451,7 @@ EXPORT_SYMBOL(strsep);
*
* Do not use memset() to access IO space, use memset_io() instead.
*/
+#undef memset
void * memset(void * s,int c,size_t count)
{
char *xs = (char *) s;
@@ -471,6 +474,7 @@ EXPORT_SYMBOL(memset);
* You should not use this function to access IO space, use memcpy_toio()
* or memcpy_fromio() instead.
*/
+#undef memcpy
void * memcpy(void * dest,const void *src,size_t count)
{
char *tmp = (char *) dest, *s = (char *) src;
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: experimental kernel patch for FORTIFY_SOURCE in kernel space
2005-05-19 9:56 experimental kernel patch for FORTIFY_SOURCE in kernel space Arjan van de Ven
@ 2005-05-23 8:57 ` David Woodhouse
0 siblings, 0 replies; 2+ messages in thread
From: David Woodhouse @ 2005-05-23 8:57 UTC (permalink / raw)
To: Arjan van de Ven; +Cc: linuxppc-dev
On Thu, 2005-05-19 at 11:56 +0200, Arjan van de Ven wrote:
> There is somewhat of an architecture impact so before submitting it on
> lkml I'd want to ask feedback from more arches than just x86...
As discussed in IRC: Put the config option in lib/Kconfig.debug instead
of in arch/i386, and we need to do something about the string functions.
I just made the versions in lib/string.c weak; I doubt that's the best
answer.
Seems to work for me on PPC. Would certainly be nice to make it know
about kmalloc() though. I also made __chk_fail use BUG() instead of
panic().
--- linux-2.6.11/arch/i386/Kconfig.debug.fortifyppc 2005-05-19 13:18:08.000000000 +0100
+++ linux-2.6.11/arch/i386/Kconfig.debug 2005-05-19 13:18:24.000000000 +0100
@@ -59,14 +59,6 @@ config 4KSTACKS
on the VM subsystem for higher order allocations. This option
will also use IRQ stacks to compensate for the reduced stackspace.
-config FORTIFY_SOURCE
- bool "Enable limited buffer overflow checking"
- help
- If you say Y here the kernel will use a recent gcc feature that
- allows several key kernel primitives to check for buffer overflows
- when dealing with static buffers. Do not enable this feature unless
- you have a very recent gcc (version 4.1 or gccs from FC3, FC4, RHEL4)
-
config X86_FIND_SMP_CONFIG
bool
depends on X86_LOCAL_APIC || X86_VOYAGER
--- linux-2.6.11/include/asm-ppc/uaccess.h.fortifyppc 2005-05-19 12:09:40.000000000 +0100
+++ linux-2.6.11/include/asm-ppc/uaccess.h 2005-05-19 13:14:18.000000000 +0100
@@ -330,8 +330,18 @@ copy_to_user(void __user *to, const void
return n;
}
+extern void __chk_fail(void);
+
static inline unsigned long __copy_from_user(void *to, const void __user *from, unsigned long size)
{
+#ifdef CONFIG_FORTIFY_SOURCE
+ /*
+ * if we know the size of "to" then we can validate that we don't overrun the buffer.
+ * note that if __nbytes is known at compiletime this check is nicely optimized out
+ */
+ if (__bos0 (to) != (size_t) -1 && size > __bos0 (to))
+ __chk_fail();
+#endif
return __copy_tofrom_user((__force void __user *)to, from, size);
}
--- linux-2.6.11/lib/fortify.c.fortifyppc 2005-05-19 13:18:56.000000000 +0100
+++ linux-2.6.11/lib/fortify.c 2005-05-19 12:22:22.000000000 +0100
@@ -29,7 +29,7 @@
void __chk_fail(void)
{
printk("** kernel buffer overflow detected via application %s ***\n", current->comm);
- panic("Aborting!\n");
+ BUG();
}
EXPORT_SYMBOL_GPL(__chk_fail);
--- linux-2.6.11/lib/Kconfig.debug.fortifyppc 2005-05-19 13:17:36.000000000 +0100
+++ linux-2.6.11/lib/Kconfig.debug 2005-05-19 13:11:33.000000000 +0100
@@ -168,6 +168,16 @@ config DEBUG_FS
If unsure, say N.
+config FORTIFY_SOURCE
+ bool "Enable limited buffer overflow checking"
+ depends on DEBUG_KERNEL
+ help
+ If you say Y here the kernel will use a recent gcc feature that
+ allows several key kernel primitives to check for buffer overflows
+ when dealing with static buffers. Do not enable this feature unless
+ you have a very recent gcc (version 4.1 or gccs from FC3, FC4, RHEL4)
+
+
config FRAME_POINTER
bool "Compile the kernel with frame pointers"
depends on DEBUG_KERNEL && ((X86 && !X86_64) || CRIS || M68K || M68KNOMMU || FRV)
--- linux-2.6.11/lib/string.c.fortifyppc 2005-05-19 12:06:49.000000000 +0100
+++ linux-2.6.11/lib/string.c 2005-05-23 09:51:27.000000000 +0100
@@ -66,7 +66,7 @@ EXPORT_SYMBOL(strnicmp);
* @src: Where to copy the string from
*/
#undef strcpy
-char * strcpy(char * dest,const char *src)
+char * __attribute__((weak)) strcpy(char * dest,const char *src)
{
char *tmp = dest;
@@ -92,7 +92,7 @@ EXPORT_SYMBOL(strcpy);
*
*/
#undef strncpy
-char * strncpy(char * dest,const char *src,size_t count)
+char * __attribute__((weak)) strncpy(char * dest,const char *src,size_t count)
{
char *tmp = dest;
@@ -139,7 +139,7 @@ EXPORT_SYMBOL(strlcpy);
* @src: The string to append to it
*/
#undef strcat
-char * strcat(char * dest, const char * src)
+char * __attribute__((weak)) strcat(char * dest, const char * src)
{
char *tmp = dest;
@@ -164,7 +164,7 @@ EXPORT_SYMBOL(strcat);
* terminated.
*/
#undef strncat
-char * strncat(char *dest, const char *src, size_t count)
+char * __attribute__((weak)) strncat(char *dest, const char *src, size_t count)
{
char *tmp = dest;
--
dwmw2
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2005-05-23 9:00 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-05-19 9:56 experimental kernel patch for FORTIFY_SOURCE in kernel space Arjan van de Ven
2005-05-23 8:57 ` David Woodhouse
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).