The patch titled Subject: string.h: add FORTIFY coverage for strscpy() has been added to the -mm tree. Its filename is stringh-add-fortify-coverage-for-strscpy.patch This patch should soon appear at https://ozlabs.org/~akpm/mmots/broken-out/stringh-add-fortify-coverage-for-strscpy.patch and later at https://ozlabs.org/~akpm/mmotm/broken-out/stringh-add-fortify-coverage-for-strscpy.patch Before you just go and hit "reply", please: a) Consider who else should be cc'ed b) Prefer to cc a suitable mailing list as well c) Ideally: find the original patch on the mailing list and do a reply-to-all to that, adding suitable additional cc's *** Remember to use Documentation/process/submit-checklist.rst when testing your code *** The -mm tree is included into linux-next and is updated there every 3-4 working days ------------------------------------------------------ From: Francis Laniel <laniel_francis@xxxxxxxxxxxxxxxxxxx> Subject: string.h: add FORTIFY coverage for strscpy() The fortified version of strscpy ensures the following before vanilla strscpy is called: 1. There is no read overflow because we either size is smaller than src length or we shrink size to src length by calling fortified strnlen. 2. There is no write overflow because we either failed during compilation or at runtime by checking that size is smaller than dest size. Link: https://lkml.kernel.org/r/20201122162451.27551-4-laniel_francis@xxxxxxxxxxxxxxxxxxx Signed-off-by: Francis Laniel <laniel_francis@xxxxxxxxxxxxxxxxxxx> Acked-by: Kees Cook <keescook@xxxxxxxxxxxx> Cc: Daniel Axtens <dja@xxxxxxxxxx> Cc: Daniel Micay <danielmicay@xxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- include/linux/string.h | 48 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) --- a/include/linux/string.h~stringh-add-fortify-coverage-for-strscpy +++ a/include/linux/string.h @@ -6,6 +6,7 @@ #include <linux/compiler.h> /* for inline */ #include <linux/types.h> /* for size_t */ #include <linux/stddef.h> /* for NULL */ +#include <linux/errno.h> /* for E2BIG */ #include <stdarg.h> #include <uapi/linux/string.h> @@ -357,6 +358,53 @@ __FORTIFY_INLINE size_t strlcpy(char *p, return ret; } +/* defined after fortified strnlen to reuse it */ +extern ssize_t __real_strscpy(char *, const char *, size_t) __RENAME(strscpy); +__FORTIFY_INLINE ssize_t strscpy(char *p, const char *q, size_t size) +{ + size_t len; + /* Use string size rather than possible enclosing struct size. */ + size_t p_size = __builtin_object_size(p, 1); + size_t q_size = __builtin_object_size(q, 1); + + /* If we cannot get size of p and q default to call strscpy. */ + if (p_size == (size_t) -1 && q_size == (size_t) -1) + return __real_strscpy(p, q, size); + + /* + * If size can be known at compile time and is greater than + * p_size, generate a compile time write overflow error. + */ + if (__builtin_constant_p(size) && size > p_size) + __write_overflow(); + + /* + * This call protects from read overflow, because len will default to q + * length if it smaller than size. + */ + len = strnlen(q, size); + /* + * If len equals size, we will copy only size bytes which leads to + * -E2BIG being returned. + * Otherwise we will copy len + 1 because of the final '\O'. + */ + len = len == size ? size : len + 1; + + /* + * Generate a runtime write overflow error if len is greater than + * p_size. + */ + if (len > p_size) + fortify_panic(__func__); + + /* + * We can now safely call vanilla strscpy because we are protected from: + * 1. Read overflow thanks to call to strnlen(). + * 2. Write overflow thanks to above ifs. + */ + return __real_strscpy(p, q, len); +} + /* defined after fortified strlen and strnlen to reuse them */ __FORTIFY_INLINE char *strncat(char *p, const char *q, __kernel_size_t count) { _ Patches currently in -mm which might be from laniel_francis@xxxxxxxxxxxxxxxxxxx are stringh-add-fortify-coverage-for-strscpy.patch add-new-file-in-lkdtm-to-test-fortified-strscpy.patch correct-wrong-filenames-in-comment.patch