Commit ffb7ed19 authored by Stanislav Fomichev's avatar Stanislav Fomichev Committed by Jakub Kicinski
Browse files

net: hold netdev instance lock during ioctl operations



Convert all ndo_eth_ioctl invocations to dev_eth_ioctl which does the
locking. Reflow some of the dev_siocxxx to drop else clause.

Cc: Saeed Mahameed <saeed@kernel.org>
Signed-off-by: default avatarStanislav Fomichev <sdf@fomichev.me>
Link: https://patch.msgid.link/20250305163732.2766420-8-sdf@fomichev.me


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 7e4d784f
Loading
Loading
Loading
Loading
+4 −5
Original line number Diff line number Diff line
@@ -855,7 +855,6 @@ static int bond_check_dev_link(struct bonding *bond,
			       struct net_device *slave_dev, int reporting)
{
	const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
	int (*ioctl)(struct net_device *, struct ifreq *, int);
	struct ifreq ifr;
	struct mii_ioctl_data *mii;

@@ -871,8 +870,7 @@ static int bond_check_dev_link(struct bonding *bond,
			BMSR_LSTATUS : 0;

	/* Ethtool can't be used, fallback to MII ioctls. */
	ioctl = slave_ops->ndo_eth_ioctl;
	if (ioctl) {
	if (slave_ops->ndo_eth_ioctl) {
		/* TODO: set pointer to correct ioctl on a per team member
		 *       bases to make this more efficient. that is, once
		 *       we determine the correct ioctl, we will always
@@ -888,9 +886,10 @@ static int bond_check_dev_link(struct bonding *bond,
		/* Yes, the mii is overlaid on the ifreq.ifr_ifru */
		strscpy_pad(ifr.ifr_name, slave_dev->name, IFNAMSIZ);
		mii = if_mii(&ifr);
		if (ioctl(slave_dev, &ifr, SIOCGMIIPHY) == 0) {

		if (dev_eth_ioctl(slave_dev, &ifr, SIOCGMIIPHY) == 0) {
			mii->reg_num = MII_BMSR;
			if (ioctl(slave_dev, &ifr, SIOCGMIIREG) == 0)
			if (dev_eth_ioctl(slave_dev, &ifr, SIOCGMIIREG) == 0)
				return mii->val_out & BMSR_LSTATUS;
		}
	}
+3 −0
Original line number Diff line number Diff line
@@ -4229,6 +4229,8 @@ int put_user_ifreq(struct ifreq *ifr, void __user *arg);
int dev_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr,
		void __user *data, bool *need_copyout);
int dev_ifconf(struct net *net, struct ifconf __user *ifc);
int dev_eth_ioctl(struct net_device *dev,
		  struct ifreq *ifr, unsigned int cmd);
int generic_hwtstamp_get_lower(struct net_device *dev,
			       struct kernel_hwtstamp_config *kernel_cfg);
int generic_hwtstamp_set_lower(struct net_device *dev,
@@ -4251,6 +4253,7 @@ int netif_change_net_namespace(struct net_device *dev, struct net *net,
int dev_change_net_namespace(struct net_device *dev, struct net *net,
			     const char *pat);
int __dev_set_mtu(struct net_device *, int);
int netif_set_mtu(struct net_device *dev, int new_mtu);
int dev_set_mtu(struct net_device *, int);
int dev_pre_changeaddr_notify(struct net_device *dev, const char *addr,
			      struct netlink_ext_ack *extack);
+1 −3
Original line number Diff line number Diff line
@@ -377,7 +377,6 @@ static int vlan_hwtstamp_set(struct net_device *dev,
static int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
	struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
	const struct net_device_ops *ops = real_dev->netdev_ops;
	struct ifreq ifrr;
	int err = -EOPNOTSUPP;

@@ -388,8 +387,7 @@ static int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
	case SIOCGMIIPHY:
	case SIOCGMIIREG:
	case SIOCSMIIREG:
		if (netif_device_present(real_dev) && ops->ndo_eth_ioctl)
			err = ops->ndo_eth_ioctl(real_dev, &ifrr, cmd);
		err = dev_eth_ioctl(real_dev, &ifrr, cmd);
		break;
	}

+2 −2
Original line number Diff line number Diff line
@@ -9522,7 +9522,7 @@ int netif_set_mtu_ext(struct net_device *dev, int new_mtu,
	return err;
}

int dev_set_mtu(struct net_device *dev, int new_mtu)
int netif_set_mtu(struct net_device *dev, int new_mtu)
{
	struct netlink_ext_ack extack;
	int err;
@@ -9533,7 +9533,7 @@ int dev_set_mtu(struct net_device *dev, int new_mtu)
		net_err_ratelimited("%s: %s\n", dev->name, extack._msg);
	return err;
}
EXPORT_SYMBOL(dev_set_mtu);
EXPORT_SYMBOL(netif_set_mtu);

int netif_change_tx_queue_len(struct net_device *dev, unsigned long new_len)
{
+30 −0
Original line number Diff line number Diff line
@@ -222,3 +222,33 @@ void dev_close(struct net_device *dev)
	netdev_unlock_ops(dev);
}
EXPORT_SYMBOL(dev_close);

int dev_eth_ioctl(struct net_device *dev,
		  struct ifreq *ifr, unsigned int cmd)
{
	const struct net_device_ops *ops = dev->netdev_ops;
	int ret = -ENODEV;

	if (!ops->ndo_eth_ioctl)
		return -EOPNOTSUPP;

	netdev_lock_ops(dev);
	if (netif_device_present(dev))
		ret = ops->ndo_eth_ioctl(dev, ifr, cmd);
	netdev_unlock_ops(dev);

	return ret;
}
EXPORT_SYMBOL(dev_eth_ioctl);

int dev_set_mtu(struct net_device *dev, int new_mtu)
{
	int ret;

	netdev_lock_ops(dev);
	ret = netif_set_mtu(dev, new_mtu);
	netdev_unlock_ops(dev);

	return ret;
}
EXPORT_SYMBOL(dev_set_mtu);
Loading