When creating link, lookup for existing device in target net namespace
instead of current one.
For example, two links created by:

  # ip link add dummy1 type dummy
  # ip link add netns ns1 dummy1 type dummy

should have no conflict since they are in different namespaces.

Signed-off-by: Xiao Liang <shaw.l...@gmail.com>
---
 net/core/rtnetlink.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 3b33810d92a8..8119f4ad9e5f 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -3744,20 +3744,26 @@ static int __rtnl_newlink(struct sk_buff *skb, struct 
nlmsghdr *nlh,
 {
        struct nlattr ** const tb = tbs->tb;
        struct net *net = sock_net(skb->sk);
+       struct net *device_net;
        struct net_device *dev;
        struct ifinfomsg *ifm;
        bool link_specified;
 
+       /* When creating, lookup for existing device in target net namespace */
+       device_net = (nlh->nlmsg_flags & NLM_F_CREATE) &&
+                    (nlh->nlmsg_flags & NLM_F_EXCL) ?
+                    tgt_net : net;
+
        ifm = nlmsg_data(nlh);
        if (ifm->ifi_index > 0) {
                link_specified = true;
-               dev = __dev_get_by_index(net, ifm->ifi_index);
+               dev = __dev_get_by_index(device_net, ifm->ifi_index);
        } else if (ifm->ifi_index < 0) {
                NL_SET_ERR_MSG(extack, "ifindex can't be negative");
                return -EINVAL;
        } else if (tb[IFLA_IFNAME] || tb[IFLA_ALT_IFNAME]) {
                link_specified = true;
-               dev = rtnl_dev_get(net, tb);
+               dev = rtnl_dev_get(device_net, tb);
        } else {
                link_specified = false;
                dev = NULL;
-- 
2.47.0


Reply via email to