Received: by 10.192.165.148 with SMTP id m20csp848511imm; Fri, 27 Apr 2018 08:28:05 -0700 (PDT) X-Google-Smtp-Source: AB8JxZqA0c/Yak7nGEmcZ6b9t9MyUHbL7/IHTXTx4r1CgZq81aPSzJULYGBD6EU/JK0RBgjBTbrG X-Received: by 2002:a17:902:2805:: with SMTP id e5-v6mr2716009plb.55.1524842885407; Fri, 27 Apr 2018 08:28:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1524842885; cv=none; d=google.com; s=arc-20160816; b=CmERbZv9FVYI97TgdGX2yfSYxJ5aB/NrJPSC57qPNX5K78ZRo3XYdVgTcGYLe/yt7p GfxinAS6De7cOZPBENQBSQtFQJVj+/v9wGNSFlp51JwagfuJGNCy+uR/jbrtb3cWKbmG OrfVAU3Y5dv7TQgRrlaL24kV1FtNx3sWS3R8J1p9jqazaRJBQ9bdj0WiElmseqMd5TjG NeUO+2ud794Ker6NkqQstBXsaa6htFNUGHTiS2lAGjZ5JOlq9A4zIuaI9CAc7POHrjhW V0OBaHRUMNRm52RqZY7CuAtzuWCFEmYD6SY7BzNgMh0TxRdD21OefumHIHNEjlX99n06 Ms5A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:user-agent:references :in-reply-to:message-id:date:subject:cc:to:from:dmarc-filter :arc-authentication-results; bh=DHxPAAesPIeYbEgSSljplQkSlHDzSQ95rmCnowMtzy8=; b=WFMjp6WmTPPfN3DBHn8MsPlpDq6wfe/1Zz5rZPanwC40ayZYwMSKHFHUOifaYnwkCS CY90wgUC+5z9MkojjF5r44liJFGJtCj7cQjX/VNoR6AiNKwPcEPSXJXxLw4CpLZVPozJ nye/O6KySt76bf5+VWUgrZAxc0/TU8Zgn/17qq9Zh9FmD3/JuEhZPeCjNqgGH/FvyBpM sDfnIn/m8ZKTqW93Cqw5prOMhbl0Pf6Exv/Y5vKYEUI5RWqpiuxSRJZlYRrmDRzY6OxG lWd72FLZhJHdkxWAL2+k8kdWmxS7dCNetpJvVTTDFCKVAFn96BVazPyVMmtlBbA0zK7S oJRg== 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 b19-v6si1465496pls.482.2018.04.27.08.27.51; Fri, 27 Apr 2018 08:28:05 -0700 (PDT) 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 S933297AbeD0P0r (ORCPT + 99 others); Fri, 27 Apr 2018 11:26:47 -0400 Received: from mail.kernel.org ([198.145.29.99]:48726 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933213AbeD0OBu (ORCPT ); Fri, 27 Apr 2018 10:01:50 -0400 Received: from localhost (LFbn-1-12247-202.w90-92.abo.wanadoo.fr [90.92.61.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id B45BA2185A; Fri, 27 Apr 2018 14:01:49 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B45BA2185A Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=linuxfoundation.org Authentication-Results: mail.kernel.org; spf=fail smtp.mailfrom=gregkh@linuxfoundation.org From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, DaeRyong Jeong , Byoungyoung Lee , Willem de Bruijn , "David S. Miller" Subject: [PATCH 4.4 36/50] packet: fix bitfield update race Date: Fri, 27 Apr 2018 15:58:38 +0200 Message-Id: <20180427135657.818374891@linuxfoundation.org> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180427135655.623669681@linuxfoundation.org> References: <20180427135655.623669681@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.4-stable review patch. If anyone has any objections, please let me know. ------------------ From: Willem de Bruijn [ Upstream commit a6361f0ca4b25460f2cdf3235ebe8115f622901e ] Updates to the bitfields in struct packet_sock are not atomic. Serialize these read-modify-write cycles. Move po->running into a separate variable. Its writes are protected by po->bind_lock (except for one startup case at packet_create). Also replace a textual precondition warning with lockdep annotation. All others are set only in packet_setsockopt. Serialize these updates by holding the socket lock. Analogous to other field updates, also hold the lock when testing whether a ring is active (pg_vec). Fixes: 8dc419447415 ("[PACKET]: Add optional checksum computation for recvmsg") Reported-by: DaeRyong Jeong Reported-by: Byoungyoung Lee Signed-off-by: Willem de Bruijn Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/packet/af_packet.c | 60 +++++++++++++++++++++++++++++++++++-------------- net/packet/internal.h | 10 ++++---- 2 files changed, 49 insertions(+), 21 deletions(-) --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -332,11 +332,11 @@ static void packet_pick_tx_queue(struct skb_set_queue_mapping(skb, queue_index); } -/* register_prot_hook must be invoked with the po->bind_lock held, +/* __register_prot_hook must be invoked through register_prot_hook * or from a context in which asynchronous accesses to the packet * socket is not possible (packet_create()). */ -static void register_prot_hook(struct sock *sk) +static void __register_prot_hook(struct sock *sk) { struct packet_sock *po = pkt_sk(sk); @@ -351,8 +351,13 @@ static void register_prot_hook(struct so } } -/* {,__}unregister_prot_hook() must be invoked with the po->bind_lock - * held. If the sync parameter is true, we will temporarily drop +static void register_prot_hook(struct sock *sk) +{ + lockdep_assert_held_once(&pkt_sk(sk)->bind_lock); + __register_prot_hook(sk); +} + +/* If the sync parameter is true, we will temporarily drop * the po->bind_lock and do a synchronize_net to make sure no * asynchronous packet processing paths still refer to the elements * of po->prot_hook. If the sync parameter is false, it is the @@ -362,6 +367,8 @@ static void __unregister_prot_hook(struc { struct packet_sock *po = pkt_sk(sk); + lockdep_assert_held_once(&po->bind_lock); + po->running = 0; if (po->fanout) @@ -3134,7 +3141,7 @@ static int packet_create(struct net *net if (proto) { po->prot_hook.type = proto; - register_prot_hook(sk); + __register_prot_hook(sk); } mutex_lock(&net->packet.sklist_lock); @@ -3653,12 +3660,18 @@ packet_setsockopt(struct socket *sock, i if (optlen != sizeof(val)) return -EINVAL; - if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) - return -EBUSY; if (copy_from_user(&val, optval, sizeof(val))) return -EFAULT; - po->tp_loss = !!val; - return 0; + + lock_sock(sk); + if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) { + ret = -EBUSY; + } else { + po->tp_loss = !!val; + ret = 0; + } + release_sock(sk); + return ret; } case PACKET_AUXDATA: { @@ -3669,7 +3682,9 @@ packet_setsockopt(struct socket *sock, i if (copy_from_user(&val, optval, sizeof(val))) return -EFAULT; + lock_sock(sk); po->auxdata = !!val; + release_sock(sk); return 0; } case PACKET_ORIGDEV: @@ -3681,7 +3696,9 @@ packet_setsockopt(struct socket *sock, i if (copy_from_user(&val, optval, sizeof(val))) return -EFAULT; + lock_sock(sk); po->origdev = !!val; + release_sock(sk); return 0; } case PACKET_VNET_HDR: @@ -3690,15 +3707,20 @@ packet_setsockopt(struct socket *sock, i if (sock->type != SOCK_RAW) return -EINVAL; - if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) - return -EBUSY; if (optlen < sizeof(val)) return -EINVAL; if (copy_from_user(&val, optval, sizeof(val))) return -EFAULT; - po->has_vnet_hdr = !!val; - return 0; + lock_sock(sk); + if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) { + ret = -EBUSY; + } else { + po->has_vnet_hdr = !!val; + ret = 0; + } + release_sock(sk); + return ret; } case PACKET_TIMESTAMP: { @@ -3736,11 +3758,17 @@ packet_setsockopt(struct socket *sock, i if (optlen != sizeof(val)) return -EINVAL; - if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) - return -EBUSY; if (copy_from_user(&val, optval, sizeof(val))) return -EFAULT; - po->tp_tx_has_off = !!val; + + lock_sock(sk); + if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) { + ret = -EBUSY; + } else { + po->tp_tx_has_off = !!val; + ret = 0; + } + release_sock(sk); return 0; } case PACKET_QDISC_BYPASS: --- a/net/packet/internal.h +++ b/net/packet/internal.h @@ -109,10 +109,12 @@ struct packet_sock { int copy_thresh; spinlock_t bind_lock; struct mutex pg_vec_lock; - unsigned int running:1, /* prot_hook is attached*/ - auxdata:1, + unsigned int running; /* bind_lock must be held */ + unsigned int auxdata:1, /* writer must hold sock lock */ origdev:1, - has_vnet_hdr:1; + has_vnet_hdr:1, + tp_loss:1, + tp_tx_has_off:1; int pressure; int ifindex; /* bound device */ __be16 num; @@ -122,8 +124,6 @@ struct packet_sock { enum tpacket_versions tp_version; unsigned int tp_hdrlen; unsigned int tp_reserve; - unsigned int tp_loss:1; - unsigned int tp_tx_has_off:1; unsigned int tp_tstamp; struct net_device __rcu *cached_dev; int (*xmit)(struct sk_buff *skb);