The patch titled Subject: drivers/misc/lkdtm: add new file in LKDTM to test fortified strscpy has been added to the -mm tree. Its filename is add-new-file-in-lkdtm-to-test-fortified-strscpy.patch This patch should soon appear at https://ozlabs.org/~akpm/mmots/broken-out/add-new-file-in-lkdtm-to-test-fortified-strscpy.patch and later at https://ozlabs.org/~akpm/mmotm/broken-out/add-new-file-in-lkdtm-to-test-fortified-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: drivers/misc/lkdtm: add new file in LKDTM to test fortified strscpy This new test ensures that fortified strscpy has the same behavior than vanilla strscpy (e.g. returning -E2BIG when src content is truncated). Finally, it generates a crash at runtime because there is a write overflow in destination string. Link: https://lkml.kernel.org/r/20201122162451.27551-5-laniel_francis@xxxxxxxxxxxxxxxxxxx Signed-off-by: Francis Laniel <laniel_francis@xxxxxxxxxxxxxxxxxxx> Reviewed-by: Kees Cook <keescook@xxxxxxxxxxxx> Cc: Daniel Axtens <dja@xxxxxxxxxx> Cc: Daniel Micay <danielmicay@xxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- drivers/misc/lkdtm/Makefile | 1 drivers/misc/lkdtm/core.c | 1 drivers/misc/lkdtm/fortify.c | 82 ++++++++++++++++++++++ drivers/misc/lkdtm/lkdtm.h | 3 tools/testing/selftests/lkdtm/tests.txt | 1 5 files changed, 88 insertions(+) --- a/drivers/misc/lkdtm/core.c~add-new-file-in-lkdtm-to-test-fortified-strscpy +++ a/drivers/misc/lkdtm/core.c @@ -175,6 +175,7 @@ static const struct crashtype crashtypes CRASHTYPE(USERCOPY_KERNEL), CRASHTYPE(STACKLEAK_ERASING), CRASHTYPE(CFI_FORWARD_PROTO), + CRASHTYPE(FORTIFIED_STRSCPY), #ifdef CONFIG_X86_32 CRASHTYPE(DOUBLE_FAULT), #endif --- /dev/null +++ a/drivers/misc/lkdtm/fortify.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 Francis Laniel <laniel_francis@xxxxxxxxxxxxxxxxxxx> + * + * Add tests related to fortified functions in this file. + */ +#include "lkdtm.h" +#include <linux/string.h> +#include <linux/slab.h> + + +/* + * Calls fortified strscpy to test that it returns the same result as vanilla + * strscpy and generate a panic because there is a write overflow (i.e. src + * length is greater than dst length). + */ +void lkdtm_FORTIFIED_STRSCPY(void) +{ + char *src; + char dst[5]; + + struct { + union { + char big[10]; + char src[5]; + }; + } weird = { .big = "hello!" }; + char weird_dst[sizeof(weird.src) + 1]; + + src = kstrdup("foobar", GFP_KERNEL); + + if (src == NULL) + return; + + /* Vanilla strscpy returns -E2BIG if size is 0. */ + if (strscpy(dst, src, 0) != -E2BIG) + pr_warn("FAIL: strscpy() of 0 length did not return -E2BIG\n"); + + /* Vanilla strscpy returns -E2BIG if src is truncated. */ + if (strscpy(dst, src, sizeof(dst)) != -E2BIG) + pr_warn("FAIL: strscpy() did not return -E2BIG while src is truncated\n"); + + /* After above call, dst must contain "foob" because src was truncated. */ + if (strncmp(dst, "foob", sizeof(dst)) != 0) + pr_warn("FAIL: after strscpy() dst does not contain \"foob\" but \"%s\"\n", + dst); + + /* Shrink src so the strscpy() below succeeds. */ + src[3] = '\0'; + + /* + * Vanilla strscpy returns number of character copied if everything goes + * well. + */ + if (strscpy(dst, src, sizeof(dst)) != 3) + pr_warn("FAIL: strscpy() did not return 3 while src was copied entirely truncated\n"); + + /* After above call, dst must contain "foo" because src was copied. */ + if (strncmp(dst, "foo", sizeof(dst)) != 0) + pr_warn("FAIL: after strscpy() dst does not contain \"foo\" but \"%s\"\n", + dst); + + /* Test when src is embedded inside a union. */ + strscpy(weird_dst, weird.src, sizeof(weird_dst)); + + if (strcmp(weird_dst, "hello") != 0) + pr_warn("FAIL: after strscpy() weird_dst does not contain \"hello\" but \"%s\"\n", + weird_dst); + + /* Restore src to its initial value. */ + src[3] = 'b'; + + /* + * Use strlen here so size cannot be known at compile time and there is + * a runtime write overflow. + */ + strscpy(dst, src, strlen(src)); + + pr_warn("FAIL: No overflow in above strscpy()\n"); + + kfree(src); +} --- a/drivers/misc/lkdtm/lkdtm.h~add-new-file-in-lkdtm-to-test-fortified-strscpy +++ a/drivers/misc/lkdtm/lkdtm.h @@ -104,4 +104,7 @@ void lkdtm_STACKLEAK_ERASING(void); /* cfi.c */ void lkdtm_CFI_FORWARD_PROTO(void); +/* fortify.c */ +void lkdtm_FORTIFIED_STRSCPY(void); + #endif --- a/drivers/misc/lkdtm/Makefile~add-new-file-in-lkdtm-to-test-fortified-strscpy +++ a/drivers/misc/lkdtm/Makefile @@ -10,6 +10,7 @@ lkdtm-$(CONFIG_LKDTM) += rodata_objcopy lkdtm-$(CONFIG_LKDTM) += usercopy.o lkdtm-$(CONFIG_LKDTM) += stackleak.o lkdtm-$(CONFIG_LKDTM) += cfi.o +lkdtm-$(CONFIG_LKDTM) += fortify.o KASAN_SANITIZE_stackleak.o := n KCOV_INSTRUMENT_rodata.o := n --- a/tools/testing/selftests/lkdtm/tests.txt~add-new-file-in-lkdtm-to-test-fortified-strscpy +++ a/tools/testing/selftests/lkdtm/tests.txt @@ -68,3 +68,4 @@ USERCOPY_STACK_BEYOND USERCOPY_KERNEL STACKLEAK_ERASING OK: the rest of the thread stack is properly erased CFI_FORWARD_PROTO +FORTIFIED_STRSCPY _ 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