netkit_fill_info() used rtnl_dereference() to fetch nk->peer, and thus required RTNL. nk->peer is already an RCU protected pointer, updated with rcu_assign_pointer() and read from the fast path with rcu_dereference(). Simply use rcu_dereference() under rcu_read_lock() instead. While at it, use READ_ONCE() when reading nk->policy, because netkit_change_link() can change it at any time (it already uses WRITE_ONCE()). Other fields (primary, mode, pair, scrub) are only set from netkit_new_link(), before the device is visible to dumps. Also add missing const qualifiers. Signed-off-by: Eric Dumazet --- Cc: Daniel Borkmann Cc: Nikolay Aleksandrov --- drivers/net/netkit.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/net/netkit.c b/drivers/net/netkit.c index a3931cd821321c3e4888edf86efc414199127bcf..82e608e733d9ee70f71c374570211c73da76ae2c 100644 --- a/drivers/net/netkit.c +++ b/drivers/net/netkit.c @@ -1209,12 +1209,12 @@ static size_t netkit_get_size(const struct net_device *dev) static int netkit_fill_info(struct sk_buff *skb, const struct net_device *dev) { - struct netkit *nk = netkit_priv(dev); - struct net_device *peer = rtnl_dereference(nk->peer); + const struct netkit *nk = netkit_priv(dev); + const struct net_device *peer; if (nla_put_u8(skb, IFLA_NETKIT_PRIMARY, nk->primary)) return -EMSGSIZE; - if (nla_put_u32(skb, IFLA_NETKIT_POLICY, nk->policy)) + if (nla_put_u32(skb, IFLA_NETKIT_POLICY, READ_ONCE(nk->policy))) return -EMSGSIZE; if (nla_put_u32(skb, IFLA_NETKIT_MODE, nk->mode)) return -EMSGSIZE; @@ -1228,13 +1228,18 @@ static int netkit_fill_info(struct sk_buff *skb, const struct net_device *dev) if (nla_put_u32(skb, IFLA_NETKIT_PAIRING, nk->pair)) return -EMSGSIZE; + rcu_read_lock(); + peer = rcu_dereference(nk->peer); if (peer) { nk = netkit_priv(peer); - if (nla_put_u32(skb, IFLA_NETKIT_PEER_POLICY, nk->policy)) - return -EMSGSIZE; - if (nla_put_u32(skb, IFLA_NETKIT_PEER_SCRUB, nk->scrub)) + if (nla_put_u32(skb, IFLA_NETKIT_PEER_POLICY, + READ_ONCE(nk->policy)) || + nla_put_u32(skb, IFLA_NETKIT_PEER_SCRUB, nk->scrub)) { + rcu_read_unlock(); return -EMSGSIZE; + } } + rcu_read_unlock(); return 0; } -- 2.55.0.1032.g73a4cd73de-goog