diff options
| -rw-r--r-- | include/stdio.h | 16 | ||||
| -rw-r--r-- | include/string.h | 38 | ||||
| -rw-r--r-- | include/strings.h | 10 |
3 files changed, 63 insertions, 1 deletions
diff --git a/include/stdio.h b/include/stdio.h index 070d4e5..285fe21 100644 --- a/include/stdio.h +++ b/include/stdio.h | |||
| @@ -6,17 +6,24 @@ | |||
| 6 | 6 | ||
| 7 | #if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && defined(__OPTIMIZE__) && __OPTIMIZE__ > 0 | 7 | #if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && defined(__OPTIMIZE__) && __OPTIMIZE__ > 0 |
| 8 | 8 | ||
| 9 | #define __errordecl(name, msg) extern void name(void) __attribute__((__error__(msg))) | ||
| 10 | |||
| 11 | __errordecl(__fgets_error, "fgets: buffer overflow detected"); | ||
| 9 | static inline __attribute__ ((always_inline)) | 12 | static inline __attribute__ ((always_inline)) |
| 10 | char * | 13 | char * |
| 11 | __fortify_fgets(char *s, int n, FILE *fp) | 14 | __fortify_fgets(char *s, int n, FILE *fp) |
| 12 | { | 15 | { |
| 13 | size_t bos = __builtin_object_size(s, 0); | 16 | size_t bos = __builtin_object_size(s, 0); |
| 14 | 17 | ||
| 18 | if (__builtin_constant_p(n) && (size_t)n > bos) | ||
| 19 | __fgets_error(); | ||
| 20 | |||
| 15 | if ((size_t)n > bos) | 21 | if ((size_t)n > bos) |
| 16 | __builtin_trap(); | 22 | __builtin_trap(); |
| 17 | return fgets(s, n, fp); | 23 | return fgets(s, n, fp); |
| 18 | } | 24 | } |
| 19 | 25 | ||
| 26 | __errordecl(__vsnprintf_error, "vsnprintf: buffer overflow detected"); | ||
| 20 | static inline | 27 | static inline |
| 21 | __attribute__ ((always_inline)) | 28 | __attribute__ ((always_inline)) |
| 22 | __attribute__ ((__format__ (printf, 3, 0))) | 29 | __attribute__ ((__format__ (printf, 3, 0))) |
| @@ -27,6 +34,9 @@ __fortify_vsnprintf(char *__restrict s, size_t n, const char *__restrict fmt, | |||
| 27 | { | 34 | { |
| 28 | size_t bos = __builtin_object_size(s, 0); | 35 | size_t bos = __builtin_object_size(s, 0); |
| 29 | 36 | ||
| 37 | if (__builtin_constant_p(n) && n > bos) | ||
| 38 | __vsnprintf_error(); | ||
| 39 | |||
| 30 | if (n > bos) | 40 | if (n > bos) |
| 31 | __builtin_trap(); | 41 | __builtin_trap(); |
| 32 | return vsnprintf(s, n, fmt, ap); | 42 | return vsnprintf(s, n, fmt, ap); |
| @@ -36,13 +46,17 @@ __fortify_vsnprintf(char *__restrict s, size_t n, const char *__restrict fmt, | |||
| 36 | #define fgets(s, n, fp) __fortify_fgets(s, n, fp) | 46 | #define fgets(s, n, fp) __fortify_fgets(s, n, fp) |
| 37 | #undef vsnprintf | 47 | #undef vsnprintf |
| 38 | #define vsnprintf(s, n, fmt, ap) __fortify_vsnprintf(s, n, fmt, ap) | 48 | #define vsnprintf(s, n, fmt, ap) __fortify_vsnprintf(s, n, fmt, ap) |
| 49 | |||
| 50 | __errordecl(__snprintf_error, "snprintf: buffer overflow detected"); | ||
| 39 | #undef snprintf | 51 | #undef snprintf |
| 40 | #define snprintf(s, n, fmt, ...) ({ \ | 52 | #define snprintf(s, n, fmt, ...) ({ \ |
| 41 | size_t _n = (n); \ | 53 | size_t _n = (n); \ |
| 42 | size_t bos = __builtin_object_size(s, 0); \ | 54 | size_t bos = __builtin_object_size(s, 0); \ |
| 55 | if (__builtin_constant_p(_n) && _n > bos) \ | ||
| 56 | __snprintf_error(); \ | ||
| 43 | if (_n > bos) \ | 57 | if (_n > bos) \ |
| 44 | __builtin_trap(); \ | 58 | __builtin_trap(); \ |
| 45 | snprintf(s, _n, fmt, __VA_ARGS__); \ | 59 | snprintf(s, _n, fmt, ## __VA_ARGS__); \ |
| 46 | }) | 60 | }) |
| 47 | 61 | ||
| 48 | #endif | 62 | #endif |
diff --git a/include/string.h b/include/string.h index 107df9b..e464eab 100644 --- a/include/string.h +++ b/include/string.h | |||
| @@ -6,6 +6,9 @@ | |||
| 6 | 6 | ||
| 7 | #if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && defined(__OPTIMIZE__) && __OPTIMIZE__ > 0 | 7 | #if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && defined(__OPTIMIZE__) && __OPTIMIZE__ > 0 |
| 8 | 8 | ||
| 9 | #define __errordecl(name, msg) extern void name(void) __attribute__((__error__(msg))) | ||
| 10 | |||
| 11 | __errordecl(__memcpy_error, "memcpy: buffer overflow detected"); | ||
| 9 | static inline __attribute__ ((always_inline)) | 12 | static inline __attribute__ ((always_inline)) |
| 10 | void * | 13 | void * |
| 11 | __fortify_memcpy(void *__restrict dest, const void *__restrict src, size_t n) | 14 | __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) | |||
| 14 | char *d = dest; | 17 | char *d = dest; |
| 15 | const char *s = src; | 18 | const char *s = src; |
| 16 | 19 | ||
| 20 | if (__builtin_constant_p(n) && n > bos) | ||
| 21 | __memcpy_error(); | ||
| 22 | |||
| 17 | /* trap if pointers are overlapping */ | 23 | /* trap if pointers are overlapping */ |
| 18 | if ((d <= s && d + n > s) || | 24 | if ((d <= s && d + n > s) || |
| 19 | (s <= d && s + n > d)) | 25 | (s <= d && s + n > d)) |
| @@ -23,23 +29,31 @@ __fortify_memcpy(void *__restrict dest, const void *__restrict src, size_t n) | |||
| 23 | return memcpy(dest, src, n); | 29 | return memcpy(dest, src, n); |
| 24 | } | 30 | } |
| 25 | 31 | ||
| 32 | __errordecl(__memmove_error, "memmove: buffer overflow detected"); | ||
| 26 | static inline __attribute__ ((always_inline)) | 33 | static inline __attribute__ ((always_inline)) |
| 27 | void * | 34 | void * |
| 28 | __fortify_memmove(void *__restrict dest, const void *__restrict src, size_t n) | 35 | __fortify_memmove(void *__restrict dest, const void *__restrict src, size_t n) |
| 29 | { | 36 | { |
| 30 | size_t bos = __builtin_object_size(dest, 0); | 37 | size_t bos = __builtin_object_size(dest, 0); |
| 31 | 38 | ||
| 39 | if (__builtin_constant_p(n) && n > bos) | ||
| 40 | __memmove_error(); | ||
| 41 | |||
| 32 | if (n > bos) | 42 | if (n > bos) |
| 33 | __builtin_trap(); | 43 | __builtin_trap(); |
| 34 | return memmove(dest, src, n); | 44 | return memmove(dest, src, n); |
| 35 | } | 45 | } |
| 36 | 46 | ||
| 47 | __errordecl(__memset_error, "memset: buffer overflow detected"); | ||
| 37 | static inline __attribute__ ((always_inline)) | 48 | static inline __attribute__ ((always_inline)) |
| 38 | void * | 49 | void * |
| 39 | __fortify_memset(void *dest, int c, size_t n) | 50 | __fortify_memset(void *dest, int c, size_t n) |
| 40 | { | 51 | { |
| 41 | size_t bos = __builtin_object_size(dest, 0); | 52 | size_t bos = __builtin_object_size(dest, 0); |
| 42 | 53 | ||
| 54 | if (__builtin_constant_p(n) && n > bos) | ||
| 55 | __memset_error(); | ||
| 56 | |||
| 43 | if (n > bos) | 57 | if (n > bos) |
| 44 | __builtin_trap(); | 58 | __builtin_trap(); |
| 45 | return memset(dest, c, n); | 59 | return memset(dest, c, n); |
| @@ -56,12 +70,16 @@ __fortify_stpcpy(char *__restrict dest, const char *__restrict src) | |||
| 56 | return stpcpy(dest, src); | 70 | return stpcpy(dest, src); |
| 57 | } | 71 | } |
| 58 | 72 | ||
| 73 | __errordecl(__stpncpy_error, "stpncpy: buffer overflow detected"); | ||
| 59 | static inline __attribute__ ((always_inline)) | 74 | static inline __attribute__ ((always_inline)) |
| 60 | char * | 75 | char * |
| 61 | __fortify_stpncpy(char *__restrict dest, const char *__restrict src, size_t n) | 76 | __fortify_stpncpy(char *__restrict dest, const char *__restrict src, size_t n) |
| 62 | { | 77 | { |
| 63 | size_t bos = __builtin_object_size(dest, 0); | 78 | size_t bos = __builtin_object_size(dest, 0); |
| 64 | 79 | ||
| 80 | if (__builtin_costant_p(n) && n > bos) | ||
| 81 | __stpncpy_error(); | ||
| 82 | |||
| 65 | if (n > bos) | 83 | if (n > bos) |
| 66 | __builtin_trap(); | 84 | __builtin_trap(); |
| 67 | return stpncpy(dest, src, n); | 85 | return stpncpy(dest, src, n); |
| @@ -89,6 +107,7 @@ __fortify_strcpy(char *__restrict dest, const char *__restrict src) | |||
| 89 | return strcpy(dest, src); | 107 | return strcpy(dest, src); |
| 90 | } | 108 | } |
| 91 | 109 | ||
| 110 | __errordecl(__strncat_error, "strncat: buffer overflow detected"); | ||
| 92 | static inline __attribute__ ((always_inline)) | 111 | static inline __attribute__ ((always_inline)) |
| 93 | char * | 112 | char * |
| 94 | __fortify_strncat(char *__restrict dest, const char *__restrict src, size_t n) | 113 | __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) | |||
| 96 | size_t bos = __builtin_object_size(dest, 0); | 115 | size_t bos = __builtin_object_size(dest, 0); |
| 97 | size_t slen, dlen; | 116 | size_t slen, dlen; |
| 98 | 117 | ||
| 118 | if (__builtin_constant_p(n) && n > bos) | ||
| 119 | __strncat_error(); | ||
| 120 | |||
| 99 | if (n > bos) { | 121 | if (n > bos) { |
| 100 | slen = strlen(src); | 122 | slen = strlen(src); |
| 101 | dlen = strlen(dest); | 123 | dlen = strlen(dest); |
| @@ -107,24 +129,32 @@ __fortify_strncat(char *__restrict dest, const char *__restrict src, size_t n) | |||
| 107 | return strncat(dest, src, n); | 129 | return strncat(dest, src, n); |
| 108 | } | 130 | } |
| 109 | 131 | ||
| 132 | __errordecl(__strncpy_error, "strncpy: buffer overflow detected"); | ||
| 110 | static inline __attribute__ ((always_inline)) | 133 | static inline __attribute__ ((always_inline)) |
| 111 | char * | 134 | char * |
| 112 | __fortify_strncpy(char *__restrict dest, const char *__restrict src, size_t n) | 135 | __fortify_strncpy(char *__restrict dest, const char *__restrict src, size_t n) |
| 113 | { | 136 | { |
| 114 | size_t bos = __builtin_object_size(dest, 0); | 137 | size_t bos = __builtin_object_size(dest, 0); |
| 115 | 138 | ||
| 139 | if (__builtin_constant_p(n) && n > bos) | ||
| 140 | __strncpy_error(); | ||
| 141 | |||
| 116 | if (n > bos) | 142 | if (n > bos) |
| 117 | __builtin_trap(); | 143 | __builtin_trap(); |
| 118 | return strncpy(dest, src, n); | 144 | return strncpy(dest, src, n); |
| 119 | } | 145 | } |
| 120 | 146 | ||
| 121 | #ifdef _GNU_SOURCE | 147 | #ifdef _GNU_SOURCE |
| 148 | __errordecl(__mempcpy_error, "mempcpy: buffer overflow detected"); | ||
| 122 | static inline __attribute__ ((always_inline)) | 149 | static inline __attribute__ ((always_inline)) |
| 123 | void * | 150 | void * |
| 124 | __fortify_mempcpy(void *__restrict dest, const void *__restrict src, size_t n) | 151 | __fortify_mempcpy(void *__restrict dest, const void *__restrict src, size_t n) |
| 125 | { | 152 | { |
| 126 | size_t bos = __builtin_object_size(dest, 0); | 153 | size_t bos = __builtin_object_size(dest, 0); |
| 127 | 154 | ||
| 155 | if (__builtin_constant_p(n) && n > bos) | ||
| 156 | __mempcpy_error(); | ||
| 157 | |||
| 128 | if (n > bos) | 158 | if (n > bos) |
| 129 | __builtin_trap(); | 159 | __builtin_trap(); |
| 130 | return mempcpy(dest, src, n); | 160 | return mempcpy(dest, src, n); |
| @@ -132,23 +162,31 @@ __fortify_mempcpy(void *__restrict dest, const void *__restrict src, size_t n) | |||
| 132 | #endif | 162 | #endif |
| 133 | 163 | ||
| 134 | #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) | 164 | #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) |
| 165 | __errordecl(__strlcat_error, "strlcat: buffer overflow detected"); | ||
| 135 | static inline __attribute__ ((always_inline)) | 166 | static inline __attribute__ ((always_inline)) |
| 136 | size_t | 167 | size_t |
| 137 | __fortify_strlcat(char *__restrict dest, const char *__restrict src, size_t n) | 168 | __fortify_strlcat(char *__restrict dest, const char *__restrict src, size_t n) |
| 138 | { | 169 | { |
| 139 | size_t bos = __builtin_object_size(dest, 0); | 170 | size_t bos = __builtin_object_size(dest, 0); |
| 140 | 171 | ||
| 172 | if (__builtin_constant_p(n) && n > bos) | ||
| 173 | __strlcat_error(); | ||
| 174 | |||
| 141 | if (n > bos) | 175 | if (n > bos) |
| 142 | __builtin_trap(); | 176 | __builtin_trap(); |
| 143 | return strlcat(dest, src, n); | 177 | return strlcat(dest, src, n); |
| 144 | } | 178 | } |
| 145 | 179 | ||
| 180 | __errordecl(__strlcpy_error, "strlcpy: buffer overflow detected"); | ||
| 146 | static inline __attribute__ ((always_inline)) | 181 | static inline __attribute__ ((always_inline)) |
| 147 | size_t | 182 | size_t |
| 148 | __fortify_strlcpy(char *__restrict dest, const char *__restrict src, size_t n) | 183 | __fortify_strlcpy(char *__restrict dest, const char *__restrict src, size_t n) |
| 149 | { | 184 | { |
| 150 | size_t bos = __builtin_object_size(dest, 0); | 185 | size_t bos = __builtin_object_size(dest, 0); |
| 151 | 186 | ||
| 187 | if (__builtin_constant_p(n) && n > bos) | ||
| 188 | __strlcpy_error(); | ||
| 189 | |||
| 152 | if (n > bos) | 190 | if (n > bos) |
| 153 | __builtin_trap(); | 191 | __builtin_trap(); |
| 154 | return strlcpy(dest, src, n); | 192 | return strlcpy(dest, src, n); |
diff --git a/include/strings.h b/include/strings.h index c2f3bcd..4086fe4 100644 --- a/include/strings.h +++ b/include/strings.h | |||
| @@ -6,26 +6,36 @@ | |||
| 6 | 6 | ||
| 7 | #if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && defined(__OPTIMIZE__) && __OPTIMIZE__ > 0 | 7 | #if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && defined(__OPTIMIZE__) && __OPTIMIZE__ > 0 |
| 8 | 8 | ||
| 9 | #define __errordecl(name, msg) extern void name(void) __attribute__((__error__(msg))) | ||
| 10 | |||
| 9 | #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_POSIX_SOURCE) \ | 11 | #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_POSIX_SOURCE) \ |
| 10 | || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE+0 < 200809L) \ | 12 | || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE+0 < 200809L) \ |
| 11 | || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE+0 < 700) | 13 | || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE+0 < 700) |
| 14 | __errordecl(__bcopy_error, "bcopy: buffer overflow detected"); | ||
| 12 | static inline __attribute__ ((always_inline)) | 15 | static inline __attribute__ ((always_inline)) |
| 13 | void | 16 | void |
| 14 | __fortify_bcopy(const void *__restrict src, void *__restrict dest, size_t n) | 17 | __fortify_bcopy(const void *__restrict src, void *__restrict dest, size_t n) |
| 15 | { | 18 | { |
| 16 | size_t bos = __builtin_object_size(dest, 0); | 19 | size_t bos = __builtin_object_size(dest, 0); |
| 17 | 20 | ||
| 21 | if (__builtin_constant_p(n) && n > bos) | ||
| 22 | __bcopy_error(); | ||
| 23 | |||
| 18 | if (n > bos) | 24 | if (n > bos) |
| 19 | __builtin_trap(); | 25 | __builtin_trap(); |
| 20 | return bcopy(src, dest, n); | 26 | return bcopy(src, dest, n); |
| 21 | } | 27 | } |
| 22 | 28 | ||
| 29 | __errordecl(__bzero_error, "bzero: buffer overflow detected"); | ||
| 23 | static inline __attribute__ ((always_inline)) | 30 | static inline __attribute__ ((always_inline)) |
| 24 | void | 31 | void |
| 25 | __fortify_bzero(void *src, size_t n) | 32 | __fortify_bzero(void *src, size_t n) |
| 26 | { | 33 | { |
| 27 | size_t bos = __builtin_object_size(src, 0); | 34 | size_t bos = __builtin_object_size(src, 0); |
| 28 | 35 | ||
| 36 | if (__builtin_constant_p(n) && n > bos) | ||
| 37 | __bzero_error(); | ||
| 38 | |||
| 29 | if (n > bos) | 39 | if (n > bos) |
| 30 | __builtin_trap(); | 40 | __builtin_trap(); |
| 31 | return bzero(src, n); | 41 | return bzero(src, n); |
