@@ -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
@@ -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
}
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 <keescook@chromium.org> --- include/linux/string.h | 12 ++++++++++++ lib/test_memcpy.c | 12 ++++++++++++ 2 files changed, 24 insertions(+)