Skip to content

Commit 5ff3fda

Browse files
committed
Merge branch 'net-sysfs-fix-race-conditions-in-the-xps-code'
Antoine Tenart says: ==================== net-sysfs: fix race conditions in the xps code This series fixes race conditions in the xps code, where out of bound accesses can occur when dev->num_tc is updated, triggering oops. The root cause is linked to locking issues. An explanation is given in each of the commit logs. We had a discussion on the v1 of this series about using the xps_map mutex instead of the rtnl lock. While that seemed a better compromise, v2 showed the added complexity wasn't best for fixes. So we decided to go back to v1 and use the rtnl lock. Because of this, the only differences between v1 and v3 are improvements in the commit messages. ==================== Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 59b4a8f + 4ae2bb8 commit 5ff3fda

File tree

1 file changed

+53
-12
lines changed

1 file changed

+53
-12
lines changed

net/core/net-sysfs.c

Lines changed: 53 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1317,8 +1317,8 @@ static const struct attribute_group dql_group = {
13171317
static ssize_t xps_cpus_show(struct netdev_queue *queue,
13181318
char *buf)
13191319
{
1320+
int cpu, len, ret, num_tc = 1, tc = 0;
13201321
struct net_device *dev = queue->dev;
1321-
int cpu, len, num_tc = 1, tc = 0;
13221322
struct xps_dev_maps *dev_maps;
13231323
cpumask_var_t mask;
13241324
unsigned long index;
@@ -1328,22 +1328,31 @@ static ssize_t xps_cpus_show(struct netdev_queue *queue,
13281328

13291329
index = get_netdev_queue_index(queue);
13301330

1331+
if (!rtnl_trylock())
1332+
return restart_syscall();
1333+
13311334
if (dev->num_tc) {
13321335
/* Do not allow XPS on subordinate device directly */
13331336
num_tc = dev->num_tc;
1334-
if (num_tc < 0)
1335-
return -EINVAL;
1337+
if (num_tc < 0) {
1338+
ret = -EINVAL;
1339+
goto err_rtnl_unlock;
1340+
}
13361341

13371342
/* If queue belongs to subordinate dev use its map */
13381343
dev = netdev_get_tx_queue(dev, index)->sb_dev ? : dev;
13391344

13401345
tc = netdev_txq_to_tc(dev, index);
1341-
if (tc < 0)
1342-
return -EINVAL;
1346+
if (tc < 0) {
1347+
ret = -EINVAL;
1348+
goto err_rtnl_unlock;
1349+
}
13431350
}
13441351

1345-
if (!zalloc_cpumask_var(&mask, GFP_KERNEL))
1346-
return -ENOMEM;
1352+
if (!zalloc_cpumask_var(&mask, GFP_KERNEL)) {
1353+
ret = -ENOMEM;
1354+
goto err_rtnl_unlock;
1355+
}
13471356

13481357
rcu_read_lock();
13491358
dev_maps = rcu_dereference(dev->xps_cpus_map);
@@ -1366,9 +1375,15 @@ static ssize_t xps_cpus_show(struct netdev_queue *queue,
13661375
}
13671376
rcu_read_unlock();
13681377

1378+
rtnl_unlock();
1379+
13691380
len = snprintf(buf, PAGE_SIZE, "%*pb\n", cpumask_pr_args(mask));
13701381
free_cpumask_var(mask);
13711382
return len < PAGE_SIZE ? len : -EINVAL;
1383+
1384+
err_rtnl_unlock:
1385+
rtnl_unlock();
1386+
return ret;
13721387
}
13731388

13741389
static ssize_t xps_cpus_store(struct netdev_queue *queue,
@@ -1396,7 +1411,13 @@ static ssize_t xps_cpus_store(struct netdev_queue *queue,
13961411
return err;
13971412
}
13981413

1414+
if (!rtnl_trylock()) {
1415+
free_cpumask_var(mask);
1416+
return restart_syscall();
1417+
}
1418+
13991419
err = netif_set_xps_queue(dev, mask, index);
1420+
rtnl_unlock();
14001421

14011422
free_cpumask_var(mask);
14021423

@@ -1408,22 +1429,29 @@ static struct netdev_queue_attribute xps_cpus_attribute __ro_after_init
14081429

14091430
static ssize_t xps_rxqs_show(struct netdev_queue *queue, char *buf)
14101431
{
1432+
int j, len, ret, num_tc = 1, tc = 0;
14111433
struct net_device *dev = queue->dev;
14121434
struct xps_dev_maps *dev_maps;
14131435
unsigned long *mask, index;
1414-
int j, len, num_tc = 1, tc = 0;
14151436

14161437
index = get_netdev_queue_index(queue);
14171438

1439+
if (!rtnl_trylock())
1440+
return restart_syscall();
1441+
14181442
if (dev->num_tc) {
14191443
num_tc = dev->num_tc;
14201444
tc = netdev_txq_to_tc(dev, index);
1421-
if (tc < 0)
1422-
return -EINVAL;
1445+
if (tc < 0) {
1446+
ret = -EINVAL;
1447+
goto err_rtnl_unlock;
1448+
}
14231449
}
14241450
mask = bitmap_zalloc(dev->num_rx_queues, GFP_KERNEL);
1425-
if (!mask)
1426-
return -ENOMEM;
1451+
if (!mask) {
1452+
ret = -ENOMEM;
1453+
goto err_rtnl_unlock;
1454+
}
14271455

14281456
rcu_read_lock();
14291457
dev_maps = rcu_dereference(dev->xps_rxqs_map);
@@ -1449,10 +1477,16 @@ static ssize_t xps_rxqs_show(struct netdev_queue *queue, char *buf)
14491477
out_no_maps:
14501478
rcu_read_unlock();
14511479

1480+
rtnl_unlock();
1481+
14521482
len = bitmap_print_to_pagebuf(false, buf, mask, dev->num_rx_queues);
14531483
bitmap_free(mask);
14541484

14551485
return len < PAGE_SIZE ? len : -EINVAL;
1486+
1487+
err_rtnl_unlock:
1488+
rtnl_unlock();
1489+
return ret;
14561490
}
14571491

14581492
static ssize_t xps_rxqs_store(struct netdev_queue *queue, const char *buf,
@@ -1478,10 +1512,17 @@ static ssize_t xps_rxqs_store(struct netdev_queue *queue, const char *buf,
14781512
return err;
14791513
}
14801514

1515+
if (!rtnl_trylock()) {
1516+
bitmap_free(mask);
1517+
return restart_syscall();
1518+
}
1519+
14811520
cpus_read_lock();
14821521
err = __netif_set_xps_queue(dev, mask, index, true);
14831522
cpus_read_unlock();
14841523

1524+
rtnl_unlock();
1525+
14851526
bitmap_free(mask);
14861527
return err ? : len;
14871528
}

0 commit comments

Comments
 (0)