net/bridge/br_netfilter_hooks.c | 1 + 1 file changed, 1 insertion(+)
Previous commit 2d72afb34065 ("netfilter: nf_conntrack: fix crash due to
removal of uninitialised entry") move the IPS_CONFIRMED assignment after
the hash table insertion.
When send a broadcast packet to a tap device, which was added to a bridge,
br_nf_local_in() is called to confirm the conntrack. If another conntrack
with the same hash value is added to the hash table, which can be
triggered by a normal packet to a non-bridge device, the below warning
may happen.
------------[ cut here ]------------
WARNING: CPU: 1 PID: 96 at net/bridge/br_netfilter_hooks.c:632 br_nf_local_in+0x168/0x200
CPU: 1 UID: 0 PID: 96 Comm: tap_send Not tainted 6.17.0-rc2-dirty #44 PREEMPT(voluntary)
RIP: 0010:br_nf_local_in+0x168/0x200
Call Trace:
<TASK>
nf_hook_slow+0x3e/0xf0
br_pass_frame_up+0x103/0x180
br_handle_frame_finish+0x2de/0x5b0
br_nf_hook_thresh+0xc0/0x120
br_nf_pre_routing_finish+0x168/0x3a0
br_nf_pre_routing+0x237/0x5e0
br_handle_frame+0x1ec/0x3c0
__netif_receive_skb_core+0x225/0x1210
__netif_receive_skb_one_core+0x37/0xa0
netif_receive_skb+0x36/0x160
tun_get_user+0xa54/0x10c0
tun_chr_write_iter+0x65/0xb0
vfs_write+0x305/0x410
ksys_write+0x60/0xd0
do_syscall_64+0xa4/0x260
entry_SYSCALL_64_after_hwframe+0x77/0x7f
</TASK>
---[ end trace 0000000000000000 ]---
To solve the hash conflict, nf_ct_resolve_clash() try to merge the
conntracks, and update skb->_nfct. However, br_nf_local_in() still use the
old ct from local variable 'nfct' after confirm(), which leads to this
issue. Fix it by rereading nfct from skb.
Fixes: 62e7151ae3eb ("netfilter: bridge: confirm multicast packets before passing them up the stack")
Signed-off-by: Wang Liang <wangliang74@huawei.com>
---
net/bridge/br_netfilter_hooks.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c
index 94cbe967d1c1..55b1b7dcb609 100644
--- a/net/bridge/br_netfilter_hooks.c
+++ b/net/bridge/br_netfilter_hooks.c
@@ -626,6 +626,7 @@ static unsigned int br_nf_local_in(void *priv,
break;
}
+ nfct = skb_nfct(skb);
ct = container_of(nfct, struct nf_conn, ct_general);
WARN_ON_ONCE(!nf_ct_is_confirmed(ct));
--
2.33.0
Wang Liang <wangliang74@huawei.com> wrote: > Previous commit 2d72afb34065 ("netfilter: nf_conntrack: fix crash due to > removal of uninitialised entry") move the IPS_CONFIRMED assignment after > the hash table insertion. How is that related to this change? As you write below, the bug came in with 62e7151ae3eb. > To solve the hash conflict, nf_ct_resolve_clash() try to merge the > conntracks, and update skb->_nfct. However, br_nf_local_in() still use the > old ct from local variable 'nfct' after confirm(), which leads to this > issue. Fix it by rereading nfct from skb. > > Fixes: 62e7151ae3eb ("netfilter: bridge: confirm multicast packets before passing them up the stack") > Signed-off-by: Wang Liang <wangliang74@huawei.com> > --- > net/bridge/br_netfilter_hooks.c | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c > index 94cbe967d1c1..55b1b7dcb609 100644 > --- a/net/bridge/br_netfilter_hooks.c > +++ b/net/bridge/br_netfilter_hooks.c > @@ -626,6 +626,7 @@ static unsigned int br_nf_local_in(void *priv, > break; > } > > + nfct = skb_nfct(skb); > ct = container_of(nfct, struct nf_conn, ct_general); > WARN_ON_ONCE(!nf_ct_is_confirmed(ct)); There is a second bug here, confirm can return NF_DROP and nfct will be NULL. Can you make this change too? (or something similar)? diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c index 94cbe967d1c1..69b7b7c7565e 100644 --- a/net/bridge/br_netfilter_hooks.c +++ b/net/bridge/br_netfilter_hooks.c @@ -619,8 +619,9 @@ static unsigned int br_nf_local_in(void *priv, nf_bridge_pull_encap_header(skb); ret = ct_hook->confirm(skb); switch (ret & NF_VERDICT_MASK) { + case NF_DROP: case NF_STOLEN: - return NF_STOLEN; + return ret; nfct reload seems correct, thanks for catching this.
在 2025/8/20 19:31, Florian Westphal 写道: > Wang Liang <wangliang74@huawei.com> wrote: >> Previous commit 2d72afb34065 ("netfilter: nf_conntrack: fix crash due to >> removal of uninitialised entry") move the IPS_CONFIRMED assignment after >> the hash table insertion. > How is that related to this change? > As you write below, the bug came in with 62e7151ae3eb. Before the commit 2d72afb34065, __nf_conntrack_confirm() set 'ct->status |= IPS_CONFIRMED;' before check hash, the warning will not happen, so I put it here. As you say, the bug came in with 62e7151ae3eb. I will delete this paragraph in next patch. >> To solve the hash conflict, nf_ct_resolve_clash() try to merge the >> conntracks, and update skb->_nfct. However, br_nf_local_in() still use the >> old ct from local variable 'nfct' after confirm(), which leads to this >> issue. Fix it by rereading nfct from skb. >> >> Fixes: 62e7151ae3eb ("netfilter: bridge: confirm multicast packets before passing them up the stack") >> Signed-off-by: Wang Liang <wangliang74@huawei.com> >> --- >> net/bridge/br_netfilter_hooks.c | 1 + >> 1 file changed, 1 insertion(+) >> >> diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c >> index 94cbe967d1c1..55b1b7dcb609 100644 >> --- a/net/bridge/br_netfilter_hooks.c >> +++ b/net/bridge/br_netfilter_hooks.c >> @@ -626,6 +626,7 @@ static unsigned int br_nf_local_in(void *priv, >> break; >> } >> >> + nfct = skb_nfct(skb); >> ct = container_of(nfct, struct nf_conn, ct_general); >> WARN_ON_ONCE(!nf_ct_is_confirmed(ct)); > There is a second bug here, confirm can return NF_DROP and > nfct will be NULL. Thanks for your suggestion! Do you mean that ct may be deleted in confirm and return NF_DROP, so we can not visit it in br_nf_local_in() and need to add 'case NF_DROP:' here? I cannot find somewhere set skb->_nfct to NULL and return NF_DROP. Can you give some hints? ------ Best regards Wang Liang > > Can you make this change too? (or something similar)? > > diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c > index 94cbe967d1c1..69b7b7c7565e 100644 > --- a/net/bridge/br_netfilter_hooks.c > +++ b/net/bridge/br_netfilter_hooks.c > @@ -619,8 +619,9 @@ static unsigned int br_nf_local_in(void *priv, > nf_bridge_pull_encap_header(skb); > ret = ct_hook->confirm(skb); > switch (ret & NF_VERDICT_MASK) { > + case NF_DROP: > case NF_STOLEN: > - return NF_STOLEN; > + return ret; > > > nfct reload seems correct, thanks for catching this.
Wang Liang <wangliang74@huawei.com> wrote: > > 在 2025/8/20 19:31, Florian Westphal 写道: > > Wang Liang <wangliang74@huawei.com> wrote: > > > Previous commit 2d72afb34065 ("netfilter: nf_conntrack: fix crash due to > > > removal of uninitialised entry") move the IPS_CONFIRMED assignment after > > > the hash table insertion. > > How is that related to this change? > > As you write below, the bug came in with 62e7151ae3eb. > > Before the commit 2d72afb34065, __nf_conntrack_confirm() set > 'ct->status |= IPS_CONFIRMED;' before check hash, the warning will not > happen, so I put it here. Oh, right, the problem was concealed before this. > > There is a second bug here, confirm can return NF_DROP and > > nfct will be NULL. > > Thanks for your suggestion! > > Do you mean that ct may be deleted in confirm and return NF_DROP, so we can > not visit it in br_nf_local_in() and need to add 'case NF_DROP:' here? > > I cannot find somewhere set skb->_nfct to NULL and return NF_DROP. Can you > give some hints? You are right, skb->_nfct isn't set to NULL in case NF_DROP is returned. However, the warning will trigger as we did not insert the conntrack entry in that case. I suggest to remove the warning, I don't think it buys anything. Thanks.
在 2025/8/21 14:57, Florian Westphal 写道: > Wang Liang <wangliang74@huawei.com> wrote: >> 在 2025/8/20 19:31, Florian Westphal 写道: >>> Wang Liang <wangliang74@huawei.com> wrote: >>>> Previous commit 2d72afb34065 ("netfilter: nf_conntrack: fix crash due to >>>> removal of uninitialised entry") move the IPS_CONFIRMED assignment after >>>> the hash table insertion. >>> How is that related to this change? >>> As you write below, the bug came in with 62e7151ae3eb. >> Before the commit 2d72afb34065, __nf_conntrack_confirm() set >> 'ct->status |= IPS_CONFIRMED;' before check hash, the warning will not >> happen, so I put it here. > Oh, right, the problem was concealed before this. > >>> There is a second bug here, confirm can return NF_DROP and >>> nfct will be NULL. >> Thanks for your suggestion! >> >> Do you mean that ct may be deleted in confirm and return NF_DROP, so we can >> not visit it in br_nf_local_in() and need to add 'case NF_DROP:' here? >> >> I cannot find somewhere set skb->_nfct to NULL and return NF_DROP. Can you >> give some hints? > You are right, skb->_nfct isn't set to NULL in case NF_DROP is returned. > However, the warning will trigger as we did not insert the conntrack > entry in that case. > > I suggest to remove the warning, I don't think it buys anything. > > Thanks. Yes, remove the warning is a good a choice. I will remove the two lines in v2 patch later, please check it. ------ Best regards Wang Liang
© 2016 - 2025 Red Hat, Inc.