From patchwork Thu Sep 28 09:32:37 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Potapenko X-Patchwork-Id: 819463 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.b="YHPhFnY+"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3y2qHH0hphz9t3C for ; Thu, 28 Sep 2017 19:32:59 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751920AbdI1Jco (ORCPT ); Thu, 28 Sep 2017 05:32:44 -0400 Received: from mail-wm0-f50.google.com ([74.125.82.50]:52123 "EHLO mail-wm0-f50.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751082AbdI1Jcn (ORCPT ); Thu, 28 Sep 2017 05:32:43 -0400 Received: by mail-wm0-f50.google.com with SMTP id i131so971348wma.0 for ; Thu, 28 Sep 2017 02:32:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=j1bpSvRScFd5LRPr29XWqegGa4oFpnjFaJbDOHlW4Io=; b=YHPhFnY+/brnT415BdVtI5v5H+Cpn31PHFvzxwjz/WCGRx+WYVofFdeqRKy/EG/0hE Towh7q5/hzZPxMOlFlTyceA/eZvHSrnrozsi1APFh3ykrrBmh9YEu2pHIiRLBsndlXWG 9fQAcoGUS8ow3SdQIABrccc1WvSOsipjjugMF7bNc7OmTef6uw7x/ScdYKn9XuxO5ygp 9kFZNifHzcD5nhSI8EOsI/AR8c/PV5y/TL8rRNCake5wVmp9tjMiLIKOQlCn3RwoaU1V RahxP98HGv5Rl7ugZgBL4qh5+8LvHTs3fNEIavHmSG/i1XyajDZAPm9iPoOI3szkesOJ /SQg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=j1bpSvRScFd5LRPr29XWqegGa4oFpnjFaJbDOHlW4Io=; b=SV9j63Ofxy005oU2POvV0Zjbl6rPA5C0dG88VPIgjsUksS1mZ+9P073Whf0hffQSHD gSyawRYhhf11DnPiP0LP39ui/REzgvfGiIHy5uPWHyJiA5Wp91ljXM+UxEKWztkF4tE2 AyoaI6kvZuQ/OUUioNVPNuu8O+YSQ9KtWDjNHyKREmFBaHqN1jZRP1qz2tajeDom1kGU pmM4fDkPmn+ib4Qrm8N9dQOts059ptZ7pfYXe0bxuB+ByjnzWuDS3AyzqEQf5rd+rHhZ tG3j6p91nMM0VMaAqg0UT2Ey06kKXXfoUWPD/1psIhMt4NjK1tqTkrI48ogRt4D51W7C arLw== X-Gm-Message-State: AMCzsaWZkgvnYjl0Hw7bs7gap5B/cO/aiFv6BLRYX8V/89mQ4Fi/eXyv 54hcTgd1y0jVWgL9hXOhg8Sa4Q== X-Google-Smtp-Source: AOwi7QCuxjRzqMdjEOLiZUiMKsBYJF3FUpuEfNFpCh/sADLnvvkj8iL7ZN6ADxmbLrDtcYREOGKCmg== X-Received: by 10.28.125.205 with SMTP id y196mr521493wmc.128.1506591161735; Thu, 28 Sep 2017 02:32:41 -0700 (PDT) Received: from glider0.muc.corp.google.com ([100.105.28.21]) by smtp.gmail.com with ESMTPSA id j73sm840342wmf.15.2017.09.28.02.32.40 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 28 Sep 2017 02:32:40 -0700 (PDT) From: Alexander Potapenko To: davem@davemloft.net, edumazet@google.com Cc: dvyukov@google.com, syzkaller@googlegroups.com, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3] tun: bail out from tun_get_user() if the skb is empty Date: Thu, 28 Sep 2017 11:32:37 +0200 Message-Id: <20170928093237.121450-1-glider@google.com> X-Mailer: git-send-email 2.14.2.822.g60be5d43e6-goog Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org KMSAN (https://github.com/google/kmsan) reported accessing uninitialized skb->data[0] in the case the skb is empty (i.e. skb->len is 0): ================================================ BUG: KMSAN: use of uninitialized memory in tun_get_user+0x19ba/0x3770 CPU: 0 PID: 3051 Comm: probe Not tainted 4.13.0+ #3140 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 Call Trace: ... __msan_warning_32+0x66/0xb0 mm/kmsan/kmsan_instr.c:477 tun_get_user+0x19ba/0x3770 drivers/net/tun.c:1301 tun_chr_write_iter+0x19f/0x300 drivers/net/tun.c:1365 call_write_iter ./include/linux/fs.h:1743 new_sync_write fs/read_write.c:457 __vfs_write+0x6c3/0x7f0 fs/read_write.c:470 vfs_write+0x3e4/0x770 fs/read_write.c:518 SYSC_write+0x12f/0x2b0 fs/read_write.c:565 SyS_write+0x55/0x80 fs/read_write.c:557 do_syscall_64+0x242/0x330 arch/x86/entry/common.c:284 entry_SYSCALL64_slow_path+0x25/0x25 arch/x86/entry/entry_64.S:245 ... origin: ... kmsan_poison_shadow+0x6e/0xc0 mm/kmsan/kmsan.c:211 slab_alloc_node mm/slub.c:2732 __kmalloc_node_track_caller+0x351/0x370 mm/slub.c:4351 __kmalloc_reserve net/core/skbuff.c:138 __alloc_skb+0x26a/0x810 net/core/skbuff.c:231 alloc_skb ./include/linux/skbuff.h:903 alloc_skb_with_frags+0x1d7/0xc80 net/core/skbuff.c:4756 sock_alloc_send_pskb+0xabf/0xfe0 net/core/sock.c:2037 tun_alloc_skb drivers/net/tun.c:1144 tun_get_user+0x9a8/0x3770 drivers/net/tun.c:1274 tun_chr_write_iter+0x19f/0x300 drivers/net/tun.c:1365 call_write_iter ./include/linux/fs.h:1743 new_sync_write fs/read_write.c:457 __vfs_write+0x6c3/0x7f0 fs/read_write.c:470 vfs_write+0x3e4/0x770 fs/read_write.c:518 SYSC_write+0x12f/0x2b0 fs/read_write.c:565 SyS_write+0x55/0x80 fs/read_write.c:557 do_syscall_64+0x242/0x330 arch/x86/entry/common.c:284 return_from_SYSCALL_64+0x0/0x6a arch/x86/entry/entry_64.S:245 ================================================ Make sure tun_get_user() doesn't touch skb->data[0] unless there is actual data. C reproducer below: ========================== // autogenerated by syzkaller (http://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include int main() { int sock = socket(PF_INET, SOCK_STREAM, IPPROTO_IP); int tun_fd = open("/dev/net/tun", O_RDWR); struct ifreq req; memset(&req, 0, sizeof(struct ifreq)); strcpy((char*)&req.ifr_name, "gre0"); req.ifr_flags = IFF_UP | IFF_MULTICAST; ioctl(tun_fd, TUNSETIFF, &req); ioctl(sock, SIOCSIFFLAGS, "gre0"); write(tun_fd, "hi", 0); return 0; } ========================== Signed-off-by: Alexander Potapenko --- v3: per request by Eric Dumazet introduce ip_version to avoid copy/paste v2: free the skb --- drivers/net/tun.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 3c9985f29950..5ce580f413b9 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1496,11 +1496,13 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, switch (tun->flags & TUN_TYPE_MASK) { case IFF_TUN: if (tun->flags & IFF_NO_PI) { - switch (skb->data[0] & 0xf0) { - case 0x40: + u8 ip_version = skb->len ? (skb->data[0] >> 4) : 0; + + switch (ip_version) { + case 4: pi.proto = htons(ETH_P_IP); break; - case 0x60: + case 6: pi.proto = htons(ETH_P_IPV6); break; default: