mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 21:39:35 -04:00
rtnetlink: Lock sock_net(skb->sk) in rtnl_newlink().
There are a few cases where rtnl_net_lock() is not properly held in rtnl_newlink(). When either of IFLA_NET_NS_PID / IFLA_NET_NS_FD / IFLA_TARGET_NETNSID is specified but IFLA_LINK_NETNSID is not, sock_net(skb->sk) is used as link_net in rtnl_newlink_link_net(). In addition, the do_setlink() path uses sock_net(skb->sk) and one from the three netns attributes while rtnl_link_get_net_capable() returns only one of four. Let's add sock_net(skb->sk) to rtnl_nets in rtnl_newlink(). Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> Link: https://patch.msgid.link/20260703001009.1572444-2-kuniyu@google.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
committed by
Paolo Abeni
parent
23dad2d088
commit
5ecbbb179e
@@ -282,10 +282,11 @@ static int rtnl_net_cmp_locks(const struct net *net_a, const struct net *net_b)
|
||||
#endif
|
||||
|
||||
struct rtnl_nets {
|
||||
/* ->newlink() needs to freeze 3 netns at most;
|
||||
* 2 for the new device, 1 for its peer.
|
||||
/* ->newlink() needs to freeze 4 netns at most;
|
||||
* 2 for the new device, 1 for its peer, 1 for
|
||||
* an existing device (do_setlink() path).
|
||||
*/
|
||||
struct net *net[3];
|
||||
struct net *net[4];
|
||||
unsigned char len;
|
||||
};
|
||||
|
||||
@@ -4158,6 +4159,8 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
}
|
||||
}
|
||||
|
||||
rtnl_nets_add(&rtnl_nets, get_net(sock_net(skb->sk)));
|
||||
|
||||
rtnl_nets_lock(&rtnl_nets);
|
||||
ret = __rtnl_newlink(skb, nlh, ops, tgt_net, link_net, peer_net, tbs, data, extack);
|
||||
rtnl_nets_unlock(&rtnl_nets);
|
||||
|
||||
Reference in New Issue
Block a user