Message ID | 20231013121029.353351-3-jiri@resnulli.us (mailing list archive) |
---|---|
State | Accepted |
Commit | c503bc7df602257e9d03851654a347649a33f3c3 |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | devlink: fix a deadlock when taking devlink instance lock while holding RTNL lock | expand |
On Fri, Oct 13, 2023 at 02:10:24PM +0200, Jiri Pirko wrote: > From: Jiri Pirko <jiri@nvidia.com> > > peernet2id_alloc() allows to be called lockless with peer net pointer > obtained in RCU critical section and makes sure to return ns ID if net > namespaces is not being removed concurrently. Benefit from > read_pnet_rcu() helper addition, use it to obtain net pointer under RCU > read lock and pass it to peernet2id_alloc() to get ns ID. > > Fixes: c137743bce02 ("devlink: introduce object and nested devlink relationship infra") > Signed-off-by: Jiri Pirko <jiri@nvidia.com> Reviewed-by: Simon Horman <horms@kernel.org>
diff --git a/net/devlink/netlink.c b/net/devlink/netlink.c index 499304d9de49..809bfc3ba8c4 100644 --- a/net/devlink/netlink.c +++ b/net/devlink/netlink.c @@ -86,18 +86,24 @@ int devlink_nl_put_nested_handle(struct sk_buff *msg, struct net *net, struct devlink *devlink, int attrtype) { struct nlattr *nested_attr; + struct net *devl_net; nested_attr = nla_nest_start(msg, attrtype); if (!nested_attr) return -EMSGSIZE; if (devlink_nl_put_handle(msg, devlink)) goto nla_put_failure; - if (!net_eq(net, devlink_net(devlink))) { - int id = peernet2id_alloc(net, devlink_net(devlink), - GFP_KERNEL); + rcu_read_lock(); + devl_net = read_pnet_rcu(&devlink->_net); + if (!net_eq(net, devl_net)) { + int id = peernet2id_alloc(net, devl_net, GFP_ATOMIC); + + rcu_read_unlock(); if (nla_put_s32(msg, DEVLINK_ATTR_NETNS_ID, id)) return -EMSGSIZE; + } else { + rcu_read_unlock(); } nla_nest_end(msg, nested_attr);