Skip to content

Commit ffb7ed1

Browse files
Stanislav Fomichevkuba-moo
authored andcommitted
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 <[email protected]> Signed-off-by: Stanislav Fomichev <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 7e4d784 commit ffb7ed1

File tree

6 files changed

+80
-37
lines changed

6 files changed

+80
-37
lines changed

drivers/net/bonding/bond_main.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -855,7 +855,6 @@ static int bond_check_dev_link(struct bonding *bond,
855855
struct net_device *slave_dev, int reporting)
856856
{
857857
const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
858-
int (*ioctl)(struct net_device *, struct ifreq *, int);
859858
struct ifreq ifr;
860859
struct mii_ioctl_data *mii;
861860

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

873872
/* Ethtool can't be used, fallback to MII ioctls. */
874-
ioctl = slave_ops->ndo_eth_ioctl;
875-
if (ioctl) {
873+
if (slave_ops->ndo_eth_ioctl) {
876874
/* TODO: set pointer to correct ioctl on a per team member
877875
* bases to make this more efficient. that is, once
878876
* we determine the correct ioctl, we will always
@@ -888,9 +886,10 @@ static int bond_check_dev_link(struct bonding *bond,
888886
/* Yes, the mii is overlaid on the ifreq.ifr_ifru */
889887
strscpy_pad(ifr.ifr_name, slave_dev->name, IFNAMSIZ);
890888
mii = if_mii(&ifr);
891-
if (ioctl(slave_dev, &ifr, SIOCGMIIPHY) == 0) {
889+
890+
if (dev_eth_ioctl(slave_dev, &ifr, SIOCGMIIPHY) == 0) {
892891
mii->reg_num = MII_BMSR;
893-
if (ioctl(slave_dev, &ifr, SIOCGMIIREG) == 0)
892+
if (dev_eth_ioctl(slave_dev, &ifr, SIOCGMIIREG) == 0)
894893
return mii->val_out & BMSR_LSTATUS;
895894
}
896895
}

include/linux/netdevice.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4229,6 +4229,8 @@ int put_user_ifreq(struct ifreq *ifr, void __user *arg);
42294229
int dev_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr,
42304230
void __user *data, bool *need_copyout);
42314231
int dev_ifconf(struct net *net, struct ifconf __user *ifc);
4232+
int dev_eth_ioctl(struct net_device *dev,
4233+
struct ifreq *ifr, unsigned int cmd);
42324234
int generic_hwtstamp_get_lower(struct net_device *dev,
42334235
struct kernel_hwtstamp_config *kernel_cfg);
42344236
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,
42514253
int dev_change_net_namespace(struct net_device *dev, struct net *net,
42524254
const char *pat);
42534255
int __dev_set_mtu(struct net_device *, int);
4256+
int netif_set_mtu(struct net_device *dev, int new_mtu);
42544257
int dev_set_mtu(struct net_device *, int);
42554258
int dev_pre_changeaddr_notify(struct net_device *dev, const char *addr,
42564259
struct netlink_ext_ack *extack);

net/8021q/vlan_dev.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,6 @@ static int vlan_hwtstamp_set(struct net_device *dev,
377377
static int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
378378
{
379379
struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
380-
const struct net_device_ops *ops = real_dev->netdev_ops;
381380
struct ifreq ifrr;
382381
int err = -EOPNOTSUPP;
383382

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

net/core/dev.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9522,7 +9522,7 @@ int netif_set_mtu_ext(struct net_device *dev, int new_mtu,
95229522
return err;
95239523
}
95249524

9525-
int dev_set_mtu(struct net_device *dev, int new_mtu)
9525+
int netif_set_mtu(struct net_device *dev, int new_mtu)
95269526
{
95279527
struct netlink_ext_ack extack;
95289528
int err;
@@ -9533,7 +9533,7 @@ int dev_set_mtu(struct net_device *dev, int new_mtu)
95339533
net_err_ratelimited("%s: %s\n", dev->name, extack._msg);
95349534
return err;
95359535
}
9536-
EXPORT_SYMBOL(dev_set_mtu);
9536+
EXPORT_SYMBOL(netif_set_mtu);
95379537

95389538
int netif_change_tx_queue_len(struct net_device *dev, unsigned long new_len)
95399539
{

net/core/dev_api.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,3 +222,33 @@ void dev_close(struct net_device *dev)
222222
netdev_unlock_ops(dev);
223223
}
224224
EXPORT_SYMBOL(dev_close);
225+
226+
int dev_eth_ioctl(struct net_device *dev,
227+
struct ifreq *ifr, unsigned int cmd)
228+
{
229+
const struct net_device_ops *ops = dev->netdev_ops;
230+
int ret = -ENODEV;
231+
232+
if (!ops->ndo_eth_ioctl)
233+
return -EOPNOTSUPP;
234+
235+
netdev_lock_ops(dev);
236+
if (netif_device_present(dev))
237+
ret = ops->ndo_eth_ioctl(dev, ifr, cmd);
238+
netdev_unlock_ops(dev);
239+
240+
return ret;
241+
}
242+
EXPORT_SYMBOL(dev_eth_ioctl);
243+
244+
int dev_set_mtu(struct net_device *dev, int new_mtu)
245+
{
246+
int ret;
247+
248+
netdev_lock_ops(dev);
249+
ret = netif_set_mtu(dev, new_mtu);
250+
netdev_unlock_ops(dev);
251+
252+
return ret;
253+
}
254+
EXPORT_SYMBOL(dev_set_mtu);

net/core/dev_ioctl.c

Lines changed: 40 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ static int dev_getifmap(struct net_device *dev, struct ifreq *ifr)
110110
return 0;
111111
}
112112

113-
static int dev_setifmap(struct net_device *dev, struct ifreq *ifr)
113+
static int netif_setifmap(struct net_device *dev, struct ifreq *ifr)
114114
{
115115
struct compat_ifmap *cifmap = (struct compat_ifmap *)&ifr->ifr_map;
116116

@@ -240,20 +240,6 @@ int net_hwtstamp_validate(const struct kernel_hwtstamp_config *cfg)
240240
return 0;
241241
}
242242

243-
static int dev_eth_ioctl(struct net_device *dev,
244-
struct ifreq *ifr, unsigned int cmd)
245-
{
246-
const struct net_device_ops *ops = dev->netdev_ops;
247-
248-
if (!ops->ndo_eth_ioctl)
249-
return -EOPNOTSUPP;
250-
251-
if (!netif_device_present(dev))
252-
return -ENODEV;
253-
254-
return ops->ndo_eth_ioctl(dev, ifr, cmd);
255-
}
256-
257243
/**
258244
* dev_get_hwtstamp_phylib() - Get hardware timestamping settings of NIC
259245
* or of attached phylib PHY
@@ -305,7 +291,9 @@ static int dev_get_hwtstamp(struct net_device *dev, struct ifreq *ifr)
305291
return -ENODEV;
306292

307293
kernel_cfg.ifr = ifr;
294+
netdev_lock_ops(dev);
308295
err = dev_get_hwtstamp_phylib(dev, &kernel_cfg);
296+
netdev_unlock_ops(dev);
309297
if (err)
310298
return err;
311299

@@ -429,7 +417,9 @@ static int dev_set_hwtstamp(struct net_device *dev, struct ifreq *ifr)
429417
if (!netif_device_present(dev))
430418
return -ENODEV;
431419

420+
netdev_lock_ops(dev);
432421
err = dev_set_hwtstamp_phylib(dev, &kernel_cfg, &extack);
422+
netdev_unlock_ops(dev);
433423
if (err)
434424
return err;
435425

@@ -504,10 +494,14 @@ static int dev_siocbond(struct net_device *dev,
504494
const struct net_device_ops *ops = dev->netdev_ops;
505495

506496
if (ops->ndo_siocbond) {
497+
int ret = -ENODEV;
498+
499+
netdev_lock_ops(dev);
507500
if (netif_device_present(dev))
508-
return ops->ndo_siocbond(dev, ifr, cmd);
509-
else
510-
return -ENODEV;
501+
ret = ops->ndo_siocbond(dev, ifr, cmd);
502+
netdev_unlock_ops(dev);
503+
504+
return ret;
511505
}
512506

513507
return -EOPNOTSUPP;
@@ -519,10 +513,14 @@ static int dev_siocdevprivate(struct net_device *dev, struct ifreq *ifr,
519513
const struct net_device_ops *ops = dev->netdev_ops;
520514

521515
if (ops->ndo_siocdevprivate) {
516+
int ret = -ENODEV;
517+
518+
netdev_lock_ops(dev);
522519
if (netif_device_present(dev))
523-
return ops->ndo_siocdevprivate(dev, ifr, data, cmd);
524-
else
525-
return -ENODEV;
520+
ret = ops->ndo_siocdevprivate(dev, ifr, data, cmd);
521+
netdev_unlock_ops(dev);
522+
523+
return ret;
526524
}
527525

528526
return -EOPNOTSUPP;
@@ -533,10 +531,14 @@ static int dev_siocwandev(struct net_device *dev, struct if_settings *ifs)
533531
const struct net_device_ops *ops = dev->netdev_ops;
534532

535533
if (ops->ndo_siocwandev) {
534+
int ret = -ENODEV;
535+
536+
netdev_lock_ops(dev);
536537
if (netif_device_present(dev))
537-
return ops->ndo_siocwandev(dev, ifs);
538-
else
539-
return -ENODEV;
538+
ret = ops->ndo_siocwandev(dev, ifs);
539+
netdev_unlock_ops(dev);
540+
541+
return ret;
540542
}
541543

542544
return -EOPNOTSUPP;
@@ -580,27 +582,38 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, void __user *data,
580582
memcpy(dev->broadcast, ifr->ifr_hwaddr.sa_data,
581583
min(sizeof(ifr->ifr_hwaddr.sa_data_min),
582584
(size_t)dev->addr_len));
585+
netdev_lock_ops(dev);
583586
call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
587+
netdev_unlock_ops(dev);
584588
return 0;
585589

586590
case SIOCSIFMAP:
587-
return dev_setifmap(dev, ifr);
591+
netdev_lock_ops(dev);
592+
err = netif_setifmap(dev, ifr);
593+
netdev_unlock_ops(dev);
594+
return err;
588595

589596
case SIOCADDMULTI:
590597
if (!ops->ndo_set_rx_mode ||
591598
ifr->ifr_hwaddr.sa_family != AF_UNSPEC)
592599
return -EINVAL;
593600
if (!netif_device_present(dev))
594601
return -ENODEV;
595-
return dev_mc_add_global(dev, ifr->ifr_hwaddr.sa_data);
602+
netdev_lock_ops(dev);
603+
err = dev_mc_add_global(dev, ifr->ifr_hwaddr.sa_data);
604+
netdev_unlock_ops(dev);
605+
return err;
596606

597607
case SIOCDELMULTI:
598608
if (!ops->ndo_set_rx_mode ||
599609
ifr->ifr_hwaddr.sa_family != AF_UNSPEC)
600610
return -EINVAL;
601611
if (!netif_device_present(dev))
602612
return -ENODEV;
603-
return dev_mc_del_global(dev, ifr->ifr_hwaddr.sa_data);
613+
netdev_lock_ops(dev);
614+
err = dev_mc_del_global(dev, ifr->ifr_hwaddr.sa_data);
615+
netdev_unlock_ops(dev);
616+
return err;
604617

605618
case SIOCSIFTXQLEN:
606619
if (ifr->ifr_qlen < 0)

0 commit comments

Comments
 (0)