fortify-headers

standalone fortify-source implementation
git clone git://git.2f30.org/fortify-headers.git
Log | Files | Refs | README | LICENSE

commit 474f2887ce756bb5a14defb25e67b89678be0b8c
parent 3effc6dacea8b8ed0edab8ad93a902fa05bafde2
Author: sin <sin@2f30.org>
Date:   Thu Jan 29 12:42:41 +0000

Add compile-time checks as well

Diffstat:
include/stdio.h | 16+++++++++++++++-
include/string.h | 38++++++++++++++++++++++++++++++++++++++
include/strings.h | 10++++++++++
3 files changed, 63 insertions(+), 1 deletion(-)
diff --git a/include/stdio.h b/include/stdio.h @@ -6,17 +6,24 @@ #if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && defined(__OPTIMIZE__) && __OPTIMIZE__ > 0 +#define __errordecl(name, msg) extern void name(void) __attribute__((__error__(msg))) + +__errordecl(__fgets_error, "fgets: buffer overflow detected"); static inline __attribute__ ((always_inline)) char * __fortify_fgets(char *s, int n, FILE *fp) { size_t bos = __builtin_object_size(s, 0); + if (__builtin_constant_p(n) && (size_t)n > bos) + __fgets_error(); + if ((size_t)n > bos) __builtin_trap(); return fgets(s, n, fp); } +__errordecl(__vsnprintf_error, "vsnprintf: buffer overflow detected"); static inline __attribute__ ((always_inline)) __attribute__ ((__format__ (printf, 3, 0))) @@ -27,6 +34,9 @@ __fortify_vsnprintf(char *__restrict s, size_t n, const char *__restrict fmt, { size_t bos = __builtin_object_size(s, 0); + if (__builtin_constant_p(n) && n > bos) + __vsnprintf_error(); + if (n > bos) __builtin_trap(); return vsnprintf(s, n, fmt, ap); @@ -36,13 +46,17 @@ __fortify_vsnprintf(char *__restrict s, size_t n, const char *__restrict fmt, #define fgets(s, n, fp) __fortify_fgets(s, n, fp) #undef vsnprintf #define vsnprintf(s, n, fmt, ap) __fortify_vsnprintf(s, n, fmt, ap) + +__errordecl(__snprintf_error, "snprintf: buffer overflow detected"); #undef snprintf #define snprintf(s, n, fmt, ...) ({ \ size_t _n = (n); \ size_t bos = __builtin_object_size(s, 0); \ + if (__builtin_constant_p(_n) && _n > bos) \ + __snprintf_error(); \ if (_n > bos) \ __builtin_trap(); \ - snprintf(s, _n, fmt, __VA_ARGS__); \ + snprintf(s, _n, fmt, ## __VA_ARGS__); \ }) #endif diff --git a/include/string.h b/include/string.h @@ -6,6 +6,9 @@ #if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && defined(__OPTIMIZE__) && __OPTIMIZE__ > 0 +#define __errordecl(name, msg) extern void name(void) __attribute__((__error__(msg))) + +__errordecl(__memcpy_error, "memcpy: buffer overflow detected"); static inline __attribute__ ((always_inline)) void * __fortify_memcpy(void *__restrict dest, const void *__restrict src, size_t n) @@ -14,6 +17,9 @@ __fortify_memcpy(void *__restrict dest, const void *__restrict src, size_t n) char *d = dest; const char *s = src; + if (__builtin_constant_p(n) && n > bos) + __memcpy_error(); + /* trap if pointers are overlapping */ if ((d <= s && d + n > s) || (s <= d && s + n > d)) @@ -23,23 +29,31 @@ __fortify_memcpy(void *__restrict dest, const void *__restrict src, size_t n) return memcpy(dest, src, n); } +__errordecl(__memmove_error, "memmove: buffer overflow detected"); static inline __attribute__ ((always_inline)) void * __fortify_memmove(void *__restrict dest, const void *__restrict src, size_t n) { size_t bos = __builtin_object_size(dest, 0); + if (__builtin_constant_p(n) && n > bos) + __memmove_error(); + if (n > bos) __builtin_trap(); return memmove(dest, src, n); } +__errordecl(__memset_error, "memset: buffer overflow detected"); static inline __attribute__ ((always_inline)) void * __fortify_memset(void *dest, int c, size_t n) { size_t bos = __builtin_object_size(dest, 0); + if (__builtin_constant_p(n) && n > bos) + __memset_error(); + if (n > bos) __builtin_trap(); return memset(dest, c, n); @@ -56,12 +70,16 @@ __fortify_stpcpy(char *__restrict dest, const char *__restrict src) return stpcpy(dest, src); } +__errordecl(__stpncpy_error, "stpncpy: buffer overflow detected"); static inline __attribute__ ((always_inline)) char * __fortify_stpncpy(char *__restrict dest, const char *__restrict src, size_t n) { size_t bos = __builtin_object_size(dest, 0); + if (__builtin_costant_p(n) && n > bos) + __stpncpy_error(); + if (n > bos) __builtin_trap(); return stpncpy(dest, src, n); @@ -89,6 +107,7 @@ __fortify_strcpy(char *__restrict dest, const char *__restrict src) return strcpy(dest, src); } +__errordecl(__strncat_error, "strncat: buffer overflow detected"); static inline __attribute__ ((always_inline)) char * __fortify_strncat(char *__restrict dest, const char *__restrict src, size_t n) @@ -96,6 +115,9 @@ __fortify_strncat(char *__restrict dest, const char *__restrict src, size_t n) size_t bos = __builtin_object_size(dest, 0); size_t slen, dlen; + if (__builtin_constant_p(n) && n > bos) + __strncat_error(); + if (n > bos) { slen = strlen(src); dlen = strlen(dest); @@ -107,24 +129,32 @@ __fortify_strncat(char *__restrict dest, const char *__restrict src, size_t n) return strncat(dest, src, n); } +__errordecl(__strncpy_error, "strncpy: buffer overflow detected"); static inline __attribute__ ((always_inline)) char * __fortify_strncpy(char *__restrict dest, const char *__restrict src, size_t n) { size_t bos = __builtin_object_size(dest, 0); + if (__builtin_constant_p(n) && n > bos) + __strncpy_error(); + if (n > bos) __builtin_trap(); return strncpy(dest, src, n); } #ifdef _GNU_SOURCE +__errordecl(__mempcpy_error, "mempcpy: buffer overflow detected"); static inline __attribute__ ((always_inline)) void * __fortify_mempcpy(void *__restrict dest, const void *__restrict src, size_t n) { size_t bos = __builtin_object_size(dest, 0); + if (__builtin_constant_p(n) && n > bos) + __mempcpy_error(); + if (n > bos) __builtin_trap(); return mempcpy(dest, src, n); @@ -132,23 +162,31 @@ __fortify_mempcpy(void *__restrict dest, const void *__restrict src, size_t n) #endif #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +__errordecl(__strlcat_error, "strlcat: buffer overflow detected"); static inline __attribute__ ((always_inline)) size_t __fortify_strlcat(char *__restrict dest, const char *__restrict src, size_t n) { size_t bos = __builtin_object_size(dest, 0); + if (__builtin_constant_p(n) && n > bos) + __strlcat_error(); + if (n > bos) __builtin_trap(); return strlcat(dest, src, n); } +__errordecl(__strlcpy_error, "strlcpy: buffer overflow detected"); static inline __attribute__ ((always_inline)) size_t __fortify_strlcpy(char *__restrict dest, const char *__restrict src, size_t n) { size_t bos = __builtin_object_size(dest, 0); + if (__builtin_constant_p(n) && n > bos) + __strlcpy_error(); + if (n > bos) __builtin_trap(); return strlcpy(dest, src, n); diff --git a/include/strings.h b/include/strings.h @@ -6,26 +6,36 @@ #if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && defined(__OPTIMIZE__) && __OPTIMIZE__ > 0 +#define __errordecl(name, msg) extern void name(void) __attribute__((__error__(msg))) + #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_POSIX_SOURCE) \ || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE+0 < 200809L) \ || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE+0 < 700) +__errordecl(__bcopy_error, "bcopy: buffer overflow detected"); static inline __attribute__ ((always_inline)) void __fortify_bcopy(const void *__restrict src, void *__restrict dest, size_t n) { size_t bos = __builtin_object_size(dest, 0); + if (__builtin_constant_p(n) && n > bos) + __bcopy_error(); + if (n > bos) __builtin_trap(); return bcopy(src, dest, n); } +__errordecl(__bzero_error, "bzero: buffer overflow detected"); static inline __attribute__ ((always_inline)) void __fortify_bzero(void *src, size_t n) { size_t bos = __builtin_object_size(src, 0); + if (__builtin_constant_p(n) && n > bos) + __bzero_error(); + if (n > bos) __builtin_trap(); return bzero(src, n);