Skip to content

Commit e6584c3

Browse files
committed
string: Allow 2-argument strscpy()
Using sizeof(dst) for the "size" argument in strscpy() is the overwhelmingly common case. Instead of requiring this everywhere, allow a 2-argument version to be used that will use the sizeof() internally. There are other functions in the kernel with optional arguments[1], so this isn't unprecedented, and improves readability. Update and relocate the kern-doc for strscpy() too, and drop __HAVE_ARCH_STRSCPY as it is unused. Adjust ARCH=um build to notice the changed export name, as it doesn't do full header includes for the string helpers. This could additionally let us save a few hundred lines of code: 1177 files changed, 2455 insertions(+), 3026 deletions(-) with a treewide cleanup using Coccinelle: @needless_arg@ expression DST, SRC; @@ strscpy(DST, SRC -, sizeof(DST) ) Link: https://elixir.bootlin.com/linux/v6.7/source/include/linux/pci.h#L1517 [1] Reviewed-by: Justin Stitt <[email protected]> Cc: Andy Shevchenko <[email protected]> Cc: [email protected] Signed-off-by: Kees Cook <[email protected]>
1 parent f478898 commit e6584c3

File tree

4 files changed

+41
-28
lines changed

4 files changed

+41
-28
lines changed

arch/um/include/shared/user.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ static inline int printk(const char *fmt, ...)
5151

5252
extern int in_aton(char *str);
5353
extern size_t strlcat(char *, const char *, size_t);
54-
extern size_t strscpy(char *, const char *, size_t);
54+
extern size_t sized_strscpy(char *, const char *, size_t);
55+
#define strscpy(dst, src, size) sized_strscpy(dst, src, size)
5556

5657
/* Copied from linux/compiler-gcc.h since we can't include it directly */
5758
#define barrier() __asm__ __volatile__("": : :"memory")

include/linux/fortify-string.h

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -215,26 +215,8 @@ __kernel_size_t __fortify_strlen(const char * const POS p)
215215
}
216216

217217
/* Defined after fortified strnlen() to reuse it. */
218-
extern ssize_t __real_strscpy(char *, const char *, size_t) __RENAME(strscpy);
219-
/**
220-
* strscpy - Copy a C-string into a sized buffer
221-
*
222-
* @p: Where to copy the string to
223-
* @q: Where to copy the string from
224-
* @size: Size of destination buffer
225-
*
226-
* Copy the source string @q, or as much of it as fits, into the destination
227-
* @p buffer. The behavior is undefined if the string buffers overlap. The
228-
* destination @p buffer is always NUL terminated, unless it's zero-sized.
229-
*
230-
* Preferred to strncpy() since it always returns a valid string, and
231-
* doesn't unnecessarily force the tail of the destination buffer to be
232-
* zero padded. If padding is desired please use strscpy_pad().
233-
*
234-
* Returns the number of characters copied in @p (not including the
235-
* trailing %NUL) or -E2BIG if @size is 0 or the copy of @q was truncated.
236-
*/
237-
__FORTIFY_INLINE ssize_t strscpy(char * const POS p, const char * const POS q, size_t size)
218+
extern ssize_t __real_strscpy(char *, const char *, size_t) __RENAME(sized_strscpy);
219+
__FORTIFY_INLINE ssize_t sized_strscpy(char * const POS p, const char * const POS q, size_t size)
238220
{
239221
/* Use string size rather than possible enclosing struct size. */
240222
const size_t p_size = __member_size(p);

include/linux/string.h

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#ifndef _LINUX_STRING_H_
33
#define _LINUX_STRING_H_
44

5+
#include <linux/args.h>
56
#include <linux/array_size.h>
67
#include <linux/compiler.h> /* for inline */
78
#include <linux/types.h> /* for size_t */
@@ -66,9 +67,40 @@ extern char * strcpy(char *,const char *);
6667
#ifndef __HAVE_ARCH_STRNCPY
6768
extern char * strncpy(char *,const char *, __kernel_size_t);
6869
#endif
69-
#ifndef __HAVE_ARCH_STRSCPY
70-
ssize_t strscpy(char *, const char *, size_t);
71-
#endif
70+
ssize_t sized_strscpy(char *, const char *, size_t);
71+
72+
/*
73+
* The 2 argument style can only be used when dst is an array with a
74+
* known size.
75+
*/
76+
#define __strscpy0(dst, src, ...) \
77+
sized_strscpy(dst, src, sizeof(dst) + __must_be_array(dst))
78+
#define __strscpy1(dst, src, size) sized_strscpy(dst, src, size)
79+
80+
/**
81+
* strscpy - Copy a C-string into a sized buffer
82+
* @dst: Where to copy the string to
83+
* @src: Where to copy the string from
84+
* @...: Size of destination buffer (optional)
85+
*
86+
* Copy the source string @src, or as much of it as fits, into the
87+
* destination @dst buffer. The behavior is undefined if the string
88+
* buffers overlap. The destination @dst buffer is always NUL terminated,
89+
* unless it's zero-sized.
90+
*
91+
* The size argument @... is only required when @dst is not an array, or
92+
* when the copy needs to be smaller than sizeof(@dst).
93+
*
94+
* Preferred to strncpy() since it always returns a valid string, and
95+
* doesn't unnecessarily force the tail of the destination buffer to be
96+
* zero padded. If padding is desired please use strscpy_pad().
97+
*
98+
* Returns the number of characters copied in @dst (not including the
99+
* trailing %NUL) or -E2BIG if @size is 0 or the copy from @src was
100+
* truncated.
101+
*/
102+
#define strscpy(dst, src, ...) \
103+
CONCATENATE(__strscpy, COUNT_ARGS(__VA_ARGS__))(dst, src, __VA_ARGS__)
72104

73105
/**
74106
* strscpy_pad() - Copy a C-string into a sized buffer

lib/string.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,7 @@ char *strncpy(char *dest, const char *src, size_t count)
104104
EXPORT_SYMBOL(strncpy);
105105
#endif
106106

107-
#ifndef __HAVE_ARCH_STRSCPY
108-
ssize_t strscpy(char *dest, const char *src, size_t count)
107+
ssize_t sized_strscpy(char *dest, const char *src, size_t count)
109108
{
110109
const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS;
111110
size_t max = count;
@@ -171,8 +170,7 @@ ssize_t strscpy(char *dest, const char *src, size_t count)
171170

172171
return -E2BIG;
173172
}
174-
EXPORT_SYMBOL(strscpy);
175-
#endif
173+
EXPORT_SYMBOL(sized_strscpy);
176174

177175
/**
178176
* stpcpy - copy a string from src to dest returning a pointer to the new end

0 commit comments

Comments
 (0)