lib/string: Add strscpy_pad() function
We have a function to copy strings safely and we have a function to copy strings and zero the tail of the destination (if source string is shorter than destination buffer) but we do not have a function to do both at once. This means developers must write this themselves if they desire this functionality. This is a chore, and also leaves us open to off by one errors unnecessarily. Add a function that calls strscpy() then memset()s the tail to zero if the source string is shorter than the destination buffer. Acked-by: Kees Cook <keescook@chromium.org> Signed-off-by: Tobin C. Harding <tobin@kernel.org> Signed-off-by: Shuah Khan <shuah@kernel.org>
This commit is contained in:
parent
6b1a4d5b1a
commit
458a3bf82d
|
@ -31,6 +31,10 @@ size_t strlcpy(char *, const char *, size_t);
|
||||||
#ifndef __HAVE_ARCH_STRSCPY
|
#ifndef __HAVE_ARCH_STRSCPY
|
||||||
ssize_t strscpy(char *, const char *, size_t);
|
ssize_t strscpy(char *, const char *, size_t);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Wraps calls to strscpy()/memset(), no arch specific code required */
|
||||||
|
ssize_t strscpy_pad(char *dest, const char *src, size_t count);
|
||||||
|
|
||||||
#ifndef __HAVE_ARCH_STRCAT
|
#ifndef __HAVE_ARCH_STRCAT
|
||||||
extern char * strcat(char *, const char *);
|
extern char * strcat(char *, const char *);
|
||||||
#endif
|
#endif
|
||||||
|
|
47
lib/string.c
47
lib/string.c
|
@ -159,11 +159,9 @@ EXPORT_SYMBOL(strlcpy);
|
||||||
* @src: Where to copy the string from
|
* @src: Where to copy the string from
|
||||||
* @count: Size of destination buffer
|
* @count: Size of destination buffer
|
||||||
*
|
*
|
||||||
* Copy the string, or as much of it as fits, into the dest buffer.
|
* Copy the string, or as much of it as fits, into the dest buffer. The
|
||||||
* The routine returns the number of characters copied (not including
|
* behavior is undefined if the string buffers overlap. The destination
|
||||||
* the trailing NUL) or -E2BIG if the destination buffer wasn't big enough.
|
* buffer is always NUL terminated, unless it's zero-sized.
|
||||||
* The behavior is undefined if the string buffers overlap.
|
|
||||||
* The destination buffer is always NUL terminated, unless it's zero-sized.
|
|
||||||
*
|
*
|
||||||
* Preferred to strlcpy() since the API doesn't require reading memory
|
* Preferred to strlcpy() since the API doesn't require reading memory
|
||||||
* from the src string beyond the specified "count" bytes, and since
|
* from the src string beyond the specified "count" bytes, and since
|
||||||
|
@ -173,8 +171,10 @@ EXPORT_SYMBOL(strlcpy);
|
||||||
*
|
*
|
||||||
* Preferred to strncpy() since it always returns a valid string, and
|
* Preferred to strncpy() since it always returns a valid string, and
|
||||||
* doesn't unnecessarily force the tail of the destination buffer to be
|
* doesn't unnecessarily force the tail of the destination buffer to be
|
||||||
* zeroed. If the zeroing is desired, it's likely cleaner to use strscpy()
|
* zeroed. If zeroing is desired please use strscpy_pad().
|
||||||
* with an overflow test, then just memset() the tail of the dest buffer.
|
*
|
||||||
|
* Return: The number of characters copied (not including the trailing
|
||||||
|
* %NUL) or -E2BIG if the destination buffer wasn't big enough.
|
||||||
*/
|
*/
|
||||||
ssize_t strscpy(char *dest, const char *src, size_t count)
|
ssize_t strscpy(char *dest, const char *src, size_t count)
|
||||||
{
|
{
|
||||||
|
@ -237,6 +237,39 @@ ssize_t strscpy(char *dest, const char *src, size_t count)
|
||||||
EXPORT_SYMBOL(strscpy);
|
EXPORT_SYMBOL(strscpy);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* strscpy_pad() - Copy a C-string into a sized buffer
|
||||||
|
* @dest: Where to copy the string to
|
||||||
|
* @src: Where to copy the string from
|
||||||
|
* @count: Size of destination buffer
|
||||||
|
*
|
||||||
|
* Copy the string, or as much of it as fits, into the dest buffer. The
|
||||||
|
* behavior is undefined if the string buffers overlap. The destination
|
||||||
|
* buffer is always %NUL terminated, unless it's zero-sized.
|
||||||
|
*
|
||||||
|
* If the source string is shorter than the destination buffer, zeros
|
||||||
|
* the tail of the destination buffer.
|
||||||
|
*
|
||||||
|
* For full explanation of why you may want to consider using the
|
||||||
|
* 'strscpy' functions please see the function docstring for strscpy().
|
||||||
|
*
|
||||||
|
* Return: The number of characters copied (not including the trailing
|
||||||
|
* %NUL) or -E2BIG if the destination buffer wasn't big enough.
|
||||||
|
*/
|
||||||
|
ssize_t strscpy_pad(char *dest, const char *src, size_t count)
|
||||||
|
{
|
||||||
|
ssize_t written;
|
||||||
|
|
||||||
|
written = strscpy(dest, src, count);
|
||||||
|
if (written < 0 || written == count - 1)
|
||||||
|
return written;
|
||||||
|
|
||||||
|
memset(dest + written + 1, 0, count - written - 1);
|
||||||
|
|
||||||
|
return written;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(strscpy_pad);
|
||||||
|
|
||||||
#ifndef __HAVE_ARCH_STRCAT
|
#ifndef __HAVE_ARCH_STRCAT
|
||||||
/**
|
/**
|
||||||
* strcat - Append one %NUL-terminated string to another
|
* strcat - Append one %NUL-terminated string to another
|
||||||
|
|
Loading…
Reference in New Issue