strncpy() has been a persistent source of bugs due to its ambiguous intended usage and frequently counter-intuitive semantics: it may not NUL-terminate the destination, and it unconditionally zero-pads to the full length, which isn't always needed. All former callers have been migrated[1] to: - strscpy() for NUL-terminated destinations - strscpy_pad() for NUL-terminated destinations needing zero-padding - strtomem_pad() for non-NUL-terminated fixed-width fields - memcpy_and_pad() for bounded copies with explicit padding - memcpy() for known-length copies Remove the generic implementation, its declaration, the FORTIFY_SOURCE wrapper, and associated tests.
Showing the changes to include (2 of 8 files). Show all
Unified · Split
| @@ -26,7 +26,6 @@ · 25 unmodified lines | |||
| 26 | #define FORTIFY_WRITE 1 | 26 | #define FORTIFY_WRITE 1 |
| 27 | 27 | ||
| 28 | #define EACH_FORTIFY_FUNC(macro) \ | 28 | #define EACH_FORTIFY_FUNC(macro) \ |
| 29 | macro(strncpy), \ | ||
| 30 | macro(strnlen), \ | 29 | macro(strnlen), \ |
| 31 | macro(strlen), \ | 30 | macro(strlen), \ |
| 32 | macro(strscpy), \ | 31 | macro(strscpy), \ |
| @@ -95,8 +94,6 @@ extern char *__underlying_strcat(char *p, const char *q) __RENAME(strcat); · 62 unmodified lines | |||
| 95 | extern char *__underlying_strcpy(char *p, const char *q) __RENAME(strcpy); | 94 | extern char *__underlying_strcpy(char *p, const char *q) __RENAME(strcpy); |
| 96 | extern __kernel_size_t __underlying_strlen(const char *p) __RENAME(strlen); | 95 | extern __kernel_size_t __underlying_strlen(const char *p) __RENAME(strlen); |
| 97 | extern char *__underlying_strncat(char *p, const char *q, __kernel_size_t count) __RENAME(strncat); | 96 | extern char *__underlying_strncat(char *p, const char *q, __kernel_size_t count) __RENAME(strncat); |
| 98 | extern char *__underlying_strncpy(char *p, const char *q, __kernel_size_t size) __RENAME(strncpy); | ||
| 99 | |||
| 100 | #else | 97 | #else |
| 101 | 98 | ||
| 102 | #if defined(__SANITIZE_MEMORY__) | 99 | #if defined(__SANITIZE_MEMORY__) |
| @@ -120,7 +117,6 @@ extern char *__underlying_strncpy(char *p, const char *q, __kernel_size_t size) · 17 unmodified lines | |||
| 120 | #define __underlying_strcpy __builtin_strcpy | 117 | #define __underlying_strcpy __builtin_strcpy |
| 121 | #define __underlying_strlen __builtin_strlen | 118 | #define __underlying_strlen __builtin_strlen |
| 122 | #define __underlying_strncat __builtin_strncat | 119 | #define __underlying_strncat __builtin_strncat |
| 123 | #define __underlying_strncpy __builtin_strncpy | ||
| 124 | 120 | ||
| 125 | #endif | 121 | #endif |
| 126 | 122 | ||
| @@ -159,50 +155,6 @@ extern char *__underlying_strncpy(char *p, const char *q, __kernel_size_t size) · 32 unmodified lines | |||
| 159 | (bounds) < (length) \ | 155 | (bounds) < (length) \ |
| 160 | ) | 156 | ) |
| 161 | 157 | ||
| 162 | /** | ||
| 163 | * strncpy - Copy a string to memory with non-guaranteed NUL padding | ||
| 164 | * | ||
| 165 | * @p: pointer to destination of copy | ||
| 166 | * @q: pointer to NUL-terminated source string to copy | ||
| 167 | * @size: bytes to write at @p | ||
| 168 | * | ||
| 169 | * If strlen(@q) >= @size, the copy of @q will stop after @size bytes, | ||
| 170 | * and @p will NOT be NUL-terminated | ||
| 171 | * | ||
| 172 | * If strlen(@q) < @size, following the copy of @q, trailing NUL bytes | ||
| 173 | * will be written to @p until @size total bytes have been written. | ||
| 174 | * | ||
| 175 | * Do not use this function. While FORTIFY_SOURCE tries to avoid | ||
| 176 | * over-reads of @q, it cannot defend against writing unterminated | ||
| 177 | * results to @p. Using strncpy() remains ambiguous and fragile. | ||
| 178 | * Instead, please choose an alternative, so that the expectation | ||
| 179 | * of @p's contents is unambiguous: | ||
| 180 | * | ||
| 181 | * +--------------------+--------------------+------------+ | ||
| 182 | * | **p** needs to be: | padded to **size** | not padded | | ||
| 183 | * +====================+====================+============+ | ||
| 184 | * | NUL-terminated | strscpy_pad() | strscpy() | | ||
| 185 | * +--------------------+--------------------+------------+ | ||
| 186 | * | not NUL-terminated | strtomem_pad() | strtomem() | | ||
| 187 | * +--------------------+--------------------+------------+ | ||
| 188 | * | ||
| 189 | * Note strscpy*()'s differing return values for detecting truncation, | ||
| 190 | * and strtomem*()'s expectation that the destination is marked with | ||
| 191 | * __nonstring when it is a character array. | ||
| 192 | * | ||
| 193 | */ | ||
| 194 | __FORTIFY_INLINE __diagnose_as(__builtin_strncpy, 1, 2, 3) | ||
| 195 | char *strncpy(char * const POS p, const char *q, __kernel_size_t size) | ||
| 196 | { | ||
| 197 | const size_t p_size = __member_size(p); | ||
| 198 | |||
| 199 | if (__compiletime_lessthan(p_size, size)) | ||
| 200 | __write_overflow(); | ||
| 201 | if (p_size < size) | ||
| 202 | fortify_panic(FORTIFY_FUNC_strncpy, FORTIFY_WRITE, p_size, size, p); | ||
| 203 | return __underlying_strncpy(p, q, size); | ||
| 204 | } | ||
| 205 | |||
| 206 | extern __kernel_size_t __real_strnlen(const char *, __kernel_size_t) __RENAME(strnlen); | 158 | extern __kernel_size_t __real_strnlen(const char *, __kernel_size_t) __RENAME(strnlen); |
| 207 | /** | 159 | /** |
| 208 | * strnlen - Return bounded count of characters in a NUL-terminated string | 160 | * strnlen - Return bounded count of characters in a NUL-terminated string |
| @@ -809,7 +761,6 @@ char *strcpy(char * const POS p, const char * const POS q) · 600 unmodified lines | |||
| 809 | #undef __underlying_strcpy | 761 | #undef __underlying_strcpy |
| 810 | #undef __underlying_strlen | 762 | #undef __underlying_strlen |
| 811 | #undef __underlying_strncat | 763 | #undef __underlying_strncat |
| 812 | #undef __underlying_strncpy | ||
| 813 | 764 | ||
| 814 | #undef POS | 765 | #undef POS |
| 815 | #undef POS0 | 766 | #undef POS0 |
| @@ -67,9 +67,6 @@ void *vmemdup_array_user(const void __user *src, size_t n, size_t size) · 66 unmodified lines | |||
| 67 | #ifndef __HAVE_ARCH_STRCPY | 67 | #ifndef __HAVE_ARCH_STRCPY |
| 68 | extern char * strcpy(char *,const char *); | 68 | extern char * strcpy(char *,const char *); |
| 69 | #endif | 69 | #endif |
| 70 | #ifndef __HAVE_ARCH_STRNCPY | ||
| 71 | extern char * strncpy(char *,const char *, __kernel_size_t); | ||
| 72 | #endif | ||
| 73 | ssize_t sized_strscpy(char *, const char *, size_t); | 70 | ssize_t sized_strscpy(char *, const char *, size_t); |
| 74 | 71 | ||
| 75 | /* | 72 | /* |