mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 06:01:57 +00:00
string: Redefine strscpy_pad() as a macro
In preparation for making strscpy_pad()'s 3rd argument optional, redefine it as a macro. This also has the benefit of allowing greater FORITFY introspection, as it couldn't see into the strscpy() nor the memset() within strscpy_pad(). Cc: Andy Shevchenko <andy@kernel.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: <linux-hardening@vger.kernel.org> Reviewed-by: Justin Stitt <justinstitt@google.com> Signed-off-by: Kees Cook <keescook@chromium.org>
This commit is contained in:
parent
557f8c582a
commit
f478898e0a
@ -70,8 +70,37 @@ extern char * strncpy(char *,const char *, __kernel_size_t);
|
||||
ssize_t strscpy(char *, const char *, size_t);
|
||||
#endif
|
||||
|
||||
/* Wraps calls to strscpy()/memset(), no arch specific code required */
|
||||
ssize_t strscpy_pad(char *dest, const char *src, size_t count);
|
||||
/**
|
||||
* 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, the
|
||||
* remaining bytes in the buffer will be filled with %NUL bytes.
|
||||
*
|
||||
* For full explanation of why you may want to consider using the
|
||||
* 'strscpy' functions please see the function docstring for strscpy().
|
||||
*
|
||||
* Returns:
|
||||
* * The number of characters copied (not including the trailing %NULs)
|
||||
* * -E2BIG if count is 0 or @src was truncated.
|
||||
*/
|
||||
#define strscpy_pad(dest, src, count) ({ \
|
||||
char *__dst = (dest); \
|
||||
const char *__src = (src); \
|
||||
const size_t __count = (count); \
|
||||
ssize_t __wrote; \
|
||||
\
|
||||
__wrote = strscpy(__dst, __src, __count); \
|
||||
if (__wrote >= 0 && __wrote < __count) \
|
||||
memset(__dst + __wrote + 1, 0, __count - __wrote - 1); \
|
||||
__wrote; \
|
||||
})
|
||||
|
||||
#ifndef __HAVE_ARCH_STRCAT
|
||||
extern char * strcat(char *, const char *);
|
||||
|
@ -825,40 +825,6 @@ char **devm_kasprintf_strarray(struct device *dev, const char *prefix, size_t n)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_kasprintf_strarray);
|
||||
|
||||
/**
|
||||
* 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().
|
||||
*
|
||||
* Returns:
|
||||
* * The number of characters copied (not including the trailing %NUL)
|
||||
* * -E2BIG if count is 0 or @src was truncated.
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* skip_spaces - Removes leading whitespace from @str.
|
||||
* @str: The string to be stripped.
|
||||
|
Loading…
Reference in New Issue
Block a user