History

string: Remove strncpy() from the kernel

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.

Kees Cook committed 7 months ago

Commit 079a0281 parent 58c4ce88 files · +28 −160Browse files

Showing the changes to include (2 of 8 files). Show all

Unified · Split

2 files
  1. include/linux/fortify-string.h +0 −49
  2. include/linux/string.h +0 −3
include/linux/fortify-string.h+0−49
@@ -26,7 +26,6 @@ · 25 unmodified lines
26#define FORTIFY_WRITE 126#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
95extern char *__underlying_strcpy(char *p, const char *q) __RENAME(strcpy);94extern char *__underlying_strcpy(char *p, const char *q) __RENAME(strcpy);
96extern __kernel_size_t __underlying_strlen(const char *p) __RENAME(strlen);95extern __kernel_size_t __underlying_strlen(const char *p) __RENAME(strlen);
97extern char *__underlying_strncat(char *p, const char *q, __kernel_size_t count) __RENAME(strncat);96extern char *__underlying_strncat(char *p, const char *q, __kernel_size_t count) __RENAME(strncat);
98extern char *__underlying_strncpy(char *p, const char *q, __kernel_size_t size) __RENAME(strncpy);
99
100#else97#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_strcpy117#define __underlying_strcpy __builtin_strcpy
121#define __underlying_strlen __builtin_strlen118#define __underlying_strlen __builtin_strlen
122#define __underlying_strncat __builtin_strncat119#define __underlying_strncat __builtin_strncat
123#define __underlying_strncpy __builtin_strncpy
124 120
125#endif121#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)
195char *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
206extern __kernel_size_t __real_strnlen(const char *, __kernel_size_t) __RENAME(strnlen);158extern __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 string160 * 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_strcpy761#undef __underlying_strcpy
810#undef __underlying_strlen762#undef __underlying_strlen
811#undef __underlying_strncat763#undef __underlying_strncat
812#undef __underlying_strncpy
813 764
814#undef POS765#undef POS
815#undef POS0766#undef POS0
include/linux/string.h+0−3
@@ -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_STRCPY67#ifndef __HAVE_ARCH_STRCPY
68extern char * strcpy(char *,const char *);68extern char * strcpy(char *,const char *);
69#endif69#endif
70#ifndef __HAVE_ARCH_STRNCPY
71extern char * strncpy(char *,const char *, __kernel_size_t);
72#endif
73ssize_t sized_strscpy(char *, const char *, size_t);70ssize_t sized_strscpy(char *, const char *, size_t);
74 71
75/*72/*

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t