Skip to content

Commit 03699f2

Browse files
committed
string: Rewrite and add more kern-doc for the str*() functions
While there were varying degrees of kern-doc for various str*()-family functions, many needed updating and clarification, or to just be entirely written. Update (and relocate) existing kern-doc and add missing functions, sadly shaking my head at how many times I have written "Do not use this function". Include the results in the core kernel API doc. Cc: Bagas Sanjaya <[email protected]> Cc: Andy Shevchenko <[email protected]> Cc: Rasmus Villemoes <[email protected]> Cc: Andrew Morton <[email protected]> Cc: [email protected] Tested-by: Akira Yokosawa <[email protected]> Link: https://lore.kernel.org/lkml/[email protected] Signed-off-by: Kees Cook <[email protected]>
1 parent 6f7630b commit 03699f2

File tree

4 files changed

+131
-93
lines changed

4 files changed

+131
-93
lines changed

Documentation/core-api/kernel-api.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ String Conversions
3636
String Manipulation
3737
-------------------
3838

39+
.. kernel-doc:: include/linux/fortify-string.h
40+
:internal:
41+
3942
.. kernel-doc:: lib/string.c
4043
:export:
4144

include/linux/fortify-string.h

Lines changed: 123 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -106,13 +106,13 @@ extern char *__underlying_strncpy(char *p, const char *q, __kernel_size_t size)
106106
* Instead, please choose an alternative, so that the expectation
107107
* of @p's contents is unambiguous:
108108
*
109-
* +--------------------+-----------------+------------+
110-
* | @p needs to be: | padded to @size | not padded |
111-
* +====================+=================+============+
112-
* | NUL-terminated | strscpy_pad() | strscpy() |
113-
* +--------------------+-----------------+------------+
114-
* | not NUL-terminated | strtomem_pad() | strtomem() |
115-
* +--------------------+-----------------+------------+
109+
* +--------------------+--------------------+------------+
110+
* | **p** needs to be: | padded to **size** | not padded |
111+
* +====================+====================+============+
112+
* | NUL-terminated | strscpy_pad() | strscpy() |
113+
* +--------------------+--------------------+------------+
114+
* | not NUL-terminated | strtomem_pad() | strtomem() |
115+
* +--------------------+--------------------+------------+
116116
*
117117
* Note strscpy*()'s differing return values for detecting truncation,
118118
* and strtomem*()'s expectation that the destination is marked with
@@ -131,6 +131,21 @@ char *strncpy(char * const POS p, const char *q, __kernel_size_t size)
131131
return __underlying_strncpy(p, q, size);
132132
}
133133

134+
/**
135+
* strcat - Append a string to an existing string
136+
*
137+
* @p: pointer to NUL-terminated string to append to
138+
* @q: pointer to NUL-terminated source string to append from
139+
*
140+
* Do not use this function. While FORTIFY_SOURCE tries to avoid
141+
* read and write overflows, this is only possible when the
142+
* destination buffer size is known to the compiler. Prefer
143+
* building the string with formatting, via scnprintf() or similar.
144+
* At the very least, use strncat().
145+
*
146+
* Returns @p.
147+
*
148+
*/
134149
__FORTIFY_INLINE __diagnose_as(__builtin_strcat, 1, 2)
135150
char *strcat(char * const POS p, const char *q)
136151
{
@@ -144,6 +159,16 @@ char *strcat(char * const POS p, const char *q)
144159
}
145160

146161
extern __kernel_size_t __real_strnlen(const char *, __kernel_size_t) __RENAME(strnlen);
162+
/**
163+
* strnlen - Return bounded count of characters in a NUL-terminated string
164+
*
165+
* @p: pointer to NUL-terminated string to count.
166+
* @maxlen: maximum number of characters to count.
167+
*
168+
* Returns number of characters in @p (NOT including the final NUL), or
169+
* @maxlen, if no NUL has been found up to there.
170+
*
171+
*/
147172
__FORTIFY_INLINE __kernel_size_t strnlen(const char * const POS p, __kernel_size_t maxlen)
148173
{
149174
size_t p_size = __member_size(p);
@@ -169,6 +194,19 @@ __FORTIFY_INLINE __kernel_size_t strnlen(const char * const POS p, __kernel_size
169194
* possible for strlen() to be used on compile-time strings for use in
170195
* static initializers (i.e. as a constant expression).
171196
*/
197+
/**
198+
* strlen - Return count of characters in a NUL-terminated string
199+
*
200+
* @p: pointer to NUL-terminated string to count.
201+
*
202+
* Do not use this function unless the string length is known at
203+
* compile-time. When @p is unterminated, this function may crash
204+
* or return unexpected counts that could lead to memory content
205+
* exposures. Prefer strnlen().
206+
*
207+
* Returns number of characters in @p (NOT including the final NUL).
208+
*
209+
*/
172210
#define strlen(p) \
173211
__builtin_choose_expr(__is_constexpr(__builtin_strlen(p)), \
174212
__builtin_strlen(p), __fortify_strlen(p))
@@ -187,8 +225,26 @@ __kernel_size_t __fortify_strlen(const char * const POS p)
187225
return ret;
188226
}
189227

190-
/* defined after fortified strlen to reuse it */
228+
/* Defined after fortified strlen() to reuse it. */
191229
extern size_t __real_strlcpy(char *, const char *, size_t) __RENAME(strlcpy);
230+
/**
231+
* strlcpy - Copy a string into another string buffer
232+
*
233+
* @p: pointer to destination of copy
234+
* @q: pointer to NUL-terminated source string to copy
235+
* @size: maximum number of bytes to write at @p
236+
*
237+
* If strlen(@q) >= @size, the copy of @q will be truncated at
238+
* @size - 1 bytes. @p will always be NUL-terminated.
239+
*
240+
* Do not use this function. While FORTIFY_SOURCE tries to avoid
241+
* over-reads when calculating strlen(@q), it is still possible.
242+
* Prefer strscpy(), though note its different return values for
243+
* detecting truncation.
244+
*
245+
* Returns total number of bytes written to @p, including terminating NUL.
246+
*
247+
*/
192248
__FORTIFY_INLINE size_t strlcpy(char * const POS p, const char * const POS q, size_t size)
193249
{
194250
size_t p_size = __member_size(p);
@@ -214,8 +270,32 @@ __FORTIFY_INLINE size_t strlcpy(char * const POS p, const char * const POS q, si
214270
return q_len;
215271
}
216272

217-
/* defined after fortified strnlen to reuse it */
273+
/* Defined after fortified strnlen() to reuse it. */
218274
extern ssize_t __real_strscpy(char *, const char *, size_t) __RENAME(strscpy);
275+
/**
276+
* strscpy - Copy a C-string into a sized buffer
277+
*
278+
* @p: Where to copy the string to
279+
* @q: Where to copy the string from
280+
* @size: Size of destination buffer
281+
*
282+
* Copy the source string @p, or as much of it as fits, into the destination
283+
* @q buffer. The behavior is undefined if the string buffers overlap. The
284+
* destination @p buffer is always NUL terminated, unless it's zero-sized.
285+
*
286+
* Preferred to strlcpy() since the API doesn't require reading memory
287+
* from the source @q string beyond the specified @size bytes, and since
288+
* the return value is easier to error-check than strlcpy()'s.
289+
* In addition, the implementation is robust to the string changing out
290+
* from underneath it, unlike the current strlcpy() implementation.
291+
*
292+
* Preferred to strncpy() since it always returns a valid string, and
293+
* doesn't unnecessarily force the tail of the destination buffer to be
294+
* zero padded. If padding is desired please use strscpy_pad().
295+
*
296+
* Returns the number of characters copied in @p (not including the
297+
* trailing %NUL) or -E2BIG if @size is 0 or the copy of @q was truncated.
298+
*/
219299
__FORTIFY_INLINE ssize_t strscpy(char * const POS p, const char * const POS q, size_t size)
220300
{
221301
size_t len;
@@ -261,7 +341,26 @@ __FORTIFY_INLINE ssize_t strscpy(char * const POS p, const char * const POS q, s
261341
return __real_strscpy(p, q, len);
262342
}
263343

264-
/* defined after fortified strlen and strnlen to reuse them */
344+
/**
345+
* strncat - Append a string to an existing string
346+
*
347+
* @p: pointer to NUL-terminated string to append to
348+
* @q: pointer to source string to append from
349+
* @count: Maximum bytes to read from @q
350+
*
351+
* Appends at most @count bytes from @q (stopping at the first
352+
* NUL byte) after the NUL-terminated string at @p. @p will be
353+
* NUL-terminated.
354+
*
355+
* Do not use this function. While FORTIFY_SOURCE tries to avoid
356+
* read and write overflows, this is only possible when the sizes
357+
* of @p and @q are known to the compiler. Prefer building the
358+
* string with formatting, via scnprintf() or similar.
359+
*
360+
* Returns @p.
361+
*
362+
*/
363+
/* Defined after fortified strlen() and strnlen() to reuse them. */
265364
__FORTIFY_INLINE __diagnose_as(__builtin_strncat, 1, 2, 3)
266365
char *strncat(char * const POS p, const char * const POS q, __kernel_size_t count)
267366
{
@@ -572,6 +671,20 @@ __FORTIFY_INLINE void *kmemdup(const void * const POS0 p, size_t size, gfp_t gfp
572671
return __real_kmemdup(p, size, gfp);
573672
}
574673

674+
/**
675+
* strcpy - Copy a string into another string buffer
676+
*
677+
* @p: pointer to destination of copy
678+
* @q: pointer to NUL-terminated source string to copy
679+
*
680+
* Do not use this function. While FORTIFY_SOURCE tries to avoid
681+
* overflows, this is only possible when the sizes of @q and @p are
682+
* known to the compiler. Prefer strscpy(), though note its different
683+
* return values for detecting truncation.
684+
*
685+
* Returns @p.
686+
*
687+
*/
575688
/* Defined after fortified strlen to reuse it. */
576689
__FORTIFY_INLINE __diagnose_as(__builtin_strcpy, 1, 2)
577690
char *strcpy(char * const POS p, const char * const POS q)

lib/string.c

Lines changed: 0 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,6 @@ EXPORT_SYMBOL(strcasecmp);
7676
#endif
7777

7878
#ifndef __HAVE_ARCH_STRCPY
79-
/**
80-
* strcpy - Copy a %NUL terminated string
81-
* @dest: Where to copy the string to
82-
* @src: Where to copy the string from
83-
*/
8479
char *strcpy(char *dest, const char *src)
8580
{
8681
char *tmp = dest;
@@ -93,19 +88,6 @@ EXPORT_SYMBOL(strcpy);
9388
#endif
9489

9590
#ifndef __HAVE_ARCH_STRNCPY
96-
/**
97-
* strncpy - Copy a length-limited, C-string
98-
* @dest: Where to copy the string to
99-
* @src: Where to copy the string from
100-
* @count: The maximum number of bytes to copy
101-
*
102-
* The result is not %NUL-terminated if the source exceeds
103-
* @count bytes.
104-
*
105-
* In the case where the length of @src is less than that of
106-
* count, the remainder of @dest will be padded with %NUL.
107-
*
108-
*/
10991
char *strncpy(char *dest, const char *src, size_t count)
11092
{
11193
char *tmp = dest;
@@ -122,17 +104,6 @@ EXPORT_SYMBOL(strncpy);
122104
#endif
123105

124106
#ifndef __HAVE_ARCH_STRLCPY
125-
/**
126-
* strlcpy - Copy a C-string into a sized buffer
127-
* @dest: Where to copy the string to
128-
* @src: Where to copy the string from
129-
* @size: size of destination buffer
130-
*
131-
* Compatible with ``*BSD``: the result is always a valid
132-
* NUL-terminated string that fits in the buffer (unless,
133-
* of course, the buffer size is zero). It does not pad
134-
* out the result like strncpy() does.
135-
*/
136107
size_t strlcpy(char *dest, const char *src, size_t size)
137108
{
138109
size_t ret = strlen(src);
@@ -148,30 +119,6 @@ EXPORT_SYMBOL(strlcpy);
148119
#endif
149120

150121
#ifndef __HAVE_ARCH_STRSCPY
151-
/**
152-
* strscpy - Copy a C-string into a sized buffer
153-
* @dest: Where to copy the string to
154-
* @src: Where to copy the string from
155-
* @count: Size of destination buffer
156-
*
157-
* Copy the string, or as much of it as fits, into the dest buffer. The
158-
* behavior is undefined if the string buffers overlap. The destination
159-
* buffer is always NUL terminated, unless it's zero-sized.
160-
*
161-
* Preferred to strlcpy() since the API doesn't require reading memory
162-
* from the src string beyond the specified "count" bytes, and since
163-
* the return value is easier to error-check than strlcpy()'s.
164-
* In addition, the implementation is robust to the string changing out
165-
* from underneath it, unlike the current strlcpy() implementation.
166-
*
167-
* Preferred to strncpy() since it always returns a valid string, and
168-
* doesn't unnecessarily force the tail of the destination buffer to be
169-
* zeroed. If zeroing is desired please use strscpy_pad().
170-
*
171-
* Returns:
172-
* * The number of characters copied (not including the trailing %NUL)
173-
* * -E2BIG if count is 0 or @src was truncated.
174-
*/
175122
ssize_t strscpy(char *dest, const char *src, size_t count)
176123
{
177124
const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS;
@@ -266,11 +213,6 @@ char *stpcpy(char *__restrict__ dest, const char *__restrict__ src)
266213
EXPORT_SYMBOL(stpcpy);
267214

268215
#ifndef __HAVE_ARCH_STRCAT
269-
/**
270-
* strcat - Append one %NUL-terminated string to another
271-
* @dest: The string to be appended to
272-
* @src: The string to append to it
273-
*/
274216
char *strcat(char *dest, const char *src)
275217
{
276218
char *tmp = dest;
@@ -285,15 +227,6 @@ EXPORT_SYMBOL(strcat);
285227
#endif
286228

287229
#ifndef __HAVE_ARCH_STRNCAT
288-
/**
289-
* strncat - Append a length-limited, C-string to another
290-
* @dest: The string to be appended to
291-
* @src: The string to append to it
292-
* @count: The maximum numbers of bytes to copy
293-
*
294-
* Note that in contrast to strncpy(), strncat() ensures the result is
295-
* terminated.
296-
*/
297230
char *strncat(char *dest, const char *src, size_t count)
298231
{
299232
char *tmp = dest;
@@ -314,12 +247,6 @@ EXPORT_SYMBOL(strncat);
314247
#endif
315248

316249
#ifndef __HAVE_ARCH_STRLCAT
317-
/**
318-
* strlcat - Append a length-limited, C-string to another
319-
* @dest: The string to be appended to
320-
* @src: The string to append to it
321-
* @count: The size of the destination buffer.
322-
*/
323250
size_t strlcat(char *dest, const char *src, size_t count)
324251
{
325252
size_t dsize = strlen(dest);
@@ -484,10 +411,6 @@ EXPORT_SYMBOL(strnchr);
484411
#endif
485412

486413
#ifndef __HAVE_ARCH_STRLEN
487-
/**
488-
* strlen - Find the length of a string
489-
* @s: The string to be sized
490-
*/
491414
size_t strlen(const char *s)
492415
{
493416
const char *sc;
@@ -500,11 +423,6 @@ EXPORT_SYMBOL(strlen);
500423
#endif
501424

502425
#ifndef __HAVE_ARCH_STRNLEN
503-
/**
504-
* strnlen - Find the length of a length-limited string
505-
* @s: The string to be sized
506-
* @count: The maximum number of bytes to search
507-
*/
508426
size_t strnlen(const char *s, size_t count)
509427
{
510428
const char *sc;

scripts/kernel-doc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1448,6 +1448,8 @@ sub create_parameterlist($$$$) {
14481448
foreach my $arg (split($splitter, $args)) {
14491449
# strip comments
14501450
$arg =~ s/\/\*.*\*\///;
1451+
# ignore argument attributes
1452+
$arg =~ s/\sPOS0?\s/ /;
14511453
# strip leading/trailing spaces
14521454
$arg =~ s/^\s*//;
14531455
$arg =~ s/\s*$//;
@@ -1657,6 +1659,7 @@ sub dump_function($$) {
16571659
$prototype =~ s/^__inline +//;
16581660
$prototype =~ s/^__always_inline +//;
16591661
$prototype =~ s/^noinline +//;
1662+
$prototype =~ s/^__FORTIFY_INLINE +//;
16601663
$prototype =~ s/__init +//;
16611664
$prototype =~ s/__init_or_module +//;
16621665
$prototype =~ s/__deprecated +//;
@@ -1666,7 +1669,8 @@ sub dump_function($$) {
16661669
$prototype =~ s/__weak +//;
16671670
$prototype =~ s/__sched +//;
16681671
$prototype =~ s/__printf\s*\(\s*\d*\s*,\s*\d*\s*\) +//;
1669-
$prototype =~ s/__alloc_size\s*\(\s*\d+\s*(?:,\s*\d+\s*)?\) +//;
1672+
$prototype =~ s/__(?:re)?alloc_size\s*\(\s*\d+\s*(?:,\s*\d+\s*)?\) +//;
1673+
$prototype =~ s/__diagnose_as\s*\(\s*\S+\s*(?:,\s*\d+\s*)*\) +//;
16701674
my $define = $prototype =~ s/^#\s*define\s+//; #ak added
16711675
$prototype =~ s/__attribute_const__ +//;
16721676
$prototype =~ s/__attribute__\s*\(\(

0 commit comments

Comments
 (0)