diff options
author | openeuler-ci-bot <george@openeuler.sh> | 2024-04-16 01:34:49 +0000 |
---|---|---|
committer | Gitee <noreply@gitee.com> | 2024-04-16 01:34:49 +0000 |
commit | fb7a4538533abcb510726bb372d530ccdf56453d (patch) | |
tree | a247124611d24e8bce7f19232f7b4c810d3f9c77 | |
parent | 8f9b035c4fb44c9cf16d33c68e4163d0ca8cb854 (diff) | |
parent | ae4d7191e99f6ed4fb2cab728a545eed9f3bffca (diff) | |
download | openEuler-kernel-fb7a4538533abcb510726bb372d530ccdf56453d.tar.gz |
!5131 [sync] PR-5113: fix CVE-2023-52578
Merge Pull Request from: @openeuler-sync-bot
Origin pull request:
https://gitee.com/openeuler/kernel/pulls/5113
PR sync from: Zhengchao Shao <shaozhengchao@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/OIOS3PLH6PBZRR4FH7X7BV5IFN7NRX6C/
fix CVE-2023-52578
Eric Dumazet (2):
net: add atomic_long_t to net_device_stats fields
net: bridge: use DEV_STATS_INC()
Felix Riemann (1):
net: Fix unwanted sign extension in netdev_stats_to_stats64()
Zhengchao Shao (1):
net: fix kabi check warning
--
2.34.1
https://gitee.com/src-openeuler/kernel/issues/I95ATV
Link:https://gitee.com/openeuler/kernel/pulls/5131
Reviewed-by: Yue Haibing <yuehaibing@huawei.com>
Signed-off-by: Jialin Zhang <zhangjialin11@huawei.com>
-rw-r--r-- | include/linux/netdevice.h | 81 | ||||
-rw-r--r-- | include/net/dst.h | 5 | ||||
-rw-r--r-- | net/bridge/br_forward.c | 4 | ||||
-rw-r--r-- | net/bridge/br_input.c | 4 | ||||
-rw-r--r-- | net/core/dev.c | 14 |
5 files changed, 67 insertions, 41 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 0550644d276df5..5d5ecff2c0415b 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -167,31 +167,61 @@ static inline bool dev_xmit_complete(int rc) * (unsigned long) so they can be read and written atomically. */ +#define NET_DEV_STAT(FIELD) \ + union { \ + unsigned long FIELD; \ + atomic_long_t __##FIELD; \ + } + struct net_device_stats { - unsigned long rx_packets; - unsigned long tx_packets; - unsigned long rx_bytes; - unsigned long tx_bytes; - unsigned long rx_errors; - unsigned long tx_errors; - unsigned long rx_dropped; - unsigned long tx_dropped; - unsigned long multicast; - unsigned long collisions; - unsigned long rx_length_errors; - unsigned long rx_over_errors; - unsigned long rx_crc_errors; - unsigned long rx_frame_errors; - unsigned long rx_fifo_errors; - unsigned long rx_missed_errors; - unsigned long tx_aborted_errors; - unsigned long tx_carrier_errors; - unsigned long tx_fifo_errors; - unsigned long tx_heartbeat_errors; - unsigned long tx_window_errors; - unsigned long rx_compressed; - unsigned long tx_compressed; + KABI_REPLACE(unsigned long rx_packets, + NET_DEV_STAT(rx_packets)) + KABI_REPLACE(unsigned long tx_packets, + NET_DEV_STAT(tx_packets)) + KABI_REPLACE(unsigned long rx_bytes, + NET_DEV_STAT(rx_bytes)) + KABI_REPLACE(unsigned long tx_bytes, + NET_DEV_STAT(tx_bytes)) + KABI_REPLACE(unsigned long rx_errors, + NET_DEV_STAT(rx_errors)) + KABI_REPLACE(unsigned long tx_errors, + NET_DEV_STAT(tx_errors)) + KABI_REPLACE(unsigned long rx_dropped, + NET_DEV_STAT(rx_dropped)) + KABI_REPLACE(unsigned long tx_dropped, + NET_DEV_STAT(tx_dropped)) + KABI_REPLACE(unsigned long multicast, + NET_DEV_STAT(multicast)) + KABI_REPLACE(unsigned long collisions, + NET_DEV_STAT(collisions)) + KABI_REPLACE(unsigned long rx_length_errors, + NET_DEV_STAT(rx_length_errors)) + KABI_REPLACE(unsigned long rx_over_errors, + NET_DEV_STAT(rx_over_errors)) + KABI_REPLACE(unsigned long rx_crc_errors, + NET_DEV_STAT(rx_crc_errors)) + KABI_REPLACE(unsigned long rx_frame_errors, + NET_DEV_STAT(rx_frame_errors)) + KABI_REPLACE(unsigned long rx_fifo_errors, + NET_DEV_STAT(rx_fifo_errors)) + KABI_REPLACE(unsigned long rx_missed_errors, + NET_DEV_STAT(rx_missed_errors)) + KABI_REPLACE(unsigned long tx_aborted_errors, + NET_DEV_STAT(tx_aborted_errors)) + KABI_REPLACE(unsigned long tx_carrier_errors, + NET_DEV_STAT(tx_carrier_errors)) + KABI_REPLACE(unsigned long tx_fifo_errors, + NET_DEV_STAT(tx_fifo_errors)) + KABI_REPLACE(unsigned long tx_heartbeat_errors, + NET_DEV_STAT(tx_heartbeat_errors)) + KABI_REPLACE(unsigned long tx_window_errors, + NET_DEV_STAT(tx_window_errors)) + KABI_REPLACE(unsigned long rx_compressed, + NET_DEV_STAT(rx_compressed)) + KABI_REPLACE(unsigned long tx_compressed, + NET_DEV_STAT(tx_compressed)) }; +#undef NET_DEV_STAT #include <linux/cache.h> @@ -5310,4 +5340,9 @@ do { \ extern struct net_device *blackhole_netdev; +/* Note: Avoid these macros in fast path, prefer per-cpu or per-queue counters. */ +#define DEV_STATS_INC(DEV, FIELD) atomic_long_inc(&(DEV)->stats.__##FIELD) +#define DEV_STATS_ADD(DEV, FIELD, VAL) \ + atomic_long_add((VAL), &(DEV)->stats.__##FIELD) + #endif /* _LINUX_NETDEVICE_H */ diff --git a/include/net/dst.h b/include/net/dst.h index ce7f7a1d968b5f..088a7ce6cc744d 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -360,9 +360,8 @@ static inline void __skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev, static inline void skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev, struct net *net) { - /* TODO : stats should be SMP safe */ - dev->stats.rx_packets++; - dev->stats.rx_bytes += skb->len; + DEV_STATS_INC(dev, rx_packets); + DEV_STATS_ADD(dev, rx_bytes, skb->len); __skb_tunnel_rx(skb, dev, net); } diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index 4610f3a13966fa..f2ef75c7ccc68a 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c @@ -118,7 +118,7 @@ static int deliver_clone(const struct net_bridge_port *prev, skb = skb_clone(skb, GFP_ATOMIC); if (!skb) { - dev->stats.tx_dropped++; + DEV_STATS_INC(dev, tx_dropped); return -ENOMEM; } @@ -255,7 +255,7 @@ static void maybe_deliver_addr(struct net_bridge_port *p, struct sk_buff *skb, skb = skb_copy(skb, GFP_ATOMIC); if (!skb) { - dev->stats.tx_dropped++; + DEV_STATS_INC(dev, tx_dropped); return; } diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index bf5bf148091f90..52dd0708fd143d 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -145,12 +145,12 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb if ((mdst && mdst->host_joined) || br_multicast_is_router(br)) { local_rcv = true; - br->dev->stats.multicast++; + DEV_STATS_INC(br->dev, multicast); } mcast_hit = true; } else { local_rcv = true; - br->dev->stats.multicast++; + DEV_STATS_INC(br->dev, multicast); } break; case BR_PKT_UNICAST: diff --git a/net/core/dev.c b/net/core/dev.c index fd2d753ebee39f..7bc8e18c47789c 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -10337,24 +10337,16 @@ void netdev_run_todo(void) void netdev_stats_to_stats64(struct rtnl_link_stats64 *stats64, const struct net_device_stats *netdev_stats) { -#if BITS_PER_LONG == 64 - BUILD_BUG_ON(sizeof(*stats64) < sizeof(*netdev_stats)); - memcpy(stats64, netdev_stats, sizeof(*netdev_stats)); - /* zero out counters that only exist in rtnl_link_stats64 */ - memset((char *)stats64 + sizeof(*netdev_stats), 0, - sizeof(*stats64) - sizeof(*netdev_stats)); -#else - size_t i, n = sizeof(*netdev_stats) / sizeof(unsigned long); - const unsigned long *src = (const unsigned long *)netdev_stats; + size_t i, n = sizeof(*netdev_stats) / sizeof(atomic_long_t); + const atomic_long_t *src = (atomic_long_t *)netdev_stats; u64 *dst = (u64 *)stats64; BUILD_BUG_ON(n > sizeof(*stats64) / sizeof(u64)); for (i = 0; i < n; i++) - dst[i] = src[i]; + dst[i] = (unsigned long)atomic_long_read(&src[i]); /* zero out counters that only exist in rtnl_link_stats64 */ memset((char *)stats64 + n * sizeof(u64), 0, sizeof(*stats64) - n * sizeof(u64)); -#endif } EXPORT_SYMBOL(netdev_stats_to_stats64); |