Received: by 2002:a25:1506:0:0:0:0:0 with SMTP id 6csp1624970ybv; Fri, 21 Feb 2020 00:31:09 -0800 (PST) X-Google-Smtp-Source: APXvYqyw3xNZoEefZrV474TCHseqgp6FN4WPbkSgu6fUMXzoFx33cNVpaMx4Ts2/sgx0eZ4xE4lX X-Received: by 2002:aca:3017:: with SMTP id w23mr1009422oiw.152.1582273869294; Fri, 21 Feb 2020 00:31:09 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1582273869; cv=none; d=google.com; s=arc-20160816; b=p5ccpj2V9XnX37156efrdct6VIZ2P+3DUbXXm0xMzC/ogoZJeys8JauaJc/U0epkfP Xy3TqqD/h22PdNru2CPGR4iaF7berHV7LryMXXBK50rSFIXrovcEuyA8F2ThztbDyjoc VwVoVOeE61Y2FK4cXcwYnmuMivuBwk/pz7w+BlDYqsg6PlGwDTtAXFV0HI4jx4SH+sxQ AwKMpI6/V/7wZiRQW6gBOtiQKocfN6Llda/JfnawzuvG4OyTGd04wk7+XOmURQEquiVT GqAogTsdluU99czcFLYKxEFLJaEfB17zfYoC+1vEXVcMNuU3VII07XlJKFkGpkSG9ZHQ /+ig== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=zotQkTJHQFs58SyJHQwEDZIg7XRwFUCipxHlTtfyMYQ=; b=L03EtUf5jxe9mSmy1c8uFN3ssdtdhf9mrYcQr6nXyx2TWy9qiktMy016Ye6HIv+WU6 p90W+Pom3vzOIH+NJL0qFJ/onvoeiDfpsWn2CYsvU1OygMdQUfS6M4iedJwJQKyp9Xqz EDWtFdKKKa2OpTDnBM7/7GEd+cP3eyc9ZHPM5m1kCNnYTHrsTYaLKcbHZY/nEFQtLSqu KFbLbqqjBqxmPO45QM2f3IDOHQWK8LUJRb5IPnNnIoFtd0+/l+7d8CpTvF3nyjZYjRa5 zoGnjdJh/0pVK5h9N2QG2tNSubZ+iaQOvUpFKqdSu4miItTn+s2zrMmOrRsWORpRxbl2 cYzQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=hc93f2su; 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 77si466509oie.10.2020.02.21.00.30.56; Fri, 21 Feb 2020 00:31:09 -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; dkim=pass header.i=@kernel.org header.s=default header.b=hc93f2su; 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 S1731270AbgBUI37 (ORCPT + 99 others); Fri, 21 Feb 2020 03:29:59 -0500 Received: from mail.kernel.org ([198.145.29.99]:53734 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732786AbgBUIQh (ORCPT ); Fri, 21 Feb 2020 03:16:37 -0500 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (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 8F4D424670; Fri, 21 Feb 2020 08:16:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1582272997; bh=xNiQ8u3f0bGj5vPAZU3XA6kdB7LnIAJHOYgY2fB7wbg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=hc93f2su8Oh3La95SjN5G9lZRCW0zNIdbAlrymU82TQScyV5QDxkFgxsMrc5Mq13K mDMVDySoRq9FSGZOh+yrxt51XRzpuGgEILLAVDNQKW6JHTF6ZK56V/+mVuJ5gU55Sg 5XLfV+HtZxODsVZcuQbe0ZhxnY1cH+eIfUYZ20uI= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Stepan Horacek , Paolo Abeni , =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= , "David S. Miller" Subject: [PATCH 4.19 001/191] core: Dont skip generic XDP program execution for cloned SKBs Date: Fri, 21 Feb 2020 08:39:34 +0100 Message-Id: <20200221072250.916265264@linuxfoundation.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200221072250.732482588@linuxfoundation.org> References: <20200221072250.732482588@linuxfoundation.org> User-Agent: quilt/0.66 X-stable: review X-Patchwork-Hint: ignore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: "Toke H?iland-J?rgensen" [ Upstream commit ad1e03b2b3d4430baaa109b77bc308dc73050de3 ] The current generic XDP handler skips execution of XDP programs entirely if an SKB is marked as cloned. This leads to some surprising behaviour, as packets can end up being cloned in various ways, which will make an XDP program not see all the traffic on an interface. This was discovered by a simple test case where an XDP program that always returns XDP_DROP is installed on a veth device. When combining this with the Scapy packet sniffer (which uses an AF_PACKET) socket on the sending side, SKBs reliably end up in the cloned state, causing them to be passed through to the receiving interface instead of being dropped. A minimal reproducer script for this is included below. This patch fixed the issue by simply triggering the existing linearisation code for cloned SKBs instead of skipping the XDP program execution. This behaviour is in line with the behaviour of the native XDP implementation for the veth driver, which will reallocate and copy the SKB data if the SKB is marked as shared. Reproducer Python script (requires BCC and Scapy): from scapy.all import TCP, IP, Ether, sendp, sniff, AsyncSniffer, Raw, UDP from bcc import BPF import time, sys, subprocess, shlex SKB_MODE = (1 << 1) DRV_MODE = (1 << 2) PYTHON=sys.executable def client(): time.sleep(2) # Sniffing on the sender causes skb_cloned() to be set s = AsyncSniffer() s.start() for p in range(10): sendp(Ether(dst="aa:aa:aa:aa:aa:aa", src="cc:cc:cc:cc:cc:cc")/IP()/UDP()/Raw("Test"), verbose=False) time.sleep(0.1) s.stop() return 0 def server(mode): prog = BPF(text="int dummy_drop(struct xdp_md *ctx) {return XDP_DROP;}") func = prog.load_func("dummy_drop", BPF.XDP) prog.attach_xdp("a_to_b", func, mode) time.sleep(1) s = sniff(iface="a_to_b", count=10, timeout=15) if len(s): print(f"Got {len(s)} packets - should have gotten 0") return 1 else: print("Got no packets - as expected") return 0 if len(sys.argv) < 2: print(f"Usage: {sys.argv[0]} ") sys.exit(1) if sys.argv[1] == "client": sys.exit(client()) elif sys.argv[1] == "server": mode = SKB_MODE if sys.argv[2] == 'skb' else DRV_MODE sys.exit(server(mode)) else: try: mode = sys.argv[1] if mode not in ('skb', 'drv'): print(f"Usage: {sys.argv[0]} ") sys.exit(1) print(f"Running in {mode} mode") for cmd in [ 'ip netns add netns_a', 'ip netns add netns_b', 'ip -n netns_a link add a_to_b type veth peer name b_to_a netns netns_b', # Disable ipv6 to make sure there's no address autoconf traffic 'ip netns exec netns_a sysctl -qw net.ipv6.conf.a_to_b.disable_ipv6=1', 'ip netns exec netns_b sysctl -qw net.ipv6.conf.b_to_a.disable_ipv6=1', 'ip -n netns_a link set dev a_to_b address aa:aa:aa:aa:aa:aa', 'ip -n netns_b link set dev b_to_a address cc:cc:cc:cc:cc:cc', 'ip -n netns_a link set dev a_to_b up', 'ip -n netns_b link set dev b_to_a up']: subprocess.check_call(shlex.split(cmd)) server = subprocess.Popen(shlex.split(f"ip netns exec netns_a {PYTHON} {sys.argv[0]} server {mode}")) client = subprocess.Popen(shlex.split(f"ip netns exec netns_b {PYTHON} {sys.argv[0]} client")) client.wait() server.wait() sys.exit(server.returncode) finally: subprocess.run(shlex.split("ip netns delete netns_a")) subprocess.run(shlex.split("ip netns delete netns_b")) Fixes: d445516966dc ("net: xdp: support xdp generic on virtual devices") Reported-by: Stepan Horacek Suggested-by: Paolo Abeni Signed-off-by: Toke Høiland-Jørgensen Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4306,14 +4306,14 @@ static u32 netif_receive_generic_xdp(str /* Reinjected packets coming from act_mirred or similar should * not get XDP generic processing. */ - if (skb_cloned(skb) || skb_is_tc_redirected(skb)) + if (skb_is_tc_redirected(skb)) return XDP_PASS; /* XDP packets must be linear and must have sufficient headroom * of XDP_PACKET_HEADROOM bytes. This is the guarantee that also * native XDP provides, thus we need to do it here as well. */ - if (skb_is_nonlinear(skb) || + if (skb_cloned(skb) || skb_is_nonlinear(skb) || skb_headroom(skb) < XDP_PACKET_HEADROOM) { int hroom = XDP_PACKET_HEADROOM - skb_headroom(skb); int troom = skb->tail + skb->data_len - skb->end;