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@xxxxxxxxxxxx> --- 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