Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bridge: ebtables: don't crash when using dnat target in output chains

xt_in() returns NULL in the output hook, skip the pkt_type change for
that case, redirection only makes sense in broute/prerouting hooks.

Reported-by: Tom Yan <tom.ty89@gmail.com>
Cc: Linus Lüssing <linus.luessing@c0d3.blue>
Fixes: cf3cb246e277d ("bridge: ebtables: fix reception of frames DNAT-ed to bridge device/port")
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Florian Westphal and committed by
Pablo Neira Ayuso
b23c0742 9fedd894

+15 -4
+15 -4
net/bridge/netfilter/ebt_dnat.c
··· 20 20 ebt_dnat_tg(struct sk_buff *skb, const struct xt_action_param *par) 21 21 { 22 22 const struct ebt_nat_info *info = par->targinfo; 23 - struct net_device *dev; 24 23 25 24 if (skb_ensure_writable(skb, ETH_ALEN)) 26 25 return EBT_DROP; ··· 32 33 else 33 34 skb->pkt_type = PACKET_MULTICAST; 34 35 } else { 35 - if (xt_hooknum(par) != NF_BR_BROUTING) 36 - dev = br_port_get_rcu(xt_in(par))->br->dev; 37 - else 36 + const struct net_device *dev; 37 + 38 + switch (xt_hooknum(par)) { 39 + case NF_BR_BROUTING: 38 40 dev = xt_in(par); 41 + break; 42 + case NF_BR_PRE_ROUTING: 43 + dev = br_port_get_rcu(xt_in(par))->br->dev; 44 + break; 45 + default: 46 + dev = NULL; 47 + break; 48 + } 49 + 50 + if (!dev) /* NF_BR_LOCAL_OUT */ 51 + return info->target; 39 52 40 53 if (ether_addr_equal(info->mac, dev->dev_addr)) 41 54 skb->pkt_type = PACKET_HOST;