From patchwork Wed Mar 25 16:12:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Potapenko X-Patchwork-Id: 11458219 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 6F78014B4 for ; Wed, 25 Mar 2020 16:12:58 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 2168320409 for ; Wed, 25 Mar 2020 16:12:58 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="Lnlc2Cy3" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 2168320409 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 35F126B000A; Wed, 25 Mar 2020 12:12:57 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 30FF36B000C; Wed, 25 Mar 2020 12:12:57 -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 200236B000D; Wed, 25 Mar 2020 12:12:57 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0113.hostedemail.com [216.40.44.113]) by kanga.kvack.org (Postfix) with ESMTP id 01D6C6B000A for ; Wed, 25 Mar 2020 12:12:56 -0400 (EDT) Received: from smtpin27.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay04.hostedemail.com (Postfix) with ESMTP id D043583C57 for ; Wed, 25 Mar 2020 16:12:56 +0000 (UTC) X-FDA: 76634378352.27.ring36_70f9e957db53e X-Spam-Summary: 2,0,0,04bfbc3c42af0483,d41d8cd98f00b204,3b4n7xgykcpqchezanckkcha.ykihejqt-iigrwyg.knc@flex--glider.bounces.google.com,,RULES_HIT:4:41:152:355:379:541:800:960:967:973:982:988:989:1260:1263:1277:1313:1314:1345:1431:1437:1516:1518:1593:1594:1605:1730:1747:1777:1792:1801:1981:2194:2199:2393:2525:2553:2559:2564:2640:2682:2685:2736:2859:2901:2911:2918:2933:2937:2939:2942:2945:2947:2951:2954:3022:3138:3139:3140:3141:3142:3152:3664:3865:3866:3867:3868:3870:3871:3872:3874:3934:3936:3938:3941:3944:3947:3950:3953:3956:3959:4037:4250:4321:4425:4559:4605:5007:6117:6119:6261:6653:6691:6737:6738:7514:7875:7903:7974:8660:8784:8957:9008:9025:9969:10004:11026:11473:11638:11639:11658:11914:12043:12048:12296:12297:12438:12555:12679:12740:12895:13019:13053:13141:13146:13148:13161:13221:13229:13230:13845:13846:14096:14097:14394:14659:14827:21060:21067:21080:21220:21324:21433:21444:21451:21627:21740:21990:30012:30034:30045:30054:30056:30062:30064:30070:30079:30090,0,RBL:209.85.217.7 4:@flex- X-HE-Tag: ring36_70f9e957db53e X-Filterd-Recvd-Size: 18395 Received: from mail-vs1-f74.google.com (mail-vs1-f74.google.com [209.85.217.74]) by imf37.hostedemail.com (Postfix) with ESMTP for ; Wed, 25 Mar 2020 16:12:56 +0000 (UTC) Received: by mail-vs1-f74.google.com with SMTP id o4so453252vsq.9 for ; Wed, 25 Mar 2020 09:12:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:message-id:mime-version:subject:from:to:cc; bh=dqvbEi1aYaMkcL5knA4Qh3ANPcfd3qqdNqZ/ztYMWlE=; b=Lnlc2Cy32vCnAGUhjatnK33hK8r3wRU/or+7GYfI38yj2ooY80lLjwWsWLMeYO9tMO OTA28sj05UOoOUOLNMV7+i4fOx6aNETQjGZ8RHbn5bgTMcJxXs5tcMnMb+iXi4cAJl2P Jcg9RMZEcFPbNS/Vm9oMf2WuVb4A3ivL9ZL8yzTFyGe817lA7ylremBUi84RCrJL0rgH JQ3pOGVtkKVn5UFSWmtzDdupOR8kgjO9DEAXPR/1bOK1f2VIwcC9+emduHiyXscaLEoJ /9AQQ0EW+cgfgRIXryfTyQA0+8ZXJm88EdWzOmU5E70F6mMDEIlTYWtMvDVikZ5IlC91 PZaQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:message-id:mime-version:subject:from:to:cc; bh=dqvbEi1aYaMkcL5knA4Qh3ANPcfd3qqdNqZ/ztYMWlE=; b=K/Anx77RiwO6Wf+CTOlDRbZv1l4ypEA6FMtyid1f77C1htd1PVE5J4gQSHwbEolJyA DglZTej6zDByJZbpQ2u1rYSO/tBx5UxTNY/VMqAWRc2y7xDbQ4CQElMivQQl3xbgIQ60 MJiE5ve+nYgrHscwpCzkBbX8U3ILsckmZF7Ss9G0g7V6pBANE0RJCyrNYOZAuPMQbBzJ ualxUnFEelu/V3pKVumxmkMBE7EwZpMSIyeuD1hrYIwTTEyb0yn34QxrzUllcxfFvmMy 95Y67/VPRCNuZD3rheCeahFDJQYIOeTbyIDWY2nuigd6JRYZ9nCKYTL2iLFpDyiSotpk nUBg== X-Gm-Message-State: ANhLgQ3k8bH6afNMpgBGE6U1xbK2lbne75xCaSAxczHIyzuhJ7iaf3ea cZAUE/99F3zHk59Y3o9+lxud/Btc4HA= X-Google-Smtp-Source: ADFU+vshJUTsj6uZ3N98jJ/3pjnrymE2rQF5U22TKF0q3nkEXGRVAQR9HbC6TKYgUuqFVM62GF7DrmrTUZ8= X-Received: by 2002:a1f:2ac4:: with SMTP id q187mr2931452vkq.6.1585152775140; Wed, 25 Mar 2020 09:12:55 -0700 (PDT) Date: Wed, 25 Mar 2020 17:12:11 +0100 Message-Id: <20200325161249.55095-1-glider@google.com> Mime-Version: 1.0 X-Mailer: git-send-email 2.25.1.696.g5e7596f4ac-goog Subject: [PATCH v5 00/38] Add KernelMemorySanitizer infrastructure From: glider@google.com To: Alexander Viro , Andreas Dilger , Andrew Morton , Andrey Konovalov , Andrey Ryabinin , Andy Lutomirski , Ard Biesheuvel , Arnd Bergmann , Christoph Hellwig , Christoph Hellwig , "Darrick J. Wong" , "David S. Miller" , Dmitry Torokhov , Dmitry Vyukov , Eric Biggers , Eric Dumazet , Eric Van Hensbergen , Greg Kroah-Hartman , Harry Wentland , Herbert Xu , Ilya Leoshkevich , Ingo Molnar , Jason Wang , Jens Axboe , Marek Szyprowski , Marco Elver , Mark Rutland , "Martin K. Petersen" , Martin Schwidefsky , Matthew Wilcox , "Michael S. Tsirkin" , Michal Simek , Petr Mladek , Qian Cai , Randy Dunlap , Robin Murphy , Sergey Senozhatsky , Steven Rostedt , Takashi Iwai , "Theodore Ts'o" , Thomas Gleixner , Vasily Gorbik , Vegard Nossum , Wolfram Sang , linux-mm@kvack.org Cc: glider@google.com, mhocko@suse.com 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: KernelMemorySanitizer (KMSAN) is a detector of errors related to uses of uninitialized memory. It relies on compile-time Clang instrumentation (similar to MSan in the userspace: https://clang.llvm.org/docs/MemorySanitizer.html) and tracks the state of every bit of kernel memory, being able to report an error if uninitialized value is used in a condition, dereferenced or copied to userspace, USB or network. KMSAN has reported more than 200 bugs in the past two years, most of them with the help of syzkaller (http://syzkaller.appspot.com). The proposed patchset contains KMSAN runtime implementation together with small changes to other subsystems needed to make KMSAN work. The latter changes fall into several categories: - nice-to-have features that are independent from KMSAN but simplify its implementation (stackdepot changes, CONFIG_GENERIC_CSUM etc.); - Kconfig changes that prohibit options incompatible with KMSAN; - calls to KMSAN runtime functions that help KMSAN do the bookkeeping (e.g. tell it to allocate, copy or delete the metadata); - calls to KMSAN runtime functions that tell KMSAN to check memory escaping the kernel for uninitialized values. These are required to increase the number of true positive error reports; - calls to runtime functions that tell KMSAN to ignore certain memory ranges to avoid false negative reports. Most certainly there can be better ways to deal with every such report. This patchset allows one to boot and run a defconfig+KMSAN kernel on a QEMU without known major false positives. It however doesn't guarantee there are no false positives in drivers of certain devices or less tested subsystems, although KMSAN is actively tested on syzbot with quite a rich config. One may find it handy to review these patches in Gerrit: https://linux-review.googlesource.com/c/linux/kernel/git/torvalds/linux/+/1081 I've ensured the Change-Id: tags stay away from commit descriptions. The patchset was generated relative to mmotm (v5.6-rc7-mmots-2020-03-23-22-35). Several points worth a separate discussion: 1. Right now KMSAN assumes that contiguous physical pages cannot be accessed as such, unless they were allocated together by a single alloc_pages() call. Some kernel code however does so, which may break under KMSAN. Two possible solutions to this problem are: A. Allocate shadow and origin pages at fixed offset from the kernel page. This is what we already do for vmalloc, but not for page_alloc(), as it turned out to be quite hard. Ideas on how to implement this approach are still welcome, because it'll simplify the rest of the KMSAN runtime a lot. B. Make all accesses touching non-contiguous pages access dummy shadow pages instead, so that such accesses don't produce any uninitialized values. This is quite controversial, as it may prevent true positives from being reported. 2. checkpatch.pl complains a lot about the use of BUG_ON in KMSAN source. I don't have a strong opinion on this, but KMSAN is a debugging tool, so any runtime invariant violation in it renders the tool useless. Therefore it doesn't make much sense to not terminate after a bug in KMSAN. There has been a suggestion to disable KMSAN gracefully instead of panicking. The downside of doing so is that users may gain a false sense of memory safety if they don't notice that the tool has shut down. 3. objtool complains a lot about calls to KMSAN runtime with UACCESS enabled. None of these functions is expected to touch userspace memory, but they can be called in the uaccess context, as the compiler adds them to every memory access. Turns out it's not enough to just whitelist KMSAN interface functions in tools/objtool/check.c, as they are viral: after whitelisting them I get warnings about their callees. On the other hand, it's unacceptable to call user_access_save()/user_access_restore() inside these functions, as this slows down the whole runtime heavily. Perhaps this problem can be solved on objtool side, as the mentioned reports aren't errors per se. Alexander Potapenko (38): stackdepot: reserve 5 extra bits in depot_stack_handle_t kmsan: add ReST documentation kmsan: gfp: introduce __GFP_NO_KMSAN_SHADOW kmsan: introduce __no_sanitize_memory and __SANITIZE_MEMORY__ kmsan: reduce vmalloc space kmsan: add KMSAN runtime core kmsan: KMSAN compiler API implementation kmsan: add KMSAN hooks for kernel subsystems kmsan: stackdepot: don't allocate KMSAN metadata for stackdepot kmsan: define READ_ONCE_NOCHECK() kmsan: make READ_ONCE_TASK_STACK() return initialized values kmsan: x86: sync metadata pages on page fault kmsan: add tests for KMSAN crypto: kmsan: disable accelerated configs under KMSAN kmsan: x86: disable UNWINDER_ORC under KMSAN kmsan: x86/asm: softirq: add KMSAN IRQ entry hooks kmsan: disable KMSAN instrumentation for certain kernel parts kmsan: mm: call KMSAN hooks from SLUB code kmsan: mm: maintain KMSAN metadata for page operations kmsan: handle memory sent to/from USB kmsan: handle task creation and exiting kmsan: net: check the value of skb before sending it to the network kmsan: printk: treat the result of vscnprintf() as initialized kmsan: disable instrumentation of certain functions kmsan: unpoison |tlb| in arch_tlb_gather_mmu() kmsan: use __msan_ string functions where possible. kmsan: hooks for copy_to_user() and friends kmsan: init: call KMSAN initialization routines kmsan: enable KMSAN builds kmsan: handle /dev/[u]random kmsan: virtio: check/unpoison scatterlist in vring_map_one_sg() kmsan: disable strscpy() optimization under KMSAN kmsan: add iomap support kmsan: dma: unpoison memory mapped by dma_direct_map_page() kmsan: disable physical page merging in biovec x86: kasan: kmsan: support CONFIG_GENERIC_CSUM on x86, enable it for KASAN/KMSAN kmsan: x86/uprobes: unpoison regs in arch_uprobe_exception_notify() kmsan: block: skip bio block merging logic for KMSAN To: Alexander Potapenko Cc: Alexander Viro Cc: Andreas Dilger Cc: Andrew Morton Cc: Andrey Konovalov Cc: Andrey Ryabinin Cc: Andy Lutomirski Cc: Ard Biesheuvel Cc: Arnd Bergmann Cc: Christoph Hellwig Cc: Christoph Hellwig Cc: Darrick J. Wong Cc: "David S. Miller" Cc: Dmitry Torokhov Cc: Dmitry Vyukov Cc: Eric Biggers Cc: Eric Dumazet Cc: Eric Van Hensbergen Cc: Greg Kroah-Hartman Cc: Harry Wentland Cc: Herbert Xu Cc: Ilya Leoshkevich Cc: Ingo Molnar Cc: Jason Wang Cc: Jens Axboe Cc: Marek Szyprowski Cc: Marco Elver Cc: Mark Rutland Cc: Martin K. Petersen Cc: Martin Schwidefsky Cc: Matthew Wilcox Cc: "Michael S. Tsirkin" Cc: Michal Simek Cc: Petr Mladek Cc: Qian Cai Cc: Randy Dunlap Cc: Robin Murphy Cc: Sergey Senozhatsky Cc: Steven Rostedt Cc: Takashi Iwai Cc: "Theodore Ts'o" Cc: Thomas Gleixner Cc: Vasily Gorbik Cc: Vegard Nossum Cc: Wolfram Sang Cc: linux-mm@kvack.org Documentation/dev-tools/index.rst | 1 + Documentation/dev-tools/kmsan.rst | 424 ++++++++++++++ Makefile | 3 +- arch/x86/Kconfig | 5 + arch/x86/Kconfig.debug | 3 + arch/x86/boot/Makefile | 1 + arch/x86/boot/compressed/Makefile | 2 + arch/x86/boot/compressed/misc.h | 1 + arch/x86/entry/common.c | 2 + arch/x86/entry/entry_64.S | 16 + arch/x86/entry/vdso/Makefile | 3 + arch/x86/include/asm/checksum.h | 10 +- arch/x86/include/asm/irq_regs.h | 2 + arch/x86/include/asm/kmsan.h | 93 +++ arch/x86/include/asm/page_64.h | 13 + arch/x86/include/asm/pgtable_64_types.h | 15 + arch/x86/include/asm/string_64.h | 23 +- arch/x86/include/asm/syscall_wrapper.h | 2 + arch/x86/include/asm/uaccess.h | 10 + arch/x86/include/asm/unwind.h | 10 +- arch/x86/kernel/Makefile | 4 + arch/x86/kernel/apic/apic.c | 3 + arch/x86/kernel/cpu/Makefile | 1 + arch/x86/kernel/dumpstack_64.c | 5 + arch/x86/kernel/process_64.c | 5 + arch/x86/kernel/traps.c | 13 +- arch/x86/kernel/uprobes.c | 7 +- arch/x86/lib/Makefile | 2 + arch/x86/mm/Makefile | 3 + arch/x86/mm/fault.c | 20 + arch/x86/mm/ioremap.c | 3 + arch/x86/realmode/rm/Makefile | 1 + block/bio.c | 2 + block/blk.h | 7 + crypto/Kconfig | 30 + drivers/char/random.c | 6 + drivers/firmware/efi/libstub/Makefile | 1 + .../firmware/efi/libstub/efi-stub-helper.c | 5 + drivers/firmware/efi/libstub/tpm.c | 5 + drivers/usb/core/urb.c | 2 + drivers/virtio/virtio_ring.c | 10 +- include/asm-generic/cacheflush.h | 7 +- include/asm-generic/uaccess.h | 12 +- include/linux/compiler-clang.h | 7 + include/linux/compiler-gcc.h | 5 + include/linux/compiler.h | 14 +- include/linux/gfp.h | 4 +- include/linux/highmem.h | 3 + include/linux/kmsan-checks.h | 127 ++++ include/linux/kmsan.h | 335 +++++++++++ include/linux/mm_types.h | 9 + include/linux/sched.h | 5 + include/linux/stackdepot.h | 8 + include/linux/string.h | 2 + include/linux/uaccess.h | 34 +- init/main.c | 3 + kernel/Makefile | 1 + kernel/dma/direct.c | 1 + kernel/exit.c | 2 + kernel/fork.c | 2 + kernel/kthread.c | 2 + kernel/locking/Makefile | 4 + kernel/printk/printk.c | 6 + kernel/sched/core.c | 22 + kernel/softirq.c | 5 + lib/Kconfig.debug | 2 + lib/Kconfig.kmsan | 22 + lib/Makefile | 3 + lib/iomap.c | 40 ++ lib/ioremap.c | 5 + lib/iov_iter.c | 14 +- lib/stackdepot.c | 26 +- lib/string.c | 8 + lib/test_kmsan.c | 229 ++++++++ lib/usercopy.c | 8 +- mm/Makefile | 1 + mm/gup.c | 3 + mm/kmsan/Makefile | 11 + mm/kmsan/kmsan.c | 547 ++++++++++++++++++ mm/kmsan/kmsan.h | 161 ++++++ mm/kmsan/kmsan_entry.c | 38 ++ mm/kmsan/kmsan_hooks.c | 416 +++++++++++++ mm/kmsan/kmsan_init.c | 79 +++ mm/kmsan/kmsan_instr.c | 229 ++++++++ mm/kmsan/kmsan_report.c | 143 +++++ mm/kmsan/kmsan_shadow.c | 456 +++++++++++++++ mm/kmsan/kmsan_shadow.h | 30 + mm/memory.c | 2 + mm/mmu_gather.c | 10 + mm/page_alloc.c | 17 + mm/slub.c | 29 +- mm/vmalloc.c | 24 +- net/sched/sch_generic.c | 2 + scripts/Makefile.kmsan | 12 + scripts/Makefile.lib | 6 + 95 files changed, 3926 insertions(+), 41 deletions(-) create mode 100644 Documentation/dev-tools/kmsan.rst create mode 100644 arch/x86/include/asm/kmsan.h create mode 100644 include/linux/kmsan-checks.h create mode 100644 include/linux/kmsan.h create mode 100644 lib/Kconfig.kmsan create mode 100644 lib/test_kmsan.c create mode 100644 mm/kmsan/Makefile create mode 100644 mm/kmsan/kmsan.c create mode 100644 mm/kmsan/kmsan.h create mode 100644 mm/kmsan/kmsan_entry.c create mode 100644 mm/kmsan/kmsan_hooks.c create mode 100644 mm/kmsan/kmsan_init.c create mode 100644 mm/kmsan/kmsan_instr.c create mode 100644 mm/kmsan/kmsan_report.c create mode 100644 mm/kmsan/kmsan_shadow.c create mode 100644 mm/kmsan/kmsan_shadow.h create mode 100644 scripts/Makefile.kmsan