From: Alexander Duyck <alexanderdu...@fb.com>

In order to access the suboordinate dev for a device we should be holding
the rtnl_lock when outside of the transmit path. The existing code was not
doing that for the sysfs dump function and as a result we were open to a
possible race.

To resolve that take the rtnl lock prior to accessing the sb_dev field of
the Tx queue and release it after we have retrieved the tc for the queue.

Signed-off-by: Alexander Duyck <alexanderdu...@fb.com>
---
 net/core/net-sysfs.c |   13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index daf502c13d6d..91afb0b6de69 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -1136,18 +1136,25 @@ static ssize_t traffic_class_show(struct netdev_queue 
*queue,
                                  char *buf)
 {
        struct net_device *dev = queue->dev;
+       int num_tc, tc;
        int index;
-       int tc;
 
        if (!netif_is_multiqueue(dev))
                return -ENOENT;
 
+       if (!rtnl_trylock())
+               return restart_syscall();
+
        index = get_netdev_queue_index(queue);
 
        /* If queue belongs to subordinate dev use its TC mapping */
        dev = netdev_get_tx_queue(dev, index)->sb_dev ? : dev;
 
+       num_tc = dev->num_tc;
        tc = netdev_txq_to_tc(dev, index);
+
+       rtnl_unlock();
+
        if (tc < 0)
                return -EINVAL;
 
@@ -1158,8 +1165,8 @@ static ssize_t traffic_class_show(struct netdev_queue 
*queue,
         * belongs to the root device it will be reported with just the
         * traffic class, so just "0" for TC 0 for example.
         */
-       return dev->num_tc < 0 ? sprintf(buf, "%d%d\n", tc, dev->num_tc) :
-                                sprintf(buf, "%d\n", tc);
+       return num_tc < 0 ? sprintf(buf, "%d%d\n", tc, num_tc) :
+                           sprintf(buf, "%d\n", tc);
 }
 
 #ifdef CONFIG_XPS


Reply via email to