Merge tag 'mtd/fixes-for-6.6-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git...
[platform/kernel/linux-starfive.git] / net / core / dev.c
index 85df22f..9f3f893 100644 (file)
@@ -345,7 +345,6 @@ int netdev_name_node_alt_create(struct net_device *dev, const char *name)
 static void __netdev_name_node_alt_destroy(struct netdev_name_node *name_node)
 {
        list_del(&name_node->list);
-       netdev_name_node_del(name_node);
        kfree(name_node->name);
        netdev_name_node_free(name_node);
 }
@@ -364,6 +363,8 @@ int netdev_name_node_alt_destroy(struct net_device *dev, const char *name)
        if (name_node == dev->name_node || name_node->dev != dev)
                return -EINVAL;
 
+       netdev_name_node_del(name_node);
+       synchronize_rcu();
        __netdev_name_node_alt_destroy(name_node);
 
        return 0;
@@ -380,6 +381,7 @@ static void netdev_name_node_alt_flush(struct net_device *dev)
 /* Device list insertion */
 static void list_netdevice(struct net_device *dev)
 {
+       struct netdev_name_node *name_node;
        struct net *net = dev_net(dev);
 
        ASSERT_RTNL();
@@ -390,6 +392,10 @@ static void list_netdevice(struct net_device *dev)
        hlist_add_head_rcu(&dev->index_hlist,
                           dev_index_hash(net, dev->ifindex));
        write_unlock(&dev_base_lock);
+
+       netdev_for_each_altname(dev, name_node)
+               netdev_name_node_add(net, name_node);
+
        /* We reserved the ifindex, this can't fail */
        WARN_ON(xa_store(&net->dev_by_index, dev->ifindex, dev, GFP_KERNEL));
 
@@ -401,12 +407,16 @@ static void list_netdevice(struct net_device *dev)
  */
 static void unlist_netdevice(struct net_device *dev, bool lock)
 {
+       struct netdev_name_node *name_node;
        struct net *net = dev_net(dev);
 
        ASSERT_RTNL();
 
        xa_erase(&net->dev_by_index, dev->ifindex);
 
+       netdev_for_each_altname(dev, name_node)
+               netdev_name_node_del(name_node);
+
        /* Unlink dev from the device chain */
        if (lock)
                write_lock(&dev_base_lock);
@@ -1086,7 +1096,8 @@ static int __dev_alloc_name(struct net *net, const char *name, char *buf)
 
                for_each_netdev(net, d) {
                        struct netdev_name_node *name_node;
-                       list_for_each_entry(name_node, &d->name_node->list, list) {
+
+                       netdev_for_each_altname(d, name_node) {
                                if (!sscanf(name_node->name, name, &i))
                                        continue;
                                if (i < 0 || i >= max_netdevices)
@@ -1123,6 +1134,26 @@ static int __dev_alloc_name(struct net *net, const char *name, char *buf)
        return -ENFILE;
 }
 
+static int dev_prep_valid_name(struct net *net, struct net_device *dev,
+                              const char *want_name, char *out_name)
+{
+       int ret;
+
+       if (!dev_valid_name(want_name))
+               return -EINVAL;
+
+       if (strchr(want_name, '%')) {
+               ret = __dev_alloc_name(net, want_name, out_name);
+               return ret < 0 ? ret : 0;
+       } else if (netdev_name_in_use(net, want_name)) {
+               return -EEXIST;
+       } else if (out_name != want_name) {
+               strscpy(out_name, want_name, IFNAMSIZ);
+       }
+
+       return 0;
+}
+
 static int dev_alloc_name_ns(struct net *net,
                             struct net_device *dev,
                             const char *name)
@@ -1160,19 +1191,13 @@ EXPORT_SYMBOL(dev_alloc_name);
 static int dev_get_valid_name(struct net *net, struct net_device *dev,
                              const char *name)
 {
-       BUG_ON(!net);
-
-       if (!dev_valid_name(name))
-               return -EINVAL;
-
-       if (strchr(name, '%'))
-               return dev_alloc_name_ns(net, dev, name);
-       else if (netdev_name_in_use(net, name))
-               return -EEXIST;
-       else if (dev->name != name)
-               strscpy(dev->name, name, IFNAMSIZ);
+       char buf[IFNAMSIZ];
+       int ret;
 
-       return 0;
+       ret = dev_prep_valid_name(net, dev, name, buf);
+       if (ret >= 0)
+               strscpy(dev->name, buf, IFNAMSIZ);
+       return ret;
 }
 
 /**
@@ -3292,15 +3317,19 @@ int skb_checksum_help(struct sk_buff *skb)
 
        offset = skb_checksum_start_offset(skb);
        ret = -EINVAL;
-       if (WARN_ON_ONCE(offset >= skb_headlen(skb))) {
+       if (unlikely(offset >= skb_headlen(skb))) {
                DO_ONCE_LITE(skb_dump, KERN_ERR, skb, false);
+               WARN_ONCE(true, "offset (%d) >= skb_headlen() (%u)\n",
+                         offset, skb_headlen(skb));
                goto out;
        }
        csum = skb_checksum(skb, offset, skb->len - offset, 0);
 
        offset += skb->csum_offset;
-       if (WARN_ON_ONCE(offset + sizeof(__sum16) > skb_headlen(skb))) {
+       if (unlikely(offset + sizeof(__sum16) > skb_headlen(skb))) {
                DO_ONCE_LITE(skb_dump, KERN_ERR, skb, false);
+               WARN_ONCE(true, "offset+2 (%zu) > skb_headlen() (%u)\n",
+                         offset + sizeof(__sum16), skb_headlen(skb));
                goto out;
        }
        ret = skb_ensure_writable(skb, offset + sizeof(__sum16));
@@ -11033,7 +11062,9 @@ EXPORT_SYMBOL(unregister_netdev);
 int __dev_change_net_namespace(struct net_device *dev, struct net *net,
                               const char *pat, int new_ifindex)
 {
+       struct netdev_name_node *name_node;
        struct net *net_old = dev_net(dev);
+       char new_name[IFNAMSIZ] = {};
        int err, new_nsid;
 
        ASSERT_RTNL();
@@ -11060,10 +11091,15 @@ int __dev_change_net_namespace(struct net_device *dev, struct net *net,
                /* We get here if we can't use the current device name */
                if (!pat)
                        goto out;
-               err = dev_get_valid_name(net, dev, pat);
+               err = dev_prep_valid_name(net, dev, pat, new_name);
                if (err < 0)
                        goto out;
        }
+       /* Check that none of the altnames conflicts. */
+       err = -EEXIST;
+       netdev_for_each_altname(dev, name_node)
+               if (netdev_name_in_use(net, name_node->name))
+                       goto out;
 
        /* Check that new_ifindex isn't used yet. */
        if (new_ifindex) {
@@ -11131,6 +11167,9 @@ int __dev_change_net_namespace(struct net_device *dev, struct net *net,
        kobject_uevent(&dev->dev.kobj, KOBJ_ADD);
        netdev_adjacent_add_links(dev);
 
+       if (new_name[0]) /* Rename the netdev to prepared name */
+               strscpy(dev->name, new_name, IFNAMSIZ);
+
        /* Fixup kobjects */
        err = device_rename(&dev->dev, dev->name);
        WARN_ON(err);