From patchwork Thu Feb 15 17:04:32 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Rutland X-Patchwork-Id: 128483 Delivered-To: patch@linaro.org Received: by 10.46.124.24 with SMTP id x24csp1967708ljc; Thu, 15 Feb 2018 09:04:44 -0800 (PST) X-Google-Smtp-Source: AH8x227rojqgtg/ttOj1KnB02cKPo2wKp2xPn/vj4C1ZOeqQRXioUK7lLV1TVLokvdcmTLBmy4lW X-Received: by 10.98.227.8 with SMTP id g8mr3261862pfh.200.1518714284054; Thu, 15 Feb 2018 09:04:44 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1518714284; cv=none; d=google.com; s=arc-20160816; b=vPFf84bs2VqrADI5pOV0ojWUIrG2hDukdGWQkg5wpHEK11ncTZsGsyvFp8UZaAsMO+ NZCeqI7xBOAG7zzRUaIWRriEtTCSLYY8izhKt0K1Vi7cRNzGEugwQ58QWLIrpES5GbVR xs3YB0EJFoBdm29ankxSzg5kcOqxASlF+mvfw8im/N5vjzdQdg9oJz3UUz0EzFANyF5w EG83WfBG36eQVkzg1QPK97DQtIgyJPIO3E/FEgXL2Z4d2VzpK+3xhFZUtAfFMhKnn0vo JgUfPYYEE/Xqev5UAPbsxSJAf85XJEb/+bmRrXkGglAbupe2bAnA8h0xcxG1knGrySQj wkkQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:content-disposition :mime-version:message-id:subject:cc:to:from:date :arc-authentication-results; bh=KDuZhWdiiPipJG0BBIW+HqNPGuC1Lr0kWrk/guRxlgc=; b=upxAiH7wmX+UX1G1ZYNgS0xgYemZ5mTa7iOkohvB93OyaQH4dcNIPBZLDMUM3/OQW4 HR+qgFj1J9uumBNfxmMAKS3KYRm6/ohTgQ2HhXiT6rxiiqrnhSTNe/awcNJuzoiCXveG ge/yTAyvypOk7Ggvq4BUcUEn+ehoCa2XEgkSDpEZqcjZvP9qDmQEaz32Tofo0OqDAnnr RrOA/LLbUHHsZfZIbgMtbtE+Hx7S/neDOCsSYg7dyCrioF/cGAvEMciwBC6VPGTMVXIE oQTiGazIY89ic9l0/zahVDHeJbGzt/PCqeD6VgJMH9v6IY92pnobbqdGTF1oY8FEuCnN UqVg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id p1si4440991pfj.124.2018.02.15.09.04.43; Thu, 15 Feb 2018 09:04:44 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1945960AbeBOREj (ORCPT + 28 others); Thu, 15 Feb 2018 12:04:39 -0500 Received: from usa-sjc-mx-foss1.foss.arm.com ([217.140.101.70]:57940 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1423337AbeBOREg (ORCPT ); Thu, 15 Feb 2018 12:04:36 -0500 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 37BC81435; Thu, 15 Feb 2018 09:04:36 -0800 (PST) Received: from lakrids.cambridge.arm.com (usa-sjc-imap-foss1.foss.arm.com [10.72.51.249]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 286AE3F24D; Thu, 15 Feb 2018 09:04:35 -0800 (PST) Date: Thu, 15 Feb 2018 17:04:32 +0000 From: Mark Rutland To: netdev@vger.kernel.org, linux-kernel@vger.kernel.org Cc: davem@davemloft.net, willemb@google.com, edumazet@google.com Subject: v4.16-rc1 misaligned atomics in skb__clone / __napi_alloc_skb Message-ID: <20180215170432.e4wue4osyv3vmdla@lakrids.cambridge.arm.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: NeoMutt/20170113 (1.7.2) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi, While fuzzing arm64 v4.16-rc1 with Syzkaller, I've been hitting a misaligned atomic in __skb_clone: atomic_inc(&(skb_shinfo(skb)->dataref)); .. where dataref doesn't have the required natural alignment, and the atomic operation faults. e.g. i often see it aligned to a single byte boundary rather than a four byte boundary. AFAICT, the skb_shared_info is misaligned at the instant it's allocated in __napi_alloc_skb(). With the patch at the end of this mail, the atomic_set() (which is a WRITE_ONCE()) in __build_skb() blows up, e.g. WARNING: CPU: 0 PID: 8457 at mm/access_once.c:12 access_once_alignment_check+0x34/0x40 mm/access_once.c:12 Kernel panic - not syncing: panic_on_warn set ... CPU: 0 PID: 8457 Comm: syz-executor1 Not tainted 4.16.0-rc1-00002-gb03ae7b8b0de #9 Hardware name: linux,dummy-virt (DT) Call trace: dump_backtrace+0x0/0x390 arch/arm64/kernel/time.c:52 show_stack+0x20/0x30 arch/arm64/kernel/traps.c:151 __dump_stack lib/dump_stack.c:17 [inline] dump_stack+0xd0/0x130 lib/dump_stack.c:53 panic+0x220/0x3fc kernel/panic.c:183 __warn+0x270/0x2bc kernel/panic.c:547 report_bug+0x1dc/0x2d0 lib/bug.c:184 bug_handler+0x7c/0x128 arch/arm64/kernel/traps.c:758 call_break_hook arch/arm64/kernel/debug-monitors.c:305 [inline] brk_handler+0x1a0/0x300 arch/arm64/kernel/debug-monitors.c:320 do_debug_exception+0x15c/0x408 arch/arm64/mm/fault.c:808 el1_dbg+0x18/0x78 access_once_alignment_check+0x34/0x40 mm/access_once.c:12 __napi_alloc_skb+0x18c/0x2b8 net/core/skbuff.c:482 napi_alloc_skb include/linux/skbuff.h:2643 [inline] napi_get_frags+0x68/0x120 net/core/dev.c:5108 tun_napi_alloc_frags drivers/net/tun.c:1477 [inline] tun_get_user+0x13b0/0x3fe8 drivers/net/tun.c:1820 tun_chr_write_iter+0xa8/0x158 drivers/net/tun.c:1988 call_write_iter include/linux/fs.h:1781 [inline] do_iter_readv_writev+0x2f8/0x490 fs/read_write.c:653 do_iter_write+0x14c/0x4b0 fs/read_write.c:932 vfs_writev+0x130/0x288 fs/read_write.c:977 do_writev+0xe0/0x248 fs/read_write.c:1012 SYSC_writev fs/read_write.c:1085 [inline] SyS_writev+0x34/0x48 fs/read_write.c:1082 el0_svc_naked+0x30/0x34 SMP: stopping secondary CPUs Kernel Offset: disabled CPU features: 0x1002082 Memory Limit: none Rebooting in 86400 seconds.. ... I see these splats with both tun and virtio-net. I have some Syzkaller logs, and can reproduce the problem locally, but unfortunately the C reproducer it generated doesn't seem to work on its own. Any ideas as to how this could happen? Thanks, Mark. ---->8---- Tested-by: Mark Rutland diff --git a/include/linux/compiler.h b/include/linux/compiler.h index c2cc57a2f508..c06b810a3b3b 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -163,6 +163,8 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val, #include +void access_once_alignment_check(const volatile void *ptr, int size); + #define __READ_ONCE_SIZE \ ({ \ switch (size) { \ @@ -180,6 +182,7 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val, static __always_inline void __read_once_size(const volatile void *p, void *res, int size) { + access_once_alignment_check(p, size); __READ_ONCE_SIZE; } @@ -203,6 +206,8 @@ void __read_once_size_nocheck(const volatile void *p, void *res, int size) static __always_inline void __write_once_size(volatile void *p, void *res, int size) { + access_once_alignment_check(p, size); + switch (size) { case 1: *(volatile __u8 *)p = *(__u8 *)res; break; case 2: *(volatile __u16 *)p = *(__u16 *)res; break; diff --git a/mm/Makefile b/mm/Makefile index e669f02c5a54..604d269d7d57 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -3,6 +3,7 @@ # Makefile for the linux memory manager. # +KASAN_SANITIZE_access_once.o := n KASAN_SANITIZE_slab_common.o := n KASAN_SANITIZE_slab.o := n KASAN_SANITIZE_slub.o := n @@ -10,6 +11,7 @@ KASAN_SANITIZE_slub.o := n # These files are disabled because they produce non-interesting and/or # flaky coverage that is not a function of syscall inputs. E.g. slab is out of # free pages, or a task is migrated between nodes. +KCOV_INSTRUMENT_access_once.o := n KCOV_INSTRUMENT_slab_common.o := n KCOV_INSTRUMENT_slob.o := n KCOV_INSTRUMENT_slab.o := n @@ -39,7 +41,7 @@ obj-y := filemap.o mempool.o oom_kill.o \ mm_init.o mmu_context.o percpu.o slab_common.o \ compaction.o vmacache.o swap_slots.o \ interval_tree.o list_lru.o workingset.o \ - debug.o $(mmu-y) + debug.o access_once.o $(mmu-y) obj-y += init-mm.o diff --git a/mm/access_once.c b/mm/access_once.c new file mode 100644 index 000000000000..42ee35d171c4 --- /dev/null +++ b/mm/access_once.c @@ -0,0 +1,15 @@ +#include +#include +#include + +void access_once_alignment_check(const volatile void *ptr, int size) +{ + switch (size) { + case 1: + case 2: + case 4: + case 8: + WARN_ON(!IS_ALIGNED((unsigned long)ptr, size)); + } +} +EXPORT_SYMBOL(access_once_alignment_check);