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 | 26 | #define FORTIFY_WRITE 1 |
| 27 | 27 | |
| 28 | 28 | #define EACH_FORTIFY_FUNC(macro) \ |
| 29 | − macro(strncpy), \ | |
| 30 | 29 | macro(strnlen), \ |
| 31 | 30 | macro(strlen), \ |
| 32 | 31 | macro(strscpy), \ |
| @@ -95,8 +94,6 @@ extern char *__underlying_strcat(char *p, const char *q) __RENAME(strcat); · 62 unmodified lines | ||
| 95 | 94 | extern char *__underlying_strcpy(char *p, const char *q) __RENAME(strcpy); |
| 96 | 95 | extern __kernel_size_t __underlying_strlen(const char *p) __RENAME(strlen); |
| 97 | 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 | 97 | #else |
| 101 | 98 | |
| 102 | 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 | 117 | #define __underlying_strcpy __builtin_strcpy |
| 121 | 118 | #define __underlying_strlen __builtin_strlen |
| 122 | 119 | #define __underlying_strncat __builtin_strncat |
| 123 | −#define __underlying_strncpy __builtin_strncpy | |
| 124 | 120 | |
| 125 | 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 | 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 | 158 | extern __kernel_size_t __real_strnlen(const char *, __kernel_size_t) __RENAME(strnlen); |
| 207 | 159 | /** |
| 208 | 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 | 761 | #undef __underlying_strcpy |
| 810 | 762 | #undef __underlying_strlen |
| 811 | 763 | #undef __underlying_strncat |
| 812 | −#undef __underlying_strncpy | |
| 813 | 764 | |
| 814 | 765 | #undef POS |
| 815 | 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 | 67 | #ifndef __HAVE_ARCH_STRCPY |
| 68 | 68 | extern char * strcpy(char *,const char *); |
| 69 | 69 | #endif |
| 70 | −#ifndef __HAVE_ARCH_STRNCPY | |
| 71 | −extern char * strncpy(char *,const char *, __kernel_size_t); | |
| 72 | −#endif | |
| 73 | 70 | ssize_t sized_strscpy(char *, const char *, size_t); |
| 74 | 71 | |
| 75 | 72 | /* |