lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Thu, 20 Jun 2024 11:47:09 +0000
From: Eric Dumazet <edumazet@...gle.com>
To: "David S . Miller" <davem@...emloft.net>, Jakub Kicinski <kuba@...nel.org>, 
	Paolo Abeni <pabeni@...hat.com>
Cc: Ziwei Xiao <ziweixiao@...gle.com>, Praveen Kaligineedi <pkaligineedi@...gle.com>, 
	Harshitha Ramamurthy <hramamurthy@...gle.com>, Willem de Bruijn <willemb@...gle.com>, 
	Jeroen de Borst <jeroendb@...gle.com>, Shailend Chand <shailend@...gle.com>, netdev@...r.kernel.org, 
	eric.dumazet@...il.com, Eric Dumazet <edumazet@...gle.com>
Subject: [PATCH net-next 4/6] net: ethtool: call ethtool_get_one_feature()
 without RTNL

ethtool_get_one_feature() is used by ETHTOOL_GTXCSUM, ETHTOOL_GRXCSUM,
ETHTOOL_GSG, ETHTOOL_GTSO, ETHTOOL_GGSO and ETHTOOL_GGRO.

Add WRITE_ONCE() and READ_ONCE() annotations on dev->features.

Note that many READ_ONCE() annotations are probably missing in many drivers,
but this is orthogonal to this patch.

Signed-off-by: Eric Dumazet <edumazet@...gle.com>
---
 net/core/dev.c      | 10 +++++-----
 net/ethtool/ioctl.c | 30 ++++++++++++++++--------------
 2 files changed, 21 insertions(+), 19 deletions(-)

diff --git a/net/core/dev.c b/net/core/dev.c
index 093d82bf0e2886d4948f4952353c71c92e3586c6..b18223ed269f24bedd02b7c435de0ce2f1f8edf3 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3536,7 +3536,7 @@ static netdev_features_t gso_features_check(const struct sk_buff *skb,
 netdev_features_t netif_skb_features(struct sk_buff *skb)
 {
 	struct net_device *dev = skb->dev;
-	netdev_features_t features = dev->features;
+	netdev_features_t features = READ_ONCE(dev->features);
 
 	if (skb_is_gso(skb))
 		features = gso_features_check(skb, dev, features);
@@ -10016,7 +10016,7 @@ int __netdev_update_features(struct net_device *dev)
 			 * but *after* calling udp_tunnel_drop_rx_info.
 			 */
 			if (features & NETIF_F_RX_UDP_TUNNEL_PORT) {
-				dev->features = features;
+				WRITE_ONCE(dev->features, features);
 				udp_tunnel_get_rx_info(dev);
 			} else {
 				udp_tunnel_drop_rx_info(dev);
@@ -10025,7 +10025,7 @@ int __netdev_update_features(struct net_device *dev)
 
 		if (diff & NETIF_F_HW_VLAN_CTAG_FILTER) {
 			if (features & NETIF_F_HW_VLAN_CTAG_FILTER) {
-				dev->features = features;
+				WRITE_ONCE(dev->features, features);
 				err |= vlan_get_rx_ctag_filter_info(dev);
 			} else {
 				vlan_drop_rx_ctag_filter_info(dev);
@@ -10034,14 +10034,14 @@ int __netdev_update_features(struct net_device *dev)
 
 		if (diff & NETIF_F_HW_VLAN_STAG_FILTER) {
 			if (features & NETIF_F_HW_VLAN_STAG_FILTER) {
-				dev->features = features;
+				WRITE_ONCE(dev->features, features);
 				err |= vlan_get_rx_stag_filter_info(dev);
 			} else {
 				vlan_drop_rx_stag_filter_info(dev);
 			}
 		}
 
-		dev->features = features;
+		WRITE_ONCE(dev->features, features);
 	}
 
 	return err < 0 ? 0 : 1;
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
index 70bb0d2fa2ed416fdff3de71a4f752e4a1bba67a..d0c9d2ad9c3d0acb1be00eb4970d3a1ef9da030a 100644
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -245,13 +245,13 @@ static netdev_features_t ethtool_get_feature_mask(u32 eth_cmd)
 	}
 }
 
-static int ethtool_get_one_feature(struct net_device *dev,
+static int ethtool_get_one_feature(const struct net_device *dev,
 	char __user *useraddr, u32 ethcmd)
 {
 	netdev_features_t mask = ethtool_get_feature_mask(ethcmd);
 	struct ethtool_value edata = {
 		.cmd = ethcmd,
-		.data = !!(dev->features & mask),
+		.data = !!(READ_ONCE(dev->features) & mask),
 	};
 
 	if (copy_to_user(useraddr, &edata, sizeof(edata)))
@@ -3049,14 +3049,6 @@ __dev_ethtool(struct net_device *dev, struct ifreq *ifr,
 	case ETHTOOL_SFEATURES:
 		rc = ethtool_set_features(dev, useraddr);
 		break;
-	case ETHTOOL_GTXCSUM:
-	case ETHTOOL_GRXCSUM:
-	case ETHTOOL_GSG:
-	case ETHTOOL_GTSO:
-	case ETHTOOL_GGSO:
-	case ETHTOOL_GGRO:
-		rc = ethtool_get_one_feature(dev, useraddr, ethcmd);
-		break;
 	case ETHTOOL_STXCSUM:
 	case ETHTOOL_SRXCSUM:
 	case ETHTOOL_SSG:
@@ -3178,10 +3170,20 @@ int dev_ethtool(struct net *net, struct ifreq *ifr, void __user *useraddr)
 	if (!netif_device_present(dev))
 		goto out_pm;
 
-	rtnl_lock();
-	rc = __dev_ethtool(dev, ifr, useraddr, ethcmd, sub_cmd, state);
-	rtnl_unlock();
-
+	switch (ethcmd) {
+	case ETHTOOL_GTXCSUM:
+	case ETHTOOL_GRXCSUM:
+	case ETHTOOL_GSG:
+	case ETHTOOL_GTSO:
+	case ETHTOOL_GGSO:
+	case ETHTOOL_GGRO:
+		rc = ethtool_get_one_feature(dev, useraddr, ethcmd);
+		break;
+	default:
+		rtnl_lock();
+		rc = __dev_ethtool(dev, ifr, useraddr, ethcmd, sub_cmd, state);
+		rtnl_unlock();
+	}
 out_pm:
 	if (dev->dev.parent)
 		pm_runtime_put(dev->dev.parent);
-- 
2.45.2.627.g7a2c4fd464-goog


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ