From patchwork Wed Mar 25 16:12:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Potapenko X-Patchwork-Id: 11458279 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B8F51913 for ; Wed, 25 Mar 2020 16:14:28 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 6C4DC20409 for ; Wed, 25 Mar 2020 16:14:28 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="MYbrzIrq" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6C4DC20409 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 4CEB86B000E; Wed, 25 Mar 2020 12:14:14 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 3D39B6B009B; Wed, 25 Mar 2020 12:14:14 -0400 (EDT) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 24D9D6B009E; Wed, 25 Mar 2020 12:14:14 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0106.hostedemail.com [216.40.44.106]) by kanga.kvack.org (Postfix) with ESMTP id E3F6B6B000E for ; Wed, 25 Mar 2020 12:14:13 -0400 (EDT) Received: from smtpin26.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay02.hostedemail.com (Postfix) with ESMTP id CB7C923118 for ; Wed, 25 Mar 2020 16:14:13 +0000 (UTC) X-FDA: 76634381586.26.spy60_7c30d4939a554 X-Spam-Summary: 2,0,0,fabb2887528f0fdc,d41d8cd98f00b204,3u4n7xgykceikpmhivksskpi.gsqpmry1-qqozego.svk@flex--glider.bounces.google.com,,RULES_HIT:1:2:41:152:355:379:541:800:960:968:973:988:989:1260:1277:1313:1314:1345:1359:1431:1437:1516:1518:1593:1594:1605:1730:1747:1777:1792:1801:2194:2199:2393:2553:2559:2562:2895:2904:3138:3139:3140:3141:3142:3152:3865:3866:3867:3868:3870:3871:3872:3874:4051:4250:4321:4605:5007:6119:6261:6653:6742:6743:7774:7875:7903:7974:8660:9040:9969:11026:11473:11657:11658:11914:12043:12048:12291:12296:12297:12438:12555:12895:12986:13148:13230:13846:13972:14096:14097:14394:14659:21080:21325:21365:21433:21444:21451:21618:21795:21966:21987:21990:30012:30029:30045:30051:30054:30064:30075:30079:30090,0,RBL:209.85.128.73:@flex--glider.bounces.google.com:.lbl8.mailshell.net-62.18.0.100 66.100.201.100,CacheIP:none,Bayesian:0.5,0.5,0.5,Netcheck:none,DomainCache:0,MSF:not bulk,SPF:fp,MSBL:0,DNSBL:none,Custom_rules:0:1:0,LFtime:2,LUA_SUMMARY:none X-HE-Tag: spy60_7c30d4939a554 X-Filterd-Recvd-Size: 12116 Received: from mail-wm1-f73.google.com (mail-wm1-f73.google.com [209.85.128.73]) by imf30.hostedemail.com (Postfix) with ESMTP for ; Wed, 25 Mar 2020 16:14:13 +0000 (UTC) Received: by mail-wm1-f73.google.com with SMTP id y1so1073874wmj.3 for ; Wed, 25 Mar 2020 09:14:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=hDEG4SL4kroOQXm1WszfPhYOz0CcPiVpP2hbsmuCCeY=; b=MYbrzIrqVxxzIGycKH1/6Rq/YAclt9uQQ1gKsN3qxXZZrnHp9ql3MFwHyQKn2q28Fw A2Xnd2mCeJESFu1a8wM1zhxMEHrRbvDOtHpRhm46vQl5p0sUOO06jOWXHUeWnUFfeoQw sDI8etOUaP4gBUAjZeHzP4YQ9pjcn/fgYbNqhzvjCrhC8frGGDue+nd3slYa48x6+ZBY fmOpJ1rJamwXQiBUJyyLC8XyqJnI1zbCSpPlime0QuAqUPeE7UZ0oKLDjOjOkXy3Cwwm vhSlJhStcSfW9WyWNodnegvw/tPXFl/+G9ZOgwxyPNUY03Cg9KIiFD1xyDp2EIx6fnfR FiMQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=hDEG4SL4kroOQXm1WszfPhYOz0CcPiVpP2hbsmuCCeY=; b=mMOiNJTEd2RNVAmB3CT6KkF39HH0sxN6z0GkT5xm1WVnRIG58K3+JIkKZYifVrDT7S Hbd/3ovXnjaQoKt97BdV4utD6htpsP4vgtwdGYdwmlys1FH/S8nR7SQIYNnR5D7X/NV7 GQAi1biJGggM40kjVxmtByx6K9semWCh/r8ZWEFRu/3d86Ruj/tmUfr1inuPigz1JgEx zNlqxFlA2ug2TT7YdpgadMnGufRsDeYXlLy1HFiNTyJzj0yi92WlIssxRgrDc+TCk7V4 +rCvvr1ah+SYqwRbVskQ7cWLpB6NM8wnogivReHehaMkqXtQuAva7DDi8Hn0LE9RA8x7 OmHg== X-Gm-Message-State: ANhLgQ3XS7VB21O/aVppXW5+etBJxht0cwWbIgA0v4bsvxEosWDA0zI0 cgRGHMRWIkkeTjnlHCxVwdth2+A/2Mw= X-Google-Smtp-Source: ADFU+vt/2hLUuCl0oc5iXdL/FQyJ0Y0Nfl1tE0Wm2ypMPo1e8PQclrs4LqCJegH58xzwkapY7i8AdqLi6EQ= X-Received: by 2002:a5d:488c:: with SMTP id g12mr4344764wrq.67.1585152851835; Wed, 25 Mar 2020 09:14:11 -0700 (PDT) Date: Wed, 25 Mar 2020 17:12:35 +0100 In-Reply-To: <20200325161249.55095-1-glider@google.com> Message-Id: <20200325161249.55095-25-glider@google.com> Mime-Version: 1.0 References: <20200325161249.55095-1-glider@google.com> X-Mailer: git-send-email 2.25.1.696.g5e7596f4ac-goog Subject: [PATCH v5 24/38] kmsan: disable instrumentation of certain functions From: glider@google.com To: Thomas Gleixner , Andrew Morton , Vegard Nossum , Dmitry Vyukov , Marco Elver , Andrey Konovalov , linux-mm@kvack.org Cc: glider@google.com, viro@zeniv.linux.org.uk, adilger.kernel@dilger.ca, aryabinin@virtuozzo.com, luto@kernel.org, ard.biesheuvel@linaro.org, arnd@arndb.de, hch@infradead.org, hch@lst.de, darrick.wong@oracle.com, davem@davemloft.net, dmitry.torokhov@gmail.com, ebiggers@google.com, edumazet@google.com, ericvh@gmail.com, gregkh@linuxfoundation.org, harry.wentland@amd.com, herbert@gondor.apana.org.au, iii@linux.ibm.com, mingo@elte.hu, jasowang@redhat.com, axboe@kernel.dk, m.szyprowski@samsung.com, mark.rutland@arm.com, martin.petersen@oracle.com, schwidefsky@de.ibm.com, willy@infradead.org, mst@redhat.com, mhocko@suse.com, monstr@monstr.eu, pmladek@suse.com, cai@lca.pw, rdunlap@infradead.org, robin.murphy@arm.com, sergey.senozhatsky@gmail.com, rostedt@goodmis.org, tiwai@suse.com, tytso@mit.edu, gor@linux.ibm.com, wsa@the-dreams.de X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: Some functions are called from handwritten assembly, and therefore don't have their arguments' metadata fully set up by the instrumentation code. Mark them with __no_sanitize_memory to avoid false positives from spreading further. Certain functions perform task switching, so that the value of |current| is different as they proceed. Because KMSAN state pointer is only read once at the beginning of the function, touching it after |current| has changed may be dangerous. Signed-off-by: Alexander Potapenko To: Alexander Potapenko Cc: Thomas Gleixner Cc: Andrew Morton Cc: Vegard Nossum Cc: Dmitry Vyukov Cc: Marco Elver Cc: Andrey Konovalov Cc: linux-mm@kvack.org --- v3: - removed TODOs from comments v4: - updated the comments, dropped __no_sanitize_memory from idle_cpu(), sched_init(), profile_tick() - split away the uprobes part as requested by Andrey Konovalov Change-Id: I684d23dac5a22eb0a4cea71993cb934302b17cea --- arch/x86/entry/common.c | 2 ++ arch/x86/include/asm/irq_regs.h | 2 ++ arch/x86/include/asm/syscall_wrapper.h | 2 ++ arch/x86/kernel/apic/apic.c | 3 +++ arch/x86/kernel/dumpstack_64.c | 5 +++++ arch/x86/kernel/process_64.c | 5 +++++ arch/x86/kernel/traps.c | 13 +++++++++++-- kernel/sched/core.c | 22 ++++++++++++++++++++++ 8 files changed, 52 insertions(+), 2 deletions(-) diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c index ec167d8c41cbd..5c3d0f3a14c37 100644 --- a/arch/x86/entry/common.c +++ b/arch/x86/entry/common.c @@ -280,6 +280,8 @@ __visible inline void syscall_return_slowpath(struct pt_regs *regs) } #ifdef CONFIG_X86_64 +/* Tell KMSAN to not instrument this function and to initialize |regs|. */ +__no_sanitize_memory __visible void do_syscall_64(unsigned long nr, struct pt_regs *regs) { struct thread_info *ti; diff --git a/arch/x86/include/asm/irq_regs.h b/arch/x86/include/asm/irq_regs.h index 187ce59aea28e..a6fc1641e2861 100644 --- a/arch/x86/include/asm/irq_regs.h +++ b/arch/x86/include/asm/irq_regs.h @@ -14,6 +14,8 @@ DECLARE_PER_CPU(struct pt_regs *, irq_regs); +/* Tell KMSAN to return an initialized struct pt_regs. */ +__no_sanitize_memory static inline struct pt_regs *get_irq_regs(void) { return __this_cpu_read(irq_regs); diff --git a/arch/x86/include/asm/syscall_wrapper.h b/arch/x86/include/asm/syscall_wrapper.h index e2389ce9bf58a..098b1a8d6bc41 100644 --- a/arch/x86/include/asm/syscall_wrapper.h +++ b/arch/x86/include/asm/syscall_wrapper.h @@ -196,6 +196,8 @@ struct pt_regs; ALLOW_ERROR_INJECTION(__x64_sys##name, ERRNO); \ static long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\ + /* Tell KMSAN to initialize |regs|. */ \ + __no_sanitize_memory \ asmlinkage long __x64_sys##name(const struct pt_regs *regs) \ { \ return __se_sys##name(SC_X86_64_REGS_TO_ARGS(x,__VA_ARGS__));\ diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 5f973fed3c9ff..1f0250f14e462 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1127,6 +1127,9 @@ static void local_apic_timer_interrupt(void) * [ if a single-CPU system runs an SMP kernel then we call the local * interrupt as well. Thus we cannot inline the local irq ... ] */ + +/* Tell KMSAN to initialize |regs|. */ +__no_sanitize_memory __visible void __irq_entry smp_apic_timer_interrupt(struct pt_regs *regs) { struct pt_regs *old_regs = set_irq_regs(regs); diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c index 87b97897a8810..3d1691f81cada 100644 --- a/arch/x86/kernel/dumpstack_64.c +++ b/arch/x86/kernel/dumpstack_64.c @@ -150,6 +150,11 @@ static bool in_irq_stack(unsigned long *stack, struct stack_info *info) return true; } +/* + * This function may touch stale uninitialized values on stack. Do not + * instrument it with KMSAN to avoid false positives. + */ +__no_sanitize_memory int get_stack_info(unsigned long *stack, struct task_struct *task, struct stack_info *info, unsigned long *visit_mask) { diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index ffd497804dbc3..5e8c6767e9916 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -424,6 +424,11 @@ void compat_start_thread(struct pt_regs *regs, u32 new_ip, u32 new_sp) * Kprobes not supported here. Set the probe on schedule instead. * Function graph tracer not supported too. */ +/* + * Avoid touching KMSAN state or reporting anything here, as __switch_to() does + * weird things with tasks. + */ +__no_sanitize_memory __visible __notrace_funcgraph struct task_struct * __switch_to(struct task_struct *prev_p, struct task_struct *next_p) { diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index d54cffdc7cac2..917268aee054e 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -638,7 +638,11 @@ NOKPROBE_SYMBOL(do_int3); * Help handler running on a per-cpu (IST or entry trampoline) stack * to switch to the normal thread stack if the interrupted code was in * user mode. The actual stack switch is done in entry_64.S + * */ + +/* This function switches the registers - don't instrument it with KMSAN. */ +__no_sanitize_memory asmlinkage __visible notrace struct pt_regs *sync_regs(struct pt_regs *eregs) { struct pt_regs *regs = (struct pt_regs *)this_cpu_read(cpu_current_top_of_stack) - 1; @@ -654,6 +658,11 @@ struct bad_iret_stack { }; asmlinkage __visible notrace +/* + * Dark magic happening here, let's not instrument this function. + * Also avoid copying any metadata by using raw __memmove(). + */ +__no_sanitize_memory struct bad_iret_stack *fixup_bad_iret(struct bad_iret_stack *s) { /* @@ -668,10 +677,10 @@ struct bad_iret_stack *fixup_bad_iret(struct bad_iret_stack *s) (struct bad_iret_stack *)this_cpu_read(cpu_tss_rw.x86_tss.sp0) - 1; /* Copy the IRET target to the new stack. */ - memmove(&new_stack->regs.ip, (void *)s->regs.sp, 5*8); + __memmove(&new_stack->regs.ip, (void *)s->regs.sp, 5*8); /* Copy the remainder of the stack from the current stack. */ - memmove(new_stack, s, offsetof(struct bad_iret_stack, regs.ip)); + __memmove(new_stack, s, offsetof(struct bad_iret_stack, regs.ip)); BUG_ON(!user_mode(&new_stack->regs)); return new_stack; diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 1a5937936ac75..bb1b659c12f6a 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -471,6 +471,11 @@ void wake_q_add_safe(struct wake_q_head *head, struct task_struct *task) put_task_struct(task); } +/* + * Context switch here may lead to KMSAN task state corruption. Disable KMSAN + * instrumentation. + */ +__no_sanitize_memory void wake_up_q(struct wake_q_head *head) { struct wake_q_node *node = head->first; @@ -3217,6 +3222,12 @@ prepare_task_switch(struct rq *rq, struct task_struct *prev, * past. prev == current is still correct but we need to recalculate this_rq * because prev may have moved to another CPU. */ + +/* + * Context switch here may lead to KMSAN task state corruption. Disable KMSAN + * instrumentation. + */ +__no_sanitize_memory static struct rq *finish_task_switch(struct task_struct *prev) __releases(rq->lock) { @@ -4052,6 +4063,12 @@ pick_next_task(struct rq *rq, struct task_struct *prev, struct rq_flags *rf) * * WARNING: must be called with preemption disabled! */ + +/* + * Context switch here may lead to KMSAN task state corruption. Disable KMSAN + * instrumentation. + */ +__no_sanitize_memory static void __sched notrace __schedule(bool preempt) { struct task_struct *prev, *next; @@ -6789,6 +6806,11 @@ static inline int preempt_count_equals(int preempt_offset) return (nested == preempt_offset); } +/* + * This function might be called from code that is not instrumented with KMSAN. + * Nevertheless, treat its arguments as initialized. + */ +__no_sanitize_memory void __might_sleep(const char *file, int line, int preempt_offset) { /*