Message ID | 20200106203048.204196-1-edumazet@google.com |
---|---|
State | Accepted |
Delegated to: | David Miller |
Headers | show |
Series | [net] macvlan: do not assume mac_header is set in macvlan_broadcast() | expand |
From: Eric Dumazet <edumazet@google.com> Date: Mon, 6 Jan 2020 12:30:48 -0800 > Use of eth_hdr() in tx path is error prone. > > Many drivers call skb_reset_mac_header() before using it, > but others do not. > > Commit 6d1ccff62780 ("net: reset mac header in dev_start_xmit()") > attempted to fix this generically, but commit d346a3fae3ff > ("packet: introduce PACKET_QDISC_BYPASS socket option") brought > back the macvlan bug. > > Lets add a new helper, so that tx paths no longer have > to call skb_reset_mac_header() only to get a pointer > to skb->data. > > Hopefully we will be able to revert 6d1ccff62780 > ("net: reset mac header in dev_start_xmit()") and save few cycles > in transmit fast path. ... > Fixes: b863ceb7ddce ("[NET]: Add macvlan driver") > Signed-off-by: Eric Dumazet <edumazet@google.com> > Reported-by: syzbot <syzkaller@googlegroups.com> Applied and queued up for -stable, thanks Eric.
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 05631d97eeb4fbfe3ca599dfdccb1c355b1feb45..747c0542a53c763676d491c91a5b704f0eb9848e 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -259,7 +259,7 @@ static void macvlan_broadcast(struct sk_buff *skb, struct net_device *src, enum macvlan_mode mode) { - const struct ethhdr *eth = eth_hdr(skb); + const struct ethhdr *eth = skb_eth_hdr(skb); const struct macvlan_dev *vlan; struct sk_buff *nskb; unsigned int i; diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h index 76cf11e905e160b32625adefd1bcc7b641ff6527..8a9792a6427ad9cf58b50c79cbfe185615800dcb 100644 --- a/include/linux/if_ether.h +++ b/include/linux/if_ether.h @@ -24,6 +24,14 @@ static inline struct ethhdr *eth_hdr(const struct sk_buff *skb) return (struct ethhdr *)skb_mac_header(skb); } +/* Prefer this version in TX path, instead of + * skb_reset_mac_header() + eth_hdr() + */ +static inline struct ethhdr *skb_eth_hdr(const struct sk_buff *skb) +{ + return (struct ethhdr *)skb->data; +} + static inline struct ethhdr *inner_eth_hdr(const struct sk_buff *skb) { return (struct ethhdr *)skb_inner_mac_header(skb);