Skip to content

Commit a0b63c6

Browse files
q2venPaolo Abeni
authored andcommitted
rtnetlink: Call rtnl_link_get_net_capable() in do_setlink().
We will push RTNL down to rtnl_setlink(). RTM_SETLINK could call rtnl_link_get_net_capable() in do_setlink() to move a dev to a new netns, but the netns needs to be fetched before holding rtnl_net_lock(). Let's move it to rtnl_setlink() and pass the netns to do_setlink(). Now, RTM_NEWLINK paths (rtnl_changelink() and rtnl_group_changelink()) can pass the prefetched netns to do_setlink(). Signed-off-by: Kuniyuki Iwashima <[email protected]> Signed-off-by: Paolo Abeni <[email protected]>
1 parent 6e495fa commit a0b63c6

File tree

1 file changed

+16
-16
lines changed

1 file changed

+16
-16
lines changed

net/core/rtnetlink.c

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2881,8 +2881,8 @@ static int do_set_proto_down(struct net_device *dev,
28812881
#define DO_SETLINK_MODIFIED 0x01
28822882
/* notify flag means notify + modified. */
28832883
#define DO_SETLINK_NOTIFY 0x03
2884-
static int do_setlink(const struct sk_buff *skb,
2885-
struct net_device *dev, struct ifinfomsg *ifm,
2884+
static int do_setlink(const struct sk_buff *skb, struct net_device *dev,
2885+
struct net *tgt_net, struct ifinfomsg *ifm,
28862886
struct netlink_ext_ack *extack,
28872887
struct nlattr **tb, int status)
28882888
{
@@ -2899,27 +2899,19 @@ static int do_setlink(const struct sk_buff *skb,
28992899
else
29002900
ifname[0] = '\0';
29012901

2902-
if (tb[IFLA_NET_NS_PID] || tb[IFLA_NET_NS_FD] || tb[IFLA_TARGET_NETNSID]) {
2902+
if (!net_eq(tgt_net, dev_net(dev))) {
29032903
const char *pat = ifname[0] ? ifname : NULL;
2904-
struct net *net;
29052904
int new_ifindex;
29062905

2907-
net = rtnl_link_get_net_capable(skb, dev_net(dev),
2908-
tb, CAP_NET_ADMIN);
2909-
if (IS_ERR(net)) {
2910-
err = PTR_ERR(net);
2911-
goto errout;
2912-
}
2913-
29142906
if (tb[IFLA_NEW_IFINDEX])
29152907
new_ifindex = nla_get_s32(tb[IFLA_NEW_IFINDEX]);
29162908
else
29172909
new_ifindex = 0;
29182910

2919-
err = __dev_change_net_namespace(dev, net, pat, new_ifindex);
2920-
put_net(net);
2911+
err = __dev_change_net_namespace(dev, tgt_net, pat, new_ifindex);
29212912
if (err)
29222913
goto errout;
2914+
29232915
status |= DO_SETLINK_MODIFIED;
29242916
}
29252917

@@ -3283,6 +3275,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
32833275
struct net *net = sock_net(skb->sk);
32843276
struct nlattr *tb[IFLA_MAX+1];
32853277
struct net_device *dev = NULL;
3278+
struct net *tgt_net;
32863279
int err;
32873280

32883281
err = nlmsg_parse_deprecated(nlh, sizeof(*ifm), tb, IFLA_MAX,
@@ -3294,6 +3287,12 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
32943287
if (err < 0)
32953288
goto errout;
32963289

3290+
tgt_net = rtnl_link_get_net_capable(skb, net, tb, CAP_NET_ADMIN);
3291+
if (IS_ERR(tgt_net)) {
3292+
err = PTR_ERR(tgt_net);
3293+
goto errout;
3294+
}
3295+
32973296
if (ifm->ifi_index > 0)
32983297
dev = __dev_get_by_index(net, ifm->ifi_index);
32993298
else if (tb[IFLA_IFNAME] || tb[IFLA_ALT_IFNAME])
@@ -3302,10 +3301,11 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
33023301
err = -EINVAL;
33033302

33043303
if (dev)
3305-
err = do_setlink(skb, dev, ifm, extack, tb, 0);
3304+
err = do_setlink(skb, dev, tgt_net, ifm, extack, tb, 0);
33063305
else if (!err)
33073306
err = -ENODEV;
33083307

3308+
put_net(tgt_net);
33093309
errout:
33103310
return err;
33113311
}
@@ -3599,7 +3599,7 @@ static int rtnl_changelink(const struct sk_buff *skb, struct nlmsghdr *nlh,
35993599
status |= DO_SETLINK_NOTIFY;
36003600
}
36013601

3602-
return do_setlink(skb, dev, nlmsg_data(nlh), extack, tb, status);
3602+
return do_setlink(skb, dev, tgt_net, nlmsg_data(nlh), extack, tb, status);
36033603
}
36043604

36053605
static int rtnl_group_changelink(const struct sk_buff *skb,
@@ -3613,7 +3613,7 @@ static int rtnl_group_changelink(const struct sk_buff *skb,
36133613

36143614
for_each_netdev_safe(net, dev, aux) {
36153615
if (dev->group == group) {
3616-
err = do_setlink(skb, dev, ifm, extack, tb, 0);
3616+
err = do_setlink(skb, dev, tgt_net, ifm, extack, tb, 0);
36173617
if (err < 0)
36183618
return err;
36193619
}

0 commit comments

Comments
 (0)