[Devel] [PATCH RH7] br_netfilter: add debug to see what happens in br_nf_pre_routing_finish

Pavel Tikhomirov ptikhomirov at virtuozzo.com
Fri Dec 22 13:33:08 MSK 2023


We see a packet with skb->dev already freed, which should have passed
this place in br_nf_pre_routing_finish as it has nf_bridge->neigh_header
set to src mac which can be set only later in this stack in
br_nf_pre_routing_finish_bridge. So I try to print all information I can
imagine to help understanding this problem.

We see this skb taken from neigh->arp_queue and then crash on it, and
here:

  +-> br_nf_pre_routing
    +-> br_nf_pre_routing_finish
      +-> skb->dev = nf_bridge->physindev #1
      +-> br_nf_pre_routing_finish_bridge #2
        +-> nf_bridge->bridged_dnat = 1 #1
        +-> neighbour->output #2
          +-> neigh_resolve_output
            +-> neigh_event_send
              +-> __neigh_event_send
                +-> __skb_queue_tail(&neigh->arp_queue, skb)

skb can acutually get to arp_queue. This is the second confirmation that
something wrong likely happened on this stack.

https://virtuozzo.atlassian.net/browse/PSBM-151735
Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
---
 net/bridge/br_netfilter_hooks.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c
index eb8ad039c343f..6258fe55a04eb 100644
--- a/net/bridge/br_netfilter_hooks.c
+++ b/net/bridge/br_netfilter_hooks.c
@@ -386,6 +386,17 @@ static int br_nf_pre_routing_finish(struct sock *sk, struct sk_buff *skb)
 		} else {
 			if (skb_dst(skb)->dev == dev) {
 bridged_dnat:
+				/*
+				 * Debug for PSBM-151735, I'm really curious how we can get here.
+				 */
+				WARN_ONCE(1, "br_nf_pre_routing_finish: saddr=%pI4 daddr=%pI4 nf_bridge_daddr=%pI4 "
+					     "dev=%s skb->dev=%s nf_bridge->indev=%s "
+					     "skb->dst->dev=%s "
+					     "err=%d indev_forward=%d\n",
+					  &iph->saddr, &iph->daddr, &nf_bridge->ipv4_daddr,
+					  dev->name, skb->dev->name, nf_bridge->physindev ? nf_bridge->physindev->name : "<none>",
+					  skb_dst(skb) && skb_dst(skb)->dev ? skb_dst(skb)->dev->name : "<none>",
+					  err, IN_DEV_FORWARD(__in_dev_get_rcu(dev)));
 				skb->dev = nf_bridge->physindev;
 				nf_bridge_update_protocol(skb);
 				nf_bridge_push_encap_header(skb);
-- 
2.43.0



More information about the Devel mailing list