We can use rcu here to make this safe even if we would not hold rtnl,
qdisc_destroy uses call_rcu to delay free of the qdisc for one grace period.

Signed-off-by: Florian Westphal <f...@strlen.de>
---
 net/core/rtnetlink.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index c801212ee40e..ad3f27da37a8 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1332,6 +1332,19 @@ static int nla_put_iflink(struct sk_buff *skb, const 
struct net_device *dev)
        return nla_put_u32(skb, IFLA_LINK, ifindex);
 }
 
+static int nla_put_qdisc(struct sk_buff *skb, struct net_device *dev)
+{
+       struct Qdisc *q;
+       int ret = 0;
+
+       rcu_read_lock();
+       q = READ_ONCE(dev->qdisc);
+       if (q)
+               ret = nla_put_string(skb, IFLA_QDISC, q->ops->id);
+       rcu_read_unlock();
+       return ret;
+}
+
 static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
                            int type, u32 pid, u32 seq, u32 change,
                            unsigned int flags, u32 ext_filter_mask,
@@ -1372,8 +1385,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct 
net_device *dev,
            nla_put_iflink(skb, dev) ||
            put_master_ifindex(skb, dev) ||
            nla_put_u8(skb, IFLA_CARRIER, netif_carrier_ok(dev)) ||
-           (dev->qdisc &&
-            nla_put_string(skb, IFLA_QDISC, dev->qdisc->ops->id)) ||
+           nla_put_qdisc(skb, dev) ||
            (dev->ifalias &&
             nla_put_string(skb, IFLA_IFALIAS, dev->ifalias)) ||
            nla_put_u32(skb, IFLA_CARRIER_CHANGES,
-- 
2.13.5

Reply via email to