Received: by 2002:a25:4158:0:0:0:0:0 with SMTP id o85csp385218yba; Thu, 18 Apr 2019 03:01:47 -0700 (PDT) X-Google-Smtp-Source: APXvYqwQ1ZNWrctjT7jSiRf9AfX04kA7x97MtYdiFDtAT13eCtGwtISyl/rjaRk8wTfWPKZPTd4l X-Received: by 2002:a62:4d43:: with SMTP id a64mr28856999pfb.174.1555581707761; Thu, 18 Apr 2019 03:01:47 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1555581707; cv=none; d=google.com; s=arc-20160816; b=h+EwPqxerpj4tKEhWEANFC0nR/Sc9lr1wCfPQN7k9RFVS6zjMQW43B+2ccRiIpnJZS zqdcWe9lYBD9oSQiNbvYIB928Oi5wYi9pJG7z+9jFcAgrzCrqrNuRs9cJ7/NxipuAI7R BZXJ9Pdt5GF7JX+y3mr64vDRD5Y9ar6dBU4yiiPbnTPaFDB57htTEBMqw2LNozizhi4K uYq7E4Acaxbg2+Q38vpdbO24hW67XGvI0e1oXRdQ8RFqNzZJ2CueA+dPVhakXUnVdZcK kI4DbSOtGLmjU7v61FZKT+J/V5wn2CLUxEWlHf30X2vj3veM9sMJ9h3Eh0DdfOc6N8vS neGg== 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:cc:to:subject :message-id:date:from:in-reply-to:references:mime-version :dkim-signature; bh=MDXx34Z4qA3a8kaTeqeuzWic43HgUDc8KSJFJYxiSAg=; b=zQ2XWYGDVsII3klxy7IaWMOEePlgMN5wzolaQv7Fju43xZU34uGaB5eIoYoscb1WYu rSViJJGuVtTsHK3Iyja044m4P8502n1v1Hzm7RV5zHr0Yv46Cgvl9tNjxP6aprn7AV7c zT49cqD699pYdWqeHcO/lJvTc/0mkM5CHcW63rbxcjEAX4kiXCRk1X8fUsx2xydAmrf4 rWU2v4wxH0YClnHF/EPklpkxIVvtVDBEH86ScDBaNrPkQOwVCLhayBX6P3N2gzx1hiQl BTUEfVtkQyv1s/Zy8U6AIDXFAO4LFTpwhkoTGy/xK5Q/aXJCrRci/pJr7oCjl/lEtZcP 9OhA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=PWJ00z+z; 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; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id g189si1515638pgc.112.2019.04.18.03.01.32; Thu, 18 Apr 2019 03:01:47 -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; dkim=pass header.i=@gmail.com header.s=20161025 header.b=PWJ00z+z; 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; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388611AbfDRJ6t (ORCPT + 99 others); Thu, 18 Apr 2019 05:58:49 -0400 Received: from mail-vk1-f193.google.com ([209.85.221.193]:44895 "EHLO mail-vk1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728074AbfDRJ6t (ORCPT ); Thu, 18 Apr 2019 05:58:49 -0400 Received: by mail-vk1-f193.google.com with SMTP id q189so329718vkq.11; Thu, 18 Apr 2019 02:58:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc:content-transfer-encoding; bh=MDXx34Z4qA3a8kaTeqeuzWic43HgUDc8KSJFJYxiSAg=; b=PWJ00z+z8JynYuz/jxo66kBeshN2b5sg9Co34vVNAbFBNzQHdY3fl+Dfopj6qqxb+q TVbsAgRO70OTaxGfhpe2Rn2UV5lGv352nHNIFY/CQdOU//ItOfWYvu22ES/7Kjq3TLxT g2+Bv1jrdViBSnNvWQfLQ9xHMb1lWcmDvgR5Y0VBidisVlNNR5lZTRccVWZfj+d24Vgl HENZq9ZzdH5nCxMuzP+/BR2/f2feGkU5GaNeaAvT1QR0+Ec21+VNLfcuixfxjagk8duo cFMfTWyLAwFc3FFq4ywGZt1hyYXp0V21psoU9hJ6ArMOq1jHMj5eESUW8kO9Q+ZZlBk5 mO9Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc:content-transfer-encoding; bh=MDXx34Z4qA3a8kaTeqeuzWic43HgUDc8KSJFJYxiSAg=; b=IQ/PD9RKWV7fKkauWlVFX0W8Hu90RIezsjA/3+Ztg3uHzRPT1wZEcSWcB38YVs/XnJ G+RYjEcRBnvMlg10z3op6Ubb+z4V7lSfgKcNnRq9RXimEjc0ViMqD9kL3dwlnrDB7z17 2hNNpsduTbLa+GFF7vTG5GXxdlCHNAa/+orYZ8cstE17MCgIz05d8p1GY8DtNUP+4HNF wrFR8O8tXOgqxNpMKb39tYj8uIAo08NgCekAEQp5kDPVr2gOGxbPyIAL95jYyICBELes eKVgOzYEK4xRB2XIy2KIMIA6spZj+JediTFQW5+gXhSvDpFBzw8LMCGbn/bXT6t8X0iO Z9kg== X-Gm-Message-State: APjAAAWzhvUWP30OkgDCRWVEiY2De8iimhiHRbCG2JcT7CpwxT8p/Znz Em5y2Ps7ImVb0YxzGQyMAQvTVqMBmAFlwBKPX0B5IYIeGQVR X-Received: by 2002:a1f:954:: with SMTP id 81mr3040252vkj.88.1555581527893; Thu, 18 Apr 2019 02:58:47 -0700 (PDT) MIME-Version: 1.0 References: <20190409065612.32652-1-rdong.ge@gmail.com> In-Reply-To: <20190409065612.32652-1-rdong.ge@gmail.com> From: Rundong Ge Date: Thu, 18 Apr 2019 17:58:37 +0800 Message-ID: Subject: Re: [PATCH] netfilter: fix dangling pointer access of fake_rtable To: Pablo Neira Ayuso Cc: kadlec@blackhole.kfki.hu, fw@strlen.de, Roopa Prabhu , davem@davemloft.net, netfilter-devel@vger.kernel.org, coreteam@netfilter.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org friendly ping Rundong Ge =E4=BA=8E2019=E5=B9=B44=E6=9C=889=E6=97=A5= =E5=91=A8=E4=BA=8C =E4=B8=8B=E5=8D=882:56=E5=86=99=E9=81=93=EF=BC=9A > > With bridge-nf-call-iptables enabeled, Skbs go through the bridge > and enqueued between and > won't be flushed when bridge is > down. Then _skb_refdst of skbs in the nfqueue become dangling pointer. > > Reproduce steps: > 1.Create a bridge on the box. > 2.echo 1 >/proc/sys/net/bridge/bridge-nf-call-iptables > 3.Add a netfilter hook function to queue the packets to nfqueuenum 0. > The hook point must between and > . > 4.Add a userspace process "nfqueue_rcv" to continuously read and > set_verdict "NF_ACCEPT" to packets from queue 0. > 5.Continuosly ping client1 from client0 > 6.Send "Ctrl + Z" to pause the "nfqueue_rcv" to simulate the queue > congestion. > 7.Using "ifconfig br0 down&&brctl delbr br0" to delete the bridge. > 8.At this time the _skb_refdst of skbs in the nfqueue become dangling > pointer. If we send "fg" to resume the "nfqueue_rcv", the kernel > may try to access the freed memory. > > Debug log: > Here I add debug logs in "netdev_freemem" and "dst_release" to prove > the freed memory access. As the log shows, the "dst_release" accessed > bridge's fake_rtable after the bridge was freed. > > Apr 8 22:25:14 raydon kernel: [62139.005062] netdev_freemem name:br0, > fake_rtable:000000009d76cef0 > > Apr 8 22:25:21 raydon kernel: [62145.967133] dst_release > dst:000000009d76cef0 dst->dev->name: =C5=99KU=C2=A1TH > > Apr 8 22:25:21 raydon kernel: [62145.967154] dst_release > dst:000000009d76cef0 dst->dev->name: =C5=99KU=C2=A1TH > > Apr 8 22:25:21 raydon kernel: [62145.967180] dst_release > dst:000000009d76cef0 dst->dev->name: =C5=99KU=C2=A1TH > > Apr 8 22:25:21 raydon kernel: [62145.967197] dst_release > dst:000000009d76cef0 dst->dev->name: =C5=99KU=C2=A1TH > > The reason why the hook point should be after NF_BR_PRI_BRNF> is skbs reference bridge's fake_rtable in > "br_nf_pre_routing_finish" hooked at . > > And the reason why the hook point should be before NF_BR_PRI_BRNF - 1> is "br_nf_forward_ip" will set the state.out to > bridge dev. After this hook point, the "nfqnl_dev_drop" triggered by > the bridge's NETDEV_DOWN event can flush the queued skbs before > bridge's memory is freed, because the state.out now matches the > bridge's dev. > > Signed-off-by: Rundong Ge > --- > net/netfilter/nfnetlink_queue.c | 24 ++++++++++++++++++------ > 1 file changed, 18 insertions(+), 6 deletions(-) > > diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_qu= eue.c > index 0dcc359..57eb02d 100644 > --- a/net/netfilter/nfnetlink_queue.c > +++ b/net/netfilter/nfnetlink_queue.c > @@ -905,13 +905,25 @@ static void free_entry(struct nf_queue_entry *entry= ) > dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex) > { > #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) > - int physinif, physoutif; > + struct net_device *physindev, *physoutdev; > + struct net_bridge_port *port; > > - physinif =3D nf_bridge_get_physinif(entry->skb); > - physoutif =3D nf_bridge_get_physoutif(entry->skb); > - > - if (physinif =3D=3D ifindex || physoutif =3D=3D ifindex) > - return 1; > + physindev =3D nf_bridge_get_physindev(entry->skb); > + physoutdev =3D nf_bridge_get_physoutdev(entry->skb); > + if (physindev) { > + if (physindev->ifindex =3D=3D ifindex) > + return 1; > + port =3D br_port_get_rcu(physindev); > + if (port && port->br->dev->ifindex =3D=3D ifindex) > + return 1; > + } > + if (physoutdev) { > + if (physoutdev->ifindex =3D=3D ifindex) > + return 1; > + port =3D br_port_get_rcu(physoutdev); > + if (port && port->br->dev->ifindex =3D=3D ifindex) > + return 1; > + } > #endif > if (entry->state.in) > if (entry->state.in->ifindex =3D=3D ifindex) > -- > 1.8.3.1 >