Currently, the return value of device_rename() is not acted upon.

To avoid an inconsistent state in case of failure, roll back the changes
made before the device_rename() call.

Found by Linux Verification Center (linuxtesting.org) with Syzkaller.

Fixes: 66e5c2672cd1 ("ieee802154: add netns support")
Signed-off-by: Ivan Abramov <i.abra...@mt-integration.ru>
---
 net/ieee802154/core.c | 45 ++++++++++++++++++++++++-------------------
 1 file changed, 25 insertions(+), 20 deletions(-)

diff --git a/net/ieee802154/core.c b/net/ieee802154/core.c
index 88adb04e4072..ddde594513a0 100644
--- a/net/ieee802154/core.c
+++ b/net/ieee802154/core.c
@@ -233,31 +233,36 @@ int cfg802154_switch_netns(struct 
cfg802154_registered_device *rdev,
                wpan_dev->netdev->netns_local = true;
        }
 
-       if (err) {
-               /* failed -- clean up to old netns */
-               net = wpan_phy_net(&rdev->wpan_phy);
-
-               list_for_each_entry_continue_reverse(wpan_dev,
-                                                    &rdev->wpan_dev_list,
-                                                    list) {
-                       if (!wpan_dev->netdev)
-                               continue;
-                       wpan_dev->netdev->netns_local = false;
-                       err = dev_change_net_namespace(wpan_dev->netdev, net,
-                                                      "wpan%d");
-                       WARN_ON(err);
-                       wpan_dev->netdev->netns_local = true;
-               }
-
-               return err;
-       }
-
-       wpan_phy_net_set(&rdev->wpan_phy, net);
+       if (err)
+               goto errout;
 
        err = device_rename(&rdev->wpan_phy.dev, dev_name(&rdev->wpan_phy.dev));
        WARN_ON(err);
 
+       if (err)
+               goto errout;
+
+       wpan_phy_net_set(&rdev->wpan_phy, net);
+
        return 0;
+
+errout:
+       /* failed -- clean up to old netns */
+       net = wpan_phy_net(&rdev->wpan_phy);
+
+       list_for_each_entry_continue_reverse(wpan_dev,
+                                            &rdev->wpan_dev_list,
+                                            list) {
+               if (!wpan_dev->netdev)
+                       continue;
+               wpan_dev->netdev->netns_local = false;
+               err = dev_change_net_namespace(wpan_dev->netdev, net,
+                                              "wpan%d");
+               WARN_ON(err);
+               wpan_dev->netdev->netns_local = true;
+       }
+
+       return err;
 }
 
 void cfg802154_dev_free(struct cfg802154_registered_device *rdev)
-- 
2.39.5


Reply via email to