| From: Alexander Potapenko <glider@google.com> |
| Subject: mm: kmsan: implement kmsan_memmove() |
| Date: Wed, 20 Mar 2024 11:18:49 +0100 |
| |
| Provide a hook that can be used by custom memcpy implementations to tell |
| KMSAN that the metadata needs to be copied. Without that, false positive |
| reports are possible in the cases where KMSAN fails to intercept memory |
| initialization. |
| |
| Link: https://lore.kernel.org/all/3b7dbd88-0861-4638-b2d2-911c97a4cadf@I-love.SAKURA.ne.jp/ |
| Link: https://lkml.kernel.org/r/20240320101851.2589698-1-glider@google.com |
| Signed-off-by: Alexander Potapenko <glider@google.com> |
| Suggested-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> |
| Reviewed-by: Marco Elver <elver@google.com> |
| Cc: Dmitry Vyukov <dvyukov@google.com> |
| Cc: Linus Torvalds <torvalds@linux-foundation.org> |
| Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> |
| Cc: Thomas Gleixner <tglx@linutronix.de> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| --- |
| |
| include/linux/kmsan-checks.h | 15 +++++++++++++++ |
| mm/kmsan/hooks.c | 11 +++++++++++ |
| 2 files changed, 26 insertions(+) |
| |
| --- a/include/linux/kmsan-checks.h~mm-kmsan-implement-kmsan_memmove |
| +++ a/include/linux/kmsan-checks.h |
| @@ -61,6 +61,17 @@ void kmsan_check_memory(const void *addr |
| void kmsan_copy_to_user(void __user *to, const void *from, size_t to_copy, |
| size_t left); |
| |
| +/** |
| + * kmsan_memmove() - Notify KMSAN about a data copy within kernel. |
| + * @to: destination address in the kernel. |
| + * @from: source address in the kernel. |
| + * @size: number of bytes to copy. |
| + * |
| + * Invoked after non-instrumented version (e.g. implemented using assembly |
| + * code) of memmove()/memcpy() is called, in order to copy KMSAN's metadata. |
| + */ |
| +void kmsan_memmove(void *to, const void *from, size_t to_copy); |
| + |
| #else |
| |
| static inline void kmsan_poison_memory(const void *address, size_t size, |
| @@ -78,6 +89,10 @@ static inline void kmsan_copy_to_user(vo |
| { |
| } |
| |
| +static inline void kmsan_memmove(void *to, const void *from, size_t to_copy) |
| +{ |
| +} |
| + |
| #endif |
| |
| #endif /* _LINUX_KMSAN_CHECKS_H */ |
| --- a/mm/kmsan/hooks.c~mm-kmsan-implement-kmsan_memmove |
| +++ a/mm/kmsan/hooks.c |
| @@ -285,6 +285,17 @@ void kmsan_copy_to_user(void __user *to, |
| } |
| EXPORT_SYMBOL(kmsan_copy_to_user); |
| |
| +void kmsan_memmove(void *to, const void *from, size_t size) |
| +{ |
| + if (!kmsan_enabled || kmsan_in_runtime()) |
| + return; |
| + |
| + kmsan_enter_runtime(); |
| + kmsan_internal_memmove_metadata(to, (void *)from, size); |
| + kmsan_leave_runtime(); |
| +} |
| +EXPORT_SYMBOL(kmsan_memmove); |
| + |
| /* Helper function to check an URB. */ |
| void kmsan_handle_urb(const struct urb *urb, bool is_out) |
| { |
| _ |