linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v6 0/5] Fortify strscpy()
@ 2020-11-19 16:49 laniel_francis
  2020-11-19 16:49 ` [PATCH v6 1/5] string.h: detect intra-object overflow in fortified string functions laniel_francis
                   ` (5 more replies)
  0 siblings, 6 replies; 14+ messages in thread
From: laniel_francis @ 2020-11-19 16:49 UTC (permalink / raw)
  To: akpm
  Cc: linux-hardening, linux-mm, linux-kernel, dja, keescook, Francis Laniel

From: Francis Laniel <laniel_francis@privacyrequired.com>

Hi.


I hope your families, friends and yourselves are fine.

This patch set answers to this issue:
https://github.com/KSPP/linux/issues/46

I based my modifications on top of two patches from Daniel Axtens which modify
calls to __builtin_object_size to ensure the true size of char * are returned
and not the surrounding structure size.

To sum up, in my first patch I implemented a fortified version of strscpy.
This new version ensures the following before calling vanilla strscpy:
1. There is no read overflow because 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.
The second patch brings a new file in LKDTM driver to test this new version.
The test ensures the fortified version still returns the same value as the
vanilla one while panic'ing when there is a write overflow.
The third just corrects some typos in LKDTM related file.

If you see any problem or way to improve the code, feel free to share it.


Best regards.

Daniel Axtens (2):
  string.h: detect intra-object overflow in fortified string functions
  lkdtm: tests for FORTIFY_SOURCE

Francis Laniel (3):
  string.h: Add FORTIFY coverage for strscpy()
  Add new file in LKDTM to test fortified strscpy.
  Correct wrong filenames in comment.

 drivers/misc/lkdtm/Makefile             |  1 +
 drivers/misc/lkdtm/bugs.c               | 50 +++++++++++++++
 drivers/misc/lkdtm/core.c               |  3 +
 drivers/misc/lkdtm/fortify.c            | 82 +++++++++++++++++++++++++
 drivers/misc/lkdtm/lkdtm.h              | 19 +++---
 include/linux/string.h                  | 75 ++++++++++++++++++----
 tools/testing/selftests/lkdtm/tests.txt |  1 +
 7 files changed, 213 insertions(+), 18 deletions(-)
 create mode 100644 drivers/misc/lkdtm/fortify.c

-- 
2.20.1


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v6 1/5] string.h: detect intra-object overflow in fortified string functions
  2020-11-19 16:49 [PATCH v6 0/5] Fortify strscpy() laniel_francis
@ 2020-11-19 16:49 ` laniel_francis
  2020-11-20  1:38   ` Andrew Morton
  2020-11-19 16:49 ` [PATCH v6 2/5] lkdtm: tests for FORTIFY_SOURCE laniel_francis
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 14+ messages in thread
From: laniel_francis @ 2020-11-19 16:49 UTC (permalink / raw)
  To: akpm; +Cc: linux-hardening, linux-mm, linux-kernel, dja, keescook, Daniel Micay

From: Daniel Axtens <dja@axtens.net>

When the fortify feature was first introduced in commit 6974f0c4555e
("include/linux/string.h: add the option of fortified string.h functions"),
Daniel Micay observed:

  * It should be possible to optionally use __builtin_object_size(x, 1) for
    some functions (C strings) to detect intra-object overflows (like
    glibc's _FORTIFY_SOURCE=2), but for now this takes the conservative
    approach to avoid likely compatibility issues.

This is a case that often cannot be caught by KASAN. Consider:

struct foo {
    char a[10];
    char b[10];
}

void test() {
    char *msg;
    struct foo foo;

    msg = kmalloc(16, GFP_KERNEL);
    strcpy(msg, "Hello world!!");
    // this copy overwrites foo.b
    strcpy(foo.a, msg);
}

The questionable copy overflows foo.a and writes to foo.b as well. It
cannot be detected by KASAN. Currently it is also not detected by fortify,
because strcpy considers __builtin_object_size(x, 0), which considers the
size of the surrounding object (here, struct foo). However, if we switch
the string functions over to use __builtin_object_size(x, 1), the compiler
will measure the size of the closest surrounding subobject (here, foo.a),
rather than the size of the surrounding object as a whole. See
https://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html for more info.

Only do this for string functions: we cannot use it on things like
memcpy, memmove, memcmp and memchr_inv due to code like this which
purposefully operates on multiple structure members:
(arch/x86/kernel/traps.c)

	/*
	 * regs->sp points to the failing IRET frame on the
	 * ESPFIX64 stack.  Copy it to the entry stack.  This fills
	 * in gpregs->ss through gpregs->ip.
	 *
	 */
	memmove(&gpregs->ip, (void *)regs->sp, 5*8);

This change passes an allyesconfig on powerpc and x86, and an x86 kernel
built with it survives running with syz-stress from syzkaller, so it seems
safe so far.

Cc: Daniel Micay <danielmicay@gmail.com>
Cc: Kees Cook <keescook@chromium.org>
Reviewed-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Daniel Axtens <dja@axtens.net>
---
 include/linux/string.h | 27 ++++++++++++++++-----------
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/include/linux/string.h b/include/linux/string.h
index b1f3894a0a3e..46e91d684c47 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -292,7 +292,7 @@ extern char *__underlying_strncpy(char *p, const char *q, __kernel_size_t size)
 
 __FORTIFY_INLINE char *strncpy(char *p, const char *q, __kernel_size_t size)
 {
-	size_t p_size = __builtin_object_size(p, 0);
+	size_t p_size = __builtin_object_size(p, 1);
 	if (__builtin_constant_p(size) && p_size < size)
 		__write_overflow();
 	if (p_size < size)
@@ -302,7 +302,7 @@ __FORTIFY_INLINE char *strncpy(char *p, const char *q, __kernel_size_t size)
 
 __FORTIFY_INLINE char *strcat(char *p, const char *q)
 {
-	size_t p_size = __builtin_object_size(p, 0);
+	size_t p_size = __builtin_object_size(p, 1);
 	if (p_size == (size_t)-1)
 		return __underlying_strcat(p, q);
 	if (strlcat(p, q, p_size) >= p_size)
@@ -313,7 +313,7 @@ __FORTIFY_INLINE char *strcat(char *p, const char *q)
 __FORTIFY_INLINE __kernel_size_t strlen(const char *p)
 {
 	__kernel_size_t ret;
-	size_t p_size = __builtin_object_size(p, 0);
+	size_t p_size = __builtin_object_size(p, 1);
 
 	/* Work around gcc excess stack consumption issue */
 	if (p_size == (size_t)-1 ||
@@ -328,7 +328,7 @@ __FORTIFY_INLINE __kernel_size_t strlen(const char *p)
 extern __kernel_size_t __real_strnlen(const char *, __kernel_size_t) __RENAME(strnlen);
 __FORTIFY_INLINE __kernel_size_t strnlen(const char *p, __kernel_size_t maxlen)
 {
-	size_t p_size = __builtin_object_size(p, 0);
+	size_t p_size = __builtin_object_size(p, 1);
 	__kernel_size_t ret = __real_strnlen(p, maxlen < p_size ? maxlen : p_size);
 	if (p_size <= ret && maxlen != ret)
 		fortify_panic(__func__);
@@ -340,8 +340,8 @@ extern size_t __real_strlcpy(char *, const char *, size_t) __RENAME(strlcpy);
 __FORTIFY_INLINE size_t strlcpy(char *p, const char *q, size_t size)
 {
 	size_t ret;
-	size_t p_size = __builtin_object_size(p, 0);
-	size_t q_size = __builtin_object_size(q, 0);
+	size_t p_size = __builtin_object_size(p, 1);
+	size_t q_size = __builtin_object_size(q, 1);
 	if (p_size == (size_t)-1 && q_size == (size_t)-1)
 		return __real_strlcpy(p, q, size);
 	ret = strlen(q);
@@ -361,8 +361,8 @@ __FORTIFY_INLINE size_t strlcpy(char *p, const char *q, size_t size)
 __FORTIFY_INLINE char *strncat(char *p, const char *q, __kernel_size_t count)
 {
 	size_t p_len, copy_len;
-	size_t p_size = __builtin_object_size(p, 0);
-	size_t q_size = __builtin_object_size(q, 0);
+	size_t p_size = __builtin_object_size(p, 1);
+	size_t q_size = __builtin_object_size(q, 1);
 	if (p_size == (size_t)-1 && q_size == (size_t)-1)
 		return __underlying_strncat(p, q, count);
 	p_len = strlen(p);
@@ -475,11 +475,16 @@ __FORTIFY_INLINE void *kmemdup(const void *p, size_t size, gfp_t gfp)
 /* defined after fortified strlen and memcpy to reuse them */
 __FORTIFY_INLINE char *strcpy(char *p, const char *q)
 {
-	size_t p_size = __builtin_object_size(p, 0);
-	size_t q_size = __builtin_object_size(q, 0);
+	size_t p_size = __builtin_object_size(p, 1);
+	size_t q_size = __builtin_object_size(q, 1);
+	size_t size;
 	if (p_size == (size_t)-1 && q_size == (size_t)-1)
 		return __underlying_strcpy(p, q);
-	memcpy(p, q, strlen(q) + 1);
+	size = strlen(q) + 1;
+	/* test here to use the more stringent object size */
+	if (p_size < size)
+		fortify_panic(__func__);
+	memcpy(p, q, size);
 	return p;
 }
 
-- 
2.20.1


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v6 2/5] lkdtm: tests for FORTIFY_SOURCE
  2020-11-19 16:49 [PATCH v6 0/5] Fortify strscpy() laniel_francis
  2020-11-19 16:49 ` [PATCH v6 1/5] string.h: detect intra-object overflow in fortified string functions laniel_francis
@ 2020-11-19 16:49 ` laniel_francis
  2020-11-19 16:49 ` [PATCH v6 3/5] string.h: Add FORTIFY coverage for strscpy() laniel_francis
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 14+ messages in thread
From: laniel_francis @ 2020-11-19 16:49 UTC (permalink / raw)
  To: akpm; +Cc: linux-hardening, linux-mm, linux-kernel, dja, keescook

From: Daniel Axtens <dja@axtens.net>

Add code to test both:

 - runtime detection of the overrun of a structure. This covers the
   __builtin_object_size(x, 0) case. This test is called FORTIFY_OBJECT.

 - runtime detection of the overrun of a char array within a structure.
   This covers the __builtin_object_size(x, 1) case which can be used
   for some string functions. This test is called FORTIFY_SUBOBJECT.

Suggested-by: Kees Cook <keescook@chromium.org>
Reviewed-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Daniel Axtens <dja@axtens.net>
---
 drivers/misc/lkdtm/bugs.c  | 50 ++++++++++++++++++++++++++++++++++++++
 drivers/misc/lkdtm/core.c  |  2 ++
 drivers/misc/lkdtm/lkdtm.h |  2 ++
 3 files changed, 54 insertions(+)

diff --git a/drivers/misc/lkdtm/bugs.c b/drivers/misc/lkdtm/bugs.c
index a0675d4154d2..110f5a8538e9 100644
--- a/drivers/misc/lkdtm/bugs.c
+++ b/drivers/misc/lkdtm/bugs.c
@@ -482,3 +482,53 @@ noinline void lkdtm_CORRUPT_PAC(void)
 	pr_err("XFAIL: this test is arm64-only\n");
 #endif
 }
+
+void lkdtm_FORTIFY_OBJECT(void)
+{
+	struct target {
+		char a[10];
+	} target[2] = {};
+	int result;
+
+	/*
+	 * Using volatile prevents the compiler from determining the value of
+	 * 'size' at compile time. Without that, we would get a compile error
+	 * rather than a runtime error.
+	 */
+	volatile int size = 11;
+
+	pr_info("trying to read past the end of a struct\n");
+
+	result = memcmp(&target[0], &target[1], size);
+
+	/* Print result to prevent the code from being eliminated */
+	pr_err("FAIL: fortify did not catch an object overread!\n"
+	       "\"%d\" was the memcmp result.\n", result);
+}
+
+void lkdtm_FORTIFY_SUBOBJECT(void)
+{
+	struct target {
+		char a[10];
+		char b[10];
+	} target;
+	char *src;
+
+	src = kmalloc(20, GFP_KERNEL);
+	strscpy(src, "over ten bytes", 20);
+
+	pr_info("trying to strcpy past the end of a member of a struct\n");
+
+	/*
+	 * strncpy(target.a, src, 20); will hit a compile error because the
+	 * compiler knows at build time that target.a < 20 bytes. Use strcpy()
+	 * to force a runtime error.
+	 */
+	strcpy(target.a, src);
+
+	/* Use target.a to prevent the code from being eliminated */
+	pr_err("FAIL: fortify did not catch an sub-object overrun!\n"
+	       "\"%s\" was copied.\n", target.a);
+
+	kfree(src);
+}
diff --git a/drivers/misc/lkdtm/core.c b/drivers/misc/lkdtm/core.c
index 97803f213d9d..b8c51a633fcc 100644
--- a/drivers/misc/lkdtm/core.c
+++ b/drivers/misc/lkdtm/core.c
@@ -117,6 +117,8 @@ static const struct crashtype crashtypes[] = {
 	CRASHTYPE(UNSET_SMEP),
 	CRASHTYPE(CORRUPT_PAC),
 	CRASHTYPE(UNALIGNED_LOAD_STORE_WRITE),
+	CRASHTYPE(FORTIFY_OBJECT),
+	CRASHTYPE(FORTIFY_SUBOBJECT),
 	CRASHTYPE(OVERWRITE_ALLOCATION),
 	CRASHTYPE(WRITE_AFTER_FREE),
 	CRASHTYPE(READ_AFTER_FREE),
diff --git a/drivers/misc/lkdtm/lkdtm.h b/drivers/misc/lkdtm/lkdtm.h
index 6dec4c9b442f..49e6b945feb7 100644
--- a/drivers/misc/lkdtm/lkdtm.h
+++ b/drivers/misc/lkdtm/lkdtm.h
@@ -32,6 +32,8 @@ void lkdtm_STACK_GUARD_PAGE_TRAILING(void);
 void lkdtm_UNSET_SMEP(void);
 void lkdtm_DOUBLE_FAULT(void);
 void lkdtm_CORRUPT_PAC(void);
+void lkdtm_FORTIFY_OBJECT(void);
+void lkdtm_FORTIFY_SUBOBJECT(void);
 
 /* lkdtm_heap.c */
 void __init lkdtm_heap_init(void);
-- 
2.20.1


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v6 3/5] string.h: Add FORTIFY coverage for strscpy()
  2020-11-19 16:49 [PATCH v6 0/5] Fortify strscpy() laniel_francis
  2020-11-19 16:49 ` [PATCH v6 1/5] string.h: detect intra-object overflow in fortified string functions laniel_francis
  2020-11-19 16:49 ` [PATCH v6 2/5] lkdtm: tests for FORTIFY_SOURCE laniel_francis
@ 2020-11-19 16:49 ` laniel_francis
  2020-11-19 16:49 ` [PATCH v6 4/5] Add new file in LKDTM to test fortified strscpy laniel_francis
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 14+ messages in thread
From: laniel_francis @ 2020-11-19 16:49 UTC (permalink / raw)
  To: akpm
  Cc: linux-hardening, linux-mm, linux-kernel, dja, keescook, Francis Laniel

From: Francis Laniel <laniel_francis@privacyrequired.com>

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.

Signed-off-by: Francis Laniel <laniel_francis@privacyrequired.com>
Acked-by: Kees Cook <keescook@chromium.org>
---
 include/linux/string.h | 48 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/include/linux/string.h b/include/linux/string.h
index 46e91d684c47..1cd63a8a23ab 100644
--- a/include/linux/string.h
+++ b/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, const char *q, size_t size)
 	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)
 {
-- 
2.20.1


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v6 4/5] Add new file in LKDTM to test fortified strscpy.
  2020-11-19 16:49 [PATCH v6 0/5] Fortify strscpy() laniel_francis
                   ` (2 preceding siblings ...)
  2020-11-19 16:49 ` [PATCH v6 3/5] string.h: Add FORTIFY coverage for strscpy() laniel_francis
@ 2020-11-19 16:49 ` laniel_francis
  2020-11-19 16:49 ` [PATCH v6 5/5] Correct wrong filenames in comment laniel_francis
  2020-11-20  1:35 ` [PATCH v6 0/5] Fortify strscpy() Andrew Morton
  5 siblings, 0 replies; 14+ messages in thread
From: laniel_francis @ 2020-11-19 16:49 UTC (permalink / raw)
  To: akpm
  Cc: linux-hardening, linux-mm, linux-kernel, dja, keescook, Francis Laniel

From: Francis Laniel <laniel_francis@privacyrequired.com>

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.

Signed-off-by: Francis Laniel <laniel_francis@privacyrequired.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
---
 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(+)
 create mode 100644 drivers/misc/lkdtm/fortify.c

diff --git a/drivers/misc/lkdtm/Makefile b/drivers/misc/lkdtm/Makefile
index c70b3822013f..d898f7b22045 100644
--- a/drivers/misc/lkdtm/Makefile
+++ b/drivers/misc/lkdtm/Makefile
@@ -10,6 +10,7 @@ lkdtm-$(CONFIG_LKDTM)		+= rodata_objcopy.o
 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
diff --git a/drivers/misc/lkdtm/core.c b/drivers/misc/lkdtm/core.c
index b8c51a633fcc..3c0a67f072c0 100644
--- a/drivers/misc/lkdtm/core.c
+++ b/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
diff --git a/drivers/misc/lkdtm/fortify.c b/drivers/misc/lkdtm/fortify.c
new file mode 100644
index 000000000000..faf29cf04baa
--- /dev/null
+++ b/drivers/misc/lkdtm/fortify.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2020 Francis Laniel <laniel_francis@privacyrequired.com>
+ *
+ * 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);
+}
diff --git a/drivers/misc/lkdtm/lkdtm.h b/drivers/misc/lkdtm/lkdtm.h
index 49e6b945feb7..138f06254b61 100644
--- a/drivers/misc/lkdtm/lkdtm.h
+++ b/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
diff --git a/tools/testing/selftests/lkdtm/tests.txt b/tools/testing/selftests/lkdtm/tests.txt
index 74a8d329a72c..92ba4cc41314 100644
--- a/tools/testing/selftests/lkdtm/tests.txt
+++ b/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
-- 
2.20.1


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v6 5/5] Correct wrong filenames in comment.
  2020-11-19 16:49 [PATCH v6 0/5] Fortify strscpy() laniel_francis
                   ` (3 preceding siblings ...)
  2020-11-19 16:49 ` [PATCH v6 4/5] Add new file in LKDTM to test fortified strscpy laniel_francis
@ 2020-11-19 16:49 ` laniel_francis
  2020-11-20  1:35 ` [PATCH v6 0/5] Fortify strscpy() Andrew Morton
  5 siblings, 0 replies; 14+ messages in thread
From: laniel_francis @ 2020-11-19 16:49 UTC (permalink / raw)
  To: akpm
  Cc: linux-hardening, linux-mm, linux-kernel, dja, keescook, Francis Laniel

From: Francis Laniel <laniel_francis@privacyrequired.com>

In lkdtm.h, files targeted in comments are named "lkdtm_file.c" while there are
named "file.c" in directory.

Signed-off-by: Francis Laniel <laniel_francis@privacyrequired.com>
Acked-by: Kees Cook <keescook@chromium.org>
---
 drivers/misc/lkdtm/lkdtm.h | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/misc/lkdtm/lkdtm.h b/drivers/misc/lkdtm/lkdtm.h
index 138f06254b61..6aa6d6a1a839 100644
--- a/drivers/misc/lkdtm/lkdtm.h
+++ b/drivers/misc/lkdtm/lkdtm.h
@@ -6,7 +6,7 @@
 
 #include <linux/kernel.h>
 
-/* lkdtm_bugs.c */
+/* bugs.c */
 void __init lkdtm_bugs_init(int *recur_param);
 void lkdtm_PANIC(void);
 void lkdtm_BUG(void);
@@ -35,7 +35,7 @@ void lkdtm_CORRUPT_PAC(void);
 void lkdtm_FORTIFY_OBJECT(void);
 void lkdtm_FORTIFY_SUBOBJECT(void);
 
-/* lkdtm_heap.c */
+/* heap.c */
 void __init lkdtm_heap_init(void);
 void __exit lkdtm_heap_exit(void);
 void lkdtm_OVERWRITE_ALLOCATION(void);
@@ -47,7 +47,7 @@ void lkdtm_SLAB_FREE_DOUBLE(void);
 void lkdtm_SLAB_FREE_CROSS(void);
 void lkdtm_SLAB_FREE_PAGE(void);
 
-/* lkdtm_perms.c */
+/* perms.c */
 void __init lkdtm_perms_init(void);
 void lkdtm_WRITE_RO(void);
 void lkdtm_WRITE_RO_AFTER_INIT(void);
@@ -62,7 +62,7 @@ void lkdtm_EXEC_NULL(void);
 void lkdtm_ACCESS_USERSPACE(void);
 void lkdtm_ACCESS_NULL(void);
 
-/* lkdtm_refcount.c */
+/* refcount.c */
 void lkdtm_REFCOUNT_INC_OVERFLOW(void);
 void lkdtm_REFCOUNT_ADD_OVERFLOW(void);
 void lkdtm_REFCOUNT_INC_NOT_ZERO_OVERFLOW(void);
@@ -83,10 +83,10 @@ void lkdtm_REFCOUNT_SUB_AND_TEST_SATURATED(void);
 void lkdtm_REFCOUNT_TIMING(void);
 void lkdtm_ATOMIC_TIMING(void);
 
-/* lkdtm_rodata.c */
+/* rodata.c */
 void lkdtm_rodata_do_nothing(void);
 
-/* lkdtm_usercopy.c */
+/* usercopy.c */
 void __init lkdtm_usercopy_init(void);
 void __exit lkdtm_usercopy_exit(void);
 void lkdtm_USERCOPY_HEAP_SIZE_TO(void);
@@ -98,7 +98,7 @@ void lkdtm_USERCOPY_STACK_FRAME_FROM(void);
 void lkdtm_USERCOPY_STACK_BEYOND(void);
 void lkdtm_USERCOPY_KERNEL(void);
 
-/* lkdtm_stackleak.c */
+/* stackleak.c */
 void lkdtm_STACKLEAK_ERASING(void);
 
 /* cfi.c */
-- 
2.20.1


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v6 0/5] Fortify strscpy()
  2020-11-19 16:49 [PATCH v6 0/5] Fortify strscpy() laniel_francis
                   ` (4 preceding siblings ...)
  2020-11-19 16:49 ` [PATCH v6 5/5] Correct wrong filenames in comment laniel_francis
@ 2020-11-20  1:35 ` Andrew Morton
  2020-11-20  9:40   ` Francis Laniel
  2020-11-20 13:33   ` David Laight
  5 siblings, 2 replies; 14+ messages in thread
From: Andrew Morton @ 2020-11-20  1:35 UTC (permalink / raw)
  To: laniel_francis; +Cc: linux-hardening, linux-mm, linux-kernel, dja, keescook

On Thu, 19 Nov 2020 17:49:10 +0100 laniel_francis@privacyrequired.com wrote:

> From: Francis Laniel <laniel_francis@privacyrequired.com>
> 
> Hi.
> 
> 
> I hope your families, friends and yourselves are fine.

Thanks.  You too ;)

> This patch set answers to this issue:
> https://github.com/KSPP/linux/issues/46

I fail to understand what this patchset has to do with that
one-element-array issue :(

> I based my modifications on top of two patches from Daniel Axtens which modify
> calls to __builtin_object_size to ensure the true size of char * are returned
> and not the surrounding structure size.
> 
> To sum up, in my first patch I implemented a fortified version of strscpy.
> This new version ensures the following before calling vanilla strscpy:
> 1. There is no read overflow because 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.
> The second patch brings a new file in LKDTM driver to test this new version.
> The test ensures the fortified version still returns the same value as the
> vanilla one while panic'ing when there is a write overflow.
> The third just corrects some typos in LKDTM related file.
> 
> If you see any problem or way to improve the code, feel free to share it.

Could you please send along a reworked [0/n] cover letter?  Explain in
your own words, without requiring that readers go off and read web
pages

- What problem the patchset solves
- How it solves it
- The value of the patchset (to kernel developers or to end-users) so that we
  can understand why it should be merged.

Thanks.


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v6 1/5] string.h: detect intra-object overflow in fortified string functions
  2020-11-19 16:49 ` [PATCH v6 1/5] string.h: detect intra-object overflow in fortified string functions laniel_francis
@ 2020-11-20  1:38   ` Andrew Morton
  2020-11-20  9:41     ` Francis Laniel
  0 siblings, 1 reply; 14+ messages in thread
From: Andrew Morton @ 2020-11-20  1:38 UTC (permalink / raw)
  To: laniel_francis
  Cc: linux-hardening, linux-mm, linux-kernel, dja, keescook, Daniel Micay

On Thu, 19 Nov 2020 17:49:11 +0100 laniel_francis@privacyrequired.com wrote:

> From: Daniel Axtens <dja@axtens.net>
> 
> ...
> 
> Cc: Daniel Micay <danielmicay@gmail.com>
> Cc: Kees Cook <keescook@chromium.org>
> Reviewed-by: Kees Cook <keescook@chromium.org>
> Signed-off-by: Daniel Axtens <dja@axtens.net>

This patch should have your signoff as well, as per
Documentation/process/submitting-patches.rst "Developer's Certificate
of Origin 1.1".

I think it would be best to send out a v7 to address this and the cover
letter issue, please.


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v6 0/5] Fortify strscpy()
  2020-11-20  1:35 ` [PATCH v6 0/5] Fortify strscpy() Andrew Morton
@ 2020-11-20  9:40   ` Francis Laniel
  2020-11-20 19:52     ` Kees Cook
  2020-11-20 13:33   ` David Laight
  1 sibling, 1 reply; 14+ messages in thread
From: Francis Laniel @ 2020-11-20  9:40 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-hardening, linux-mm, linux-kernel, dja, keescook

Le vendredi 20 novembre 2020, 02:35:43 CET Andrew Morton a écrit :
> On Thu, 19 Nov 2020 17:49:10 +0100 laniel_francis@privacyrequired.com wrote:
> > From: Francis Laniel <laniel_francis@privacyrequired.com>
> > 
> > Hi.
> > 
> > 
> > I hope your families, friends and yourselves are fine.
> 
> Thanks.  You too ;)

Thank you!

> > This patch set answers to this issue:
> > https://github.com/KSPP/linux/issues/46
> 
> I fail to understand what this patchset has to do with that
> one-element-array issue :(

I think I linked another issue totally not related with that one...

> > I based my modifications on top of two patches from Daniel Axtens which
> > modify calls to __builtin_object_size to ensure the true size of char *
> > are returned and not the surrounding structure size.
> > 
> > To sum up, in my first patch I implemented a fortified version of strscpy.
> > This new version ensures the following before calling vanilla strscpy:
> > 1. There is no read overflow because 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.
> > The second patch brings a new file in LKDTM driver to test this new
> > version. The test ensures the fortified version still returns the same
> > value as the vanilla one while panic'ing when there is a write overflow.
> > The third just corrects some typos in LKDTM related file.
> > 
> > If you see any problem or way to improve the code, feel free to share it.
> 
> Could you please send along a reworked [0/n] cover letter?  Explain in
> your own words, without requiring that readers go off and read web
> pages
> 
> - What problem the patchset solves
> - How it solves it
> - The value of the patchset (to kernel developers or to end-users) so that
> we can understand why it should be merged.
> 
> Thanks.

I will do it, moreover Kees Cook already told me that cover letter should 
suffices itself (e.g. if the issue disappeared on GitHub).
So I will rework the cover letter for the v7!




^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v6 1/5] string.h: detect intra-object overflow in fortified string functions
  2020-11-20  1:38   ` Andrew Morton
@ 2020-11-20  9:41     ` Francis Laniel
  0 siblings, 0 replies; 14+ messages in thread
From: Francis Laniel @ 2020-11-20  9:41 UTC (permalink / raw)
  To: Andrew Morton
  Cc: linux-hardening, linux-mm, linux-kernel, dja, keescook, Daniel Micay

Le vendredi 20 novembre 2020, 02:38:22 CET Andrew Morton a écrit :
> On Thu, 19 Nov 2020 17:49:11 +0100 laniel_francis@privacyrequired.com wrote:
> > From: Daniel Axtens <dja@axtens.net>
> > 
> > ...
> > 
> > Cc: Daniel Micay <danielmicay@gmail.com>
> > Cc: Kees Cook <keescook@chromium.org>
> > Reviewed-by: Kees Cook <keescook@chromium.org>
> > Signed-off-by: Daniel Axtens <dja@axtens.net>
> 
> This patch should have your signoff as well, as per
> Documentation/process/submitting-patches.rst "Developer's Certificate
> of Origin 1.1".
> 
> I think it would be best to send out a v7 to address this and the cover
> letter issue, please.

Will be done for the v7!
I just read the documentation page, rebase on Linus Torvalds tree and send the 
v7!




^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: [PATCH v6 0/5] Fortify strscpy()
  2020-11-20  1:35 ` [PATCH v6 0/5] Fortify strscpy() Andrew Morton
  2020-11-20  9:40   ` Francis Laniel
@ 2020-11-20 13:33   ` David Laight
  2020-11-20 15:51     ` Francis Laniel
  1 sibling, 1 reply; 14+ messages in thread
From: David Laight @ 2020-11-20 13:33 UTC (permalink / raw)
  To: 'Andrew Morton', laniel_francis
  Cc: linux-hardening, linux-mm, linux-kernel, dja, keescook

From: Andrew Morton
> Sent: 20 November 2020 01:36
...
> Could you please send along a reworked [0/n] cover letter?  Explain in
> your own words, without requiring that readers go off and read web
> pages
> 
> - What problem the patchset solves
> - How it solves it
> - The value of the patchset (to kernel developers or to end-users) so that we
>   can understand why it should be merged.

- How much it slows things down.

	David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v6 0/5] Fortify strscpy()
  2020-11-20 13:33   ` David Laight
@ 2020-11-20 15:51     ` Francis Laniel
  0 siblings, 0 replies; 14+ messages in thread
From: Francis Laniel @ 2020-11-20 15:51 UTC (permalink / raw)
  To: David Laight
  Cc: 'Andrew Morton',
	linux-hardening, linux-mm, linux-kernel, dja, keescook

Le vendredi 20 novembre 2020, 14:33:53 CET David Laight a écrit :
> From: Andrew Morton
> 
> > Sent: 20 November 2020 01:36
> 
> ...
> 
> > Could you please send along a reworked [0/n] cover letter?  Explain in
> > your own words, without requiring that readers go off and read web
> > pages
> > 
> > - What problem the patchset solves
> > - How it solves it
> > - The value of the patchset (to kernel developers or to end-users) so that
> > we> 
> >   can understand why it should be merged.
> 
> - How much it slows things down.

I will add it for the next version!

> 	David
> 
> -
> Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1
> 1PT, UK Registration No: 1397386 (Wales)





^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v6 0/5] Fortify strscpy()
  2020-11-20  9:40   ` Francis Laniel
@ 2020-11-20 19:52     ` Kees Cook
  2020-11-22 16:28       ` Francis Laniel
  0 siblings, 1 reply; 14+ messages in thread
From: Kees Cook @ 2020-11-20 19:52 UTC (permalink / raw)
  To: Francis Laniel
  Cc: Andrew Morton, linux-hardening, linux-mm, linux-kernel, dja

On Fri, Nov 20, 2020 at 10:40:38AM +0100, Francis Laniel wrote:
> Le vendredi 20 novembre 2020, 02:35:43 CET Andrew Morton a écrit :
> > On Thu, 19 Nov 2020 17:49:10 +0100 laniel_francis@privacyrequired.com wrote:
> > > This patch set answers to this issue:
> > > https://github.com/KSPP/linux/issues/46
> > 
> > I fail to understand what this patchset has to do with that
> > one-element-array issue :(
>
> I think I linked another issue totally not related with that one...

This just looks like a typo. The URL should be:
https://github.com/KSPP/linux/issues/96

-- 
Kees Cook

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v6 0/5] Fortify strscpy()
  2020-11-20 19:52     ` Kees Cook
@ 2020-11-22 16:28       ` Francis Laniel
  0 siblings, 0 replies; 14+ messages in thread
From: Francis Laniel @ 2020-11-22 16:28 UTC (permalink / raw)
  To: Kees Cook; +Cc: Andrew Morton, linux-hardening, linux-mm, linux-kernel, dja

Le vendredi 20 novembre 2020, 20:52:07 CET Kees Cook a écrit :
> On Fri, Nov 20, 2020 at 10:40:38AM +0100, Francis Laniel wrote:
> > Le vendredi 20 novembre 2020, 02:35:43 CET Andrew Morton a écrit :
> > > On Thu, 19 Nov 2020 17:49:10 +0100 laniel_francis@privacyrequired.com 
wrote:
> > > > This patch set answers to this issue:
> > > > https://github.com/KSPP/linux/issues/46
> > > 
> > > I fail to understand what this patchset has to do with that
> > > one-element-array issue :(
> > 
> > I think I linked another issue totally not related with that one...
> 
> This just looks like a typo. The URL should be:
> https://github.com/KSPP/linux/issues/96

This is not a typo because my branch to work on this issue is called 46-
fortifiy_strscpy.
I just think I got mixed up!

But I completely removed the link to this issue in the v7, so it does not 
matter a lot now.



^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2020-11-22 16:29 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-19 16:49 [PATCH v6 0/5] Fortify strscpy() laniel_francis
2020-11-19 16:49 ` [PATCH v6 1/5] string.h: detect intra-object overflow in fortified string functions laniel_francis
2020-11-20  1:38   ` Andrew Morton
2020-11-20  9:41     ` Francis Laniel
2020-11-19 16:49 ` [PATCH v6 2/5] lkdtm: tests for FORTIFY_SOURCE laniel_francis
2020-11-19 16:49 ` [PATCH v6 3/5] string.h: Add FORTIFY coverage for strscpy() laniel_francis
2020-11-19 16:49 ` [PATCH v6 4/5] Add new file in LKDTM to test fortified strscpy laniel_francis
2020-11-19 16:49 ` [PATCH v6 5/5] Correct wrong filenames in comment laniel_francis
2020-11-20  1:35 ` [PATCH v6 0/5] Fortify strscpy() Andrew Morton
2020-11-20  9:40   ` Francis Laniel
2020-11-20 19:52     ` Kees Cook
2020-11-22 16:28       ` Francis Laniel
2020-11-20 13:33   ` David Laight
2020-11-20 15:51     ` Francis Laniel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).