| From: Alexander Potapenko <glider@google.com> |
| Subject: kmsan: handle task creation and exiting |
| Date: Thu, 15 Sep 2022 17:03:50 +0200 |
| |
| Tell KMSAN that a new task is created, so the tool creates a backing |
| metadata structure for that task. |
| |
| Link: https://lkml.kernel.org/r/20220915150417.722975-17-glider@google.com |
| Signed-off-by: Alexander Potapenko <glider@google.com> |
| Cc: Alexander Viro <viro@zeniv.linux.org.uk> |
| Cc: Alexei Starovoitov <ast@kernel.org> |
| Cc: Andrey Konovalov <andreyknvl@gmail.com> |
| Cc: Andrey Konovalov <andreyknvl@google.com> |
| Cc: Andy Lutomirski <luto@kernel.org> |
| Cc: Arnd Bergmann <arnd@arndb.de> |
| Cc: Borislav Petkov <bp@alien8.de> |
| Cc: Christoph Hellwig <hch@lst.de> |
| Cc: Christoph Lameter <cl@linux.com> |
| Cc: David Rientjes <rientjes@google.com> |
| Cc: Dmitry Vyukov <dvyukov@google.com> |
| Cc: Eric Biggers <ebiggers@google.com> |
| Cc: Eric Biggers <ebiggers@kernel.org> |
| Cc: Eric Dumazet <edumazet@google.com> |
| Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| Cc: Herbert Xu <herbert@gondor.apana.org.au> |
| Cc: Ilya Leoshkevich <iii@linux.ibm.com> |
| Cc: Ingo Molnar <mingo@redhat.com> |
| Cc: Jens Axboe <axboe@kernel.dk> |
| Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com> |
| Cc: Kees Cook <keescook@chromium.org> |
| Cc: Marco Elver <elver@google.com> |
| Cc: Mark Rutland <mark.rutland@arm.com> |
| Cc: Matthew Wilcox <willy@infradead.org> |
| Cc: Michael S. Tsirkin <mst@redhat.com> |
| Cc: Pekka Enberg <penberg@kernel.org> |
| Cc: Peter Zijlstra <peterz@infradead.org> |
| Cc: Petr Mladek <pmladek@suse.com> |
| Cc: Stephen Rothwell <sfr@canb.auug.org.au> |
| Cc: Steven Rostedt <rostedt@goodmis.org> |
| Cc: Thomas Gleixner <tglx@linutronix.de> |
| Cc: Vasily Gorbik <gor@linux.ibm.com> |
| Cc: Vegard Nossum <vegard.nossum@oracle.com> |
| Cc: Vlastimil Babka <vbabka@suse.cz> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| --- |
| |
| include/linux/kmsan.h | 21 +++++++++++++++++++++ |
| kernel/exit.c | 2 ++ |
| kernel/fork.c | 2 ++ |
| mm/kmsan/core.c | 10 ++++++++++ |
| mm/kmsan/hooks.c | 17 +++++++++++++++++ |
| mm/kmsan/kmsan.h | 2 ++ |
| 6 files changed, 54 insertions(+) |
| |
| --- a/include/linux/kmsan.h~kmsan-handle-task-creation-and-exiting |
| +++ a/include/linux/kmsan.h |
| @@ -15,10 +15,23 @@ |
| |
| struct page; |
| struct kmem_cache; |
| +struct task_struct; |
| |
| #ifdef CONFIG_KMSAN |
| |
| /** |
| + * kmsan_task_create() - Initialize KMSAN state for the task. |
| + * @task: task to initialize. |
| + */ |
| +void kmsan_task_create(struct task_struct *task); |
| + |
| +/** |
| + * kmsan_task_exit() - Notify KMSAN that a task has exited. |
| + * @task: task about to finish. |
| + */ |
| +void kmsan_task_exit(struct task_struct *task); |
| + |
| +/** |
| * kmsan_alloc_page() - Notify KMSAN about an alloc_pages() call. |
| * @page: struct page pointer returned by alloc_pages(). |
| * @order: order of allocated struct page. |
| @@ -139,6 +152,14 @@ void kmsan_iounmap_page_range(unsigned l |
| |
| #else |
| |
| +static inline void kmsan_task_create(struct task_struct *task) |
| +{ |
| +} |
| + |
| +static inline void kmsan_task_exit(struct task_struct *task) |
| +{ |
| +} |
| + |
| static inline int kmsan_alloc_page(struct page *page, unsigned int order, |
| gfp_t flags) |
| { |
| --- a/kernel/exit.c~kmsan-handle-task-creation-and-exiting |
| +++ a/kernel/exit.c |
| @@ -60,6 +60,7 @@ |
| #include <linux/writeback.h> |
| #include <linux/shm.h> |
| #include <linux/kcov.h> |
| +#include <linux/kmsan.h> |
| #include <linux/random.h> |
| #include <linux/rcuwait.h> |
| #include <linux/compat.h> |
| @@ -742,6 +743,7 @@ void __noreturn do_exit(long code) |
| WARN_ON(tsk->plug); |
| |
| kcov_task_exit(tsk); |
| + kmsan_task_exit(tsk); |
| |
| coredump_task_exit(tsk); |
| ptrace_event(PTRACE_EVENT_EXIT, code); |
| --- a/kernel/fork.c~kmsan-handle-task-creation-and-exiting |
| +++ a/kernel/fork.c |
| @@ -37,6 +37,7 @@ |
| #include <linux/fdtable.h> |
| #include <linux/iocontext.h> |
| #include <linux/key.h> |
| +#include <linux/kmsan.h> |
| #include <linux/binfmts.h> |
| #include <linux/mman.h> |
| #include <linux/mmu_notifier.h> |
| @@ -1023,6 +1024,7 @@ static struct task_struct *dup_task_stru |
| tsk->worker_private = NULL; |
| |
| kcov_task_init(tsk); |
| + kmsan_task_create(tsk); |
| kmap_local_fork(tsk); |
| |
| #ifdef CONFIG_FAULT_INJECTION |
| --- a/mm/kmsan/core.c~kmsan-handle-task-creation-and-exiting |
| +++ a/mm/kmsan/core.c |
| @@ -37,6 +37,16 @@ bool kmsan_enabled __read_mostly; |
| */ |
| DEFINE_PER_CPU(struct kmsan_ctx, kmsan_percpu_ctx); |
| |
| +void kmsan_internal_task_create(struct task_struct *task) |
| +{ |
| + struct kmsan_ctx *ctx = &task->kmsan_ctx; |
| + struct thread_info *info = current_thread_info(); |
| + |
| + __memset(ctx, 0, sizeof(*ctx)); |
| + ctx->allow_reporting = true; |
| + kmsan_internal_unpoison_memory(info, sizeof(*info), false); |
| +} |
| + |
| void kmsan_internal_poison_memory(void *address, size_t size, gfp_t flags, |
| unsigned int poison_flags) |
| { |
| --- a/mm/kmsan/hooks.c~kmsan-handle-task-creation-and-exiting |
| +++ a/mm/kmsan/hooks.c |
| @@ -27,6 +27,23 @@ |
| * skipping effects of functions like memset() inside instrumented code. |
| */ |
| |
| +void kmsan_task_create(struct task_struct *task) |
| +{ |
| + kmsan_enter_runtime(); |
| + kmsan_internal_task_create(task); |
| + kmsan_leave_runtime(); |
| +} |
| + |
| +void kmsan_task_exit(struct task_struct *task) |
| +{ |
| + struct kmsan_ctx *ctx = &task->kmsan_ctx; |
| + |
| + if (!kmsan_enabled || kmsan_in_runtime()) |
| + return; |
| + |
| + ctx->allow_reporting = false; |
| +} |
| + |
| void kmsan_slab_alloc(struct kmem_cache *s, void *object, gfp_t flags) |
| { |
| if (unlikely(object == NULL)) |
| --- a/mm/kmsan/kmsan.h~kmsan-handle-task-creation-and-exiting |
| +++ a/mm/kmsan/kmsan.h |
| @@ -180,6 +180,8 @@ void kmsan_internal_set_shadow_origin(vo |
| u32 origin, bool checked); |
| depot_stack_handle_t kmsan_internal_chain_origin(depot_stack_handle_t id); |
| |
| +void kmsan_internal_task_create(struct task_struct *task); |
| + |
| bool kmsan_metadata_is_contiguous(void *addr, size_t size); |
| void kmsan_internal_check_memory(void *addr, size_t size, const void *user_addr, |
| int reason); |
| _ |