A common idiom in kernel code is to wipe the contents of a structure
after a given member. This includes places where there is trailing
struct padding. These open-coded cases are usually difficult to read and
very sensitive to struct layout changes. Introduce a new helper,
memset_after() that takes the target struct instance, the byte to
write, and the member name after which the zeroing should start.

Signed-off-by: Kees Cook <keesc...@chromium.org>
---
 include/linux/string.h | 12 ++++++++++++
 lib/test_memcpy.c      | 12 ++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/include/linux/string.h b/include/linux/string.h
index cbe889e404e2..4f9f67505f70 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -272,6 +272,18 @@ static __always_inline void memcpy_and_pad(void *dest, 
size_t dest_len,
                memcpy(dest, src, dest_len);
 }
 
+/**
+ * memset_after - Set a value after a struct member to the end of a struct
+ *
+ * @obj: Address of target struct instance
+ * @v: Byte value to repeatedly write
+ * @member: after which struct member to start writing bytes
+ */
+#define memset_after(obj, v, member) do {                              \
+       memset((u8 *)(obj) + offsetofend(typeof(*(obj)), member), v,    \
+              sizeof(*(obj)) - offsetofend(typeof(*(obj)), member));   \
+} while (0)
+
 /**
  * str_has_prefix - Test if a string has a given prefix
  * @str: The string to test
diff --git a/lib/test_memcpy.c b/lib/test_memcpy.c
index 7c64120a68a9..f52b284f4410 100644
--- a/lib/test_memcpy.c
+++ b/lib/test_memcpy.c
@@ -223,6 +223,13 @@ static int __init test_memset(void)
                          0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
                        },
        };
+       struct some_bytes after = {
+               .data = { 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x72,
+                         0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72,
+                         0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72,
+                         0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72,
+                       },
+       };
        struct some_bytes dest = { };
        int count, value;
        u8 *ptr;
@@ -254,6 +261,11 @@ static int __init test_memset(void)
        memset(ptr++, value++, count++);
        compare("argument side-effects", dest, three);
 
+       /* Verify memset_after() */
+       dest = control;
+       memset_after(&dest, 0x72, three);
+       compare("memset_after()", dest, after);
+
        return 0;
 #undef TEST_OP
 }
-- 
2.30.2

Reply via email to