From patchwork Sun Feb 5 17:25:24 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Dumazet X-Patchwork-Id: 724263 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3vGcwl5kShz9s4s for ; Mon, 6 Feb 2017 04:27:03 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="bV5lEWV6"; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751559AbdBERZ2 (ORCPT ); Sun, 5 Feb 2017 12:25:28 -0500 Received: from mail-io0-f194.google.com ([209.85.223.194]:33375 "EHLO mail-io0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751425AbdBERZ1 (ORCPT ); Sun, 5 Feb 2017 12:25:27 -0500 Received: by mail-io0-f194.google.com with SMTP id 101so7077477iom.0 for ; Sun, 05 Feb 2017 09:25:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=message-id:subject:from:to:cc:date:mime-version :content-transfer-encoding; bh=VpQk4KFBxK7qgtP/1BWQHXSBGvEX/tEEyikK6xVeg64=; b=bV5lEWV60nIY/VFbeiaih5c0Vv4yH7jjNz+y2/2qCFy1IVuYUBV/KATh4TkcFmZkhP HKIjGq3V7YW4op0bJm8n8wZbzCPg8QqqTWGZ2gCaPiy/jJoNwP1gaZZUQ+9AYkJjj7WF 0WqT66lCo5Dlcel4gIDhm6ZhesJMhaa7jiEfnQvEHAElnkS8rq6S/7vsm1xyRS+d3f+R 4u3zpqRb4Dgm4HT8icMrFWQkw/FI8ufIliYL+YtdeA9UWQ9D8n96Y98n/vESPR5iaJZv y39tQ6YqcgiNZjo7ZxY0RqQ00UyYHN5OOHKVefGaDbYwmlWCeRlTOYC200XQjrWkIhhP AL3w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:message-id:subject:from:to:cc:date:mime-version :content-transfer-encoding; bh=VpQk4KFBxK7qgtP/1BWQHXSBGvEX/tEEyikK6xVeg64=; b=dGPONaIpY//E0u1bcWu6+kEWqUtU8X2qJq1Z1ZqKr4stxmHebiYijyz9/ORVSjgzbX M1rGyd/GtnDV64jimCMIYVJhlVTVYMwZsg5pOEuNgPdged3McHM6rN4IFSMvRucEhWpH a47QjTMHLzfIdC47CW91LQJ+sHT1LqTxyP2lWLTSLjw/UmE7dPW+WobbmlTTVWMlanUq zj7VgDescpiIV2TPXRWq3TSqZJ+RGIY76EJhUXXD3m57KNuHQRruWKJLTc98baqnznEr JDCjYNxLZOu/xXIm57K5LrhuhXlFI9PJpD9RJdywF+EoDqG1WS3uRDQtOwHSSs2NHyim iPTw== X-Gm-Message-State: AMke39m7ifNtejsdgWKwPGNCywpmgOuXAvGoOP8unrqXysfDUjfDnWAPndgMMM8Fe433dA== X-Received: by 10.107.157.21 with SMTP id g21mr4098940ioe.219.1486315526474; Sun, 05 Feb 2017 09:25:26 -0800 (PST) Received: from [172.16.50.53] ([172.16.50.53]) by smtp.googlemail.com with ESMTPSA id 98sm6333813iol.5.2017.02.05.09.25.25 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 05 Feb 2017 09:25:25 -0800 (PST) Message-ID: <1486315524.7793.22.camel@edumazet-glaptop3.roam.corp.google.com> Subject: [PATCH net] udp: properly cope with csum errors From: Eric Dumazet To: David Miller Cc: netdev , Paolo Abeni , Hannes Frederic Sowa , Dmitry Vyukov Date: Sun, 05 Feb 2017 09:25:24 -0800 X-Mailer: Evolution 3.10.4-0ubuntu2 Mime-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Eric Dumazet Dmitry reported that UDP sockets being destroyed would trigger the WARN_ON(atomic_read(&sk->sk_rmem_alloc)); in inet_sock_destruct() It turns out we do not properly destroy skb(s) that have wrong UDP checksum. Thanks again to syzkaller team. Fixes : 7c13f97ffde6 ("udp: do fwd memory scheduling on dequeue") Reported-by: Dmitry Vyukov Signed-off-by: Eric Dumazet Cc: Paolo Abeni Cc: Hannes Frederic Sowa Acked-by: Paolo Abeni --- include/net/sock.h | 4 +++- net/core/datagram.c | 8 ++++++-- net/ipv4/udp.c | 2 +- net/ipv6/udp.c | 2 +- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/include/net/sock.h b/include/net/sock.h index f0e867f58722..c4f5e6fca17c 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -2006,7 +2006,9 @@ void sk_reset_timer(struct sock *sk, struct timer_list *timer, void sk_stop_timer(struct sock *sk, struct timer_list *timer); int __sk_queue_drop_skb(struct sock *sk, struct sk_buff *skb, - unsigned int flags); + unsigned int flags, + void (*destructor)(struct sock *sk, + struct sk_buff *skb)); int __sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb); int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb); diff --git a/net/core/datagram.c b/net/core/datagram.c index 662bea587165..ea633342ab0d 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -332,7 +332,9 @@ void __skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb, int len) EXPORT_SYMBOL(__skb_free_datagram_locked); int __sk_queue_drop_skb(struct sock *sk, struct sk_buff *skb, - unsigned int flags) + unsigned int flags, + void (*destructor)(struct sock *sk, + struct sk_buff *skb)) { int err = 0; @@ -342,6 +344,8 @@ int __sk_queue_drop_skb(struct sock *sk, struct sk_buff *skb, if (skb == skb_peek(&sk->sk_receive_queue)) { __skb_unlink(skb, &sk->sk_receive_queue); atomic_dec(&skb->users); + if (destructor) + destructor(sk, skb); err = 0; } spin_unlock_bh(&sk->sk_receive_queue.lock); @@ -375,7 +379,7 @@ EXPORT_SYMBOL(__sk_queue_drop_skb); int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags) { - int err = __sk_queue_drop_skb(sk, skb, flags); + int err = __sk_queue_drop_skb(sk, skb, flags, NULL); kfree_skb(skb); sk_mem_reclaim_partial(sk); diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 1307a7c2e544..8aab7d78d25b 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1501,7 +1501,7 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock, return err; csum_copy_err: - if (!__sk_queue_drop_skb(sk, skb, flags)) { + if (!__sk_queue_drop_skb(sk, skb, flags, udp_skb_destructor)) { UDP_INC_STATS(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite); UDP_INC_STATS(sock_net(sk), UDP_MIB_INERRORS, is_udplite); } diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 4d5c4eee4b3f..8990856f5101 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -441,7 +441,7 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, return err; csum_copy_err: - if (!__sk_queue_drop_skb(sk, skb, flags)) { + if (!__sk_queue_drop_skb(sk, skb, flags, udp_skb_destructor)) { if (is_udp4) { UDP_INC_STATS(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite);