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). Fixes: 04600794958f ("cfg80211: support sysfs namespaces") Suggested-by: Kuniyuki Iwashima <kuniyu@xxxxxxxxxx> Signed-off-by: Ivan Abramov <i.abramov@xxxxxxxxxxxxxxxxx> --- net/wireless/core.c | 47 +++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/net/wireless/core.c b/net/wireless/core.c index 9e6b31903121..e4d353ec9436 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -169,27 +169,17 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev, wdev->netdev->netns_immutable = true; } - if (err) { - /* failed -- clean up to old netns */ - net = wiphy_net(&rdev->wiphy); - - list_for_each_entry_continue_reverse(wdev, - &rdev->wiphy.wdev_list, - list) { - if (!wdev->netdev) - continue; - wdev->netdev->netns_immutable = false; - err = dev_change_net_namespace(wdev->netdev, net, - "wlan%d"); - WARN_ON(err); - wdev->netdev->netns_immutable = true; - } - - return err; - } + if (err) + goto errout; guard(wiphy)(&rdev->wiphy); + err = device_rename(&rdev->wiphy.dev, dev_name(&rdev->wiphy.dev)); + WARN_ON(err); + + if (err) + goto errout; + list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) { if (!wdev->netdev) continue; @@ -200,9 +190,6 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev, wiphy_net_set(&rdev->wiphy, net); - err = device_rename(&rdev->wiphy.dev, dev_name(&rdev->wiphy.dev)); - WARN_ON(err); - nl80211_notify_wiphy(rdev, NL80211_CMD_NEW_WIPHY); list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) { @@ -212,6 +199,24 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev, } return 0; + +errout: + /* failed -- clean up to old netns */ + net = wiphy_net(&rdev->wiphy); + + list_for_each_entry_continue_reverse(wdev, + &rdev->wiphy.wdev_list, + list) { + if (!wdev->netdev) + continue; + wdev->netdev->netns_immutable = false; + err = dev_change_net_namespace(wdev->netdev, net, + "wlan%d"); + WARN_ON(err); + wdev->netdev->netns_immutable = true; + } + + return err; } static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data) -- 2.39.5