Skip to content

Commit 574a5b8

Browse files
Florian Westphalummakynes
authored andcommitted
netfilter: nf_dup_netdev: do not push mac header a second time
Eric reports skb_under_panic when using dup/fwd via bond+egress hook. Before pushing mac header, we should make sure that we're called from ingress to put back what was pulled earlier. In egress case, the MAC header is already there; we should leave skb alone. While at it be more careful here: skb might have been altered and headroom reduced, so add a skb_cow() before so that headroom is increased if necessary. nf_do_netdev_egress() assumes skb ownership (it normally ends with a call to dev_queue_xmit), so we must free the packet on error. Fixes: f87b946 ("netfilter: nft_fwd_netdev: Support egress hook") Reported-by: Eric Garver <[email protected]> Signed-off-by: Florian Westphal <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent 5d79d8a commit 574a5b8

File tree

1 file changed

+10
-4
lines changed

1 file changed

+10
-4
lines changed

net/netfilter/nf_dup_netdev.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,16 @@
1313
#include <net/netfilter/nf_tables_offload.h>
1414
#include <net/netfilter/nf_dup_netdev.h>
1515

16-
static void nf_do_netdev_egress(struct sk_buff *skb, struct net_device *dev)
16+
static void nf_do_netdev_egress(struct sk_buff *skb, struct net_device *dev,
17+
enum nf_dev_hooks hook)
1718
{
18-
if (skb_mac_header_was_set(skb))
19+
if (hook == NF_NETDEV_INGRESS && skb_mac_header_was_set(skb)) {
20+
if (skb_cow_head(skb, skb->mac_len)) {
21+
kfree_skb(skb);
22+
return;
23+
}
1924
skb_push(skb, skb->mac_len);
25+
}
2026

2127
skb->dev = dev;
2228
skb_clear_tstamp(skb);
@@ -33,7 +39,7 @@ void nf_fwd_netdev_egress(const struct nft_pktinfo *pkt, int oif)
3339
return;
3440
}
3541

36-
nf_do_netdev_egress(pkt->skb, dev);
42+
nf_do_netdev_egress(pkt->skb, dev, nft_hook(pkt));
3743
}
3844
EXPORT_SYMBOL_GPL(nf_fwd_netdev_egress);
3945

@@ -48,7 +54,7 @@ void nf_dup_netdev_egress(const struct nft_pktinfo *pkt, int oif)
4854

4955
skb = skb_clone(pkt->skb, GFP_ATOMIC);
5056
if (skb)
51-
nf_do_netdev_egress(skb, dev);
57+
nf_do_netdev_egress(skb, dev, nft_hook(pkt));
5258
}
5359
EXPORT_SYMBOL_GPL(nf_dup_netdev_egress);
5460

0 commit comments

Comments
 (0)