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

Configure Feed

Select the types of activity you want to include in your feed.

bonding: prevent potential infinite loop in bond_header_parse()

bond_header_parse() can loop if a stack of two bonding devices is setup,
because skb->dev always points to the hierarchy top.

Add new "const struct net_device *dev" parameter to
(struct header_ops)->parse() method to make sure the recursion
is bounded, and that the final leaf parse method is called.

Fixes: 950803f72547 ("bonding: fix type confusion in bond_setup_by_slave()")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Jiayuan Chen <jiayuan.chen@shopee.com>
Tested-by: Jiayuan Chen <jiayuan.chen@shopee.com>
Cc: Jay Vosburgh <jv@jvosburgh.net>
Cc: Andrew Lunn <andrew+netdev@lunn.ch>
Link: https://patch.msgid.link/20260315104152.1436867-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Eric Dumazet and committed by
Jakub Kicinski
b7405dcf 43d222fb

+28 -18
+3 -2
drivers/firewire/net.c
··· 257 257 memcpy((u8 *)hh->hh_data + HH_DATA_OFF(FWNET_HLEN), haddr, net->addr_len); 258 258 } 259 259 260 - static int fwnet_header_parse(const struct sk_buff *skb, unsigned char *haddr) 260 + static int fwnet_header_parse(const struct sk_buff *skb, const struct net_device *dev, 261 + unsigned char *haddr) 261 262 { 262 - memcpy(haddr, skb->dev->dev_addr, FWNET_ALEN); 263 + memcpy(haddr, dev->dev_addr, FWNET_ALEN); 263 264 264 265 return FWNET_ALEN; 265 266 }
+5 -3
drivers/net/bonding/bond_main.c
··· 1530 1530 return ret; 1531 1531 } 1532 1532 1533 - static int bond_header_parse(const struct sk_buff *skb, unsigned char *haddr) 1533 + static int bond_header_parse(const struct sk_buff *skb, 1534 + const struct net_device *dev, 1535 + unsigned char *haddr) 1534 1536 { 1535 - struct bonding *bond = netdev_priv(skb->dev); 1537 + struct bonding *bond = netdev_priv(dev); 1536 1538 const struct header_ops *slave_ops; 1537 1539 struct slave *slave; 1538 1540 int ret = 0; ··· 1544 1542 if (slave) { 1545 1543 slave_ops = READ_ONCE(slave->dev->header_ops); 1546 1544 if (slave_ops && slave_ops->parse) 1547 - ret = slave_ops->parse(skb, haddr); 1545 + ret = slave_ops->parse(skb, slave->dev, haddr); 1548 1546 } 1549 1547 rcu_read_unlock(); 1550 1548 return ret;
+2 -1
include/linux/etherdevice.h
··· 42 42 43 43 int eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, 44 44 const void *daddr, const void *saddr, unsigned len); 45 - int eth_header_parse(const struct sk_buff *skb, unsigned char *haddr); 45 + int eth_header_parse(const struct sk_buff *skb, const struct net_device *dev, 46 + unsigned char *haddr); 46 47 int eth_header_cache(const struct neighbour *neigh, struct hh_cache *hh, 47 48 __be16 type); 48 49 void eth_header_cache_update(struct hh_cache *hh, const struct net_device *dev,
+2 -1
include/linux/if_ether.h
··· 40 40 return (struct ethhdr *)skb_inner_mac_header(skb); 41 41 } 42 42 43 - int eth_header_parse(const struct sk_buff *skb, unsigned char *haddr); 43 + int eth_header_parse(const struct sk_buff *skb, const struct net_device *dev, 44 + unsigned char *haddr); 44 45 45 46 extern ssize_t sysfs_format_mac(char *buf, const unsigned char *addr, int len); 46 47
+4 -2
include/linux/netdevice.h
··· 311 311 int (*create) (struct sk_buff *skb, struct net_device *dev, 312 312 unsigned short type, const void *daddr, 313 313 const void *saddr, unsigned int len); 314 - int (*parse)(const struct sk_buff *skb, unsigned char *haddr); 314 + int (*parse)(const struct sk_buff *skb, 315 + const struct net_device *dev, 316 + unsigned char *haddr); 315 317 int (*cache)(const struct neighbour *neigh, struct hh_cache *hh, __be16 type); 316 318 void (*cache_update)(struct hh_cache *hh, 317 319 const struct net_device *dev, ··· 3447 3445 3448 3446 if (!dev->header_ops || !dev->header_ops->parse) 3449 3447 return 0; 3450 - return dev->header_ops->parse(skb, haddr); 3448 + return dev->header_ops->parse(skb, dev, haddr); 3451 3449 } 3452 3450 3453 3451 static inline __be16 dev_parse_header_protocol(const struct sk_buff *skb)
+3 -6
net/ethernet/eth.c
··· 193 193 } 194 194 EXPORT_SYMBOL(eth_type_trans); 195 195 196 - /** 197 - * eth_header_parse - extract hardware address from packet 198 - * @skb: packet to extract header from 199 - * @haddr: destination buffer 200 - */ 201 - int eth_header_parse(const struct sk_buff *skb, unsigned char *haddr) 196 + int eth_header_parse(const struct sk_buff *skb, const struct net_device *dev, 197 + unsigned char *haddr) 202 198 { 203 199 const struct ethhdr *eth = eth_hdr(skb); 200 + 204 201 memcpy(haddr, eth->h_source, ETH_ALEN); 205 202 return ETH_ALEN; 206 203 }
+2 -1
net/ipv4/ip_gre.c
··· 919 919 return -(t->hlen + sizeof(*iph)); 920 920 } 921 921 922 - static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr) 922 + static int ipgre_header_parse(const struct sk_buff *skb, const struct net_device *dev, 923 + unsigned char *haddr) 923 924 { 924 925 const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb); 925 926 memcpy(haddr, &iph->saddr, 4);
+3 -1
net/mac802154/iface.c
··· 469 469 } 470 470 471 471 static int 472 - mac802154_header_parse(const struct sk_buff *skb, unsigned char *haddr) 472 + mac802154_header_parse(const struct sk_buff *skb, 473 + const struct net_device *dev, 474 + unsigned char *haddr) 473 475 { 474 476 struct ieee802154_hdr hdr; 475 477
+4 -1
net/phonet/af_phonet.c
··· 129 129 return 1; 130 130 } 131 131 132 - static int pn_header_parse(const struct sk_buff *skb, unsigned char *haddr) 132 + static int pn_header_parse(const struct sk_buff *skb, 133 + const struct net_device *dev, 134 + unsigned char *haddr) 133 135 { 134 136 const u8 *media = skb_mac_header(skb); 137 + 135 138 *haddr = *media; 136 139 return 1; 137 140 }