Commit 51a00eaf authored by Sven Eckelmann's avatar Sven Eckelmann Committed by Greg Kroah-Hartman

Staging: batman-adv: Don't use net_dev after dev_put

dev_put allows a device to be freed when all its references are dropped.
After that we are not allowed to access that information anymore. Access
to the data structure of a net_device must be surrounded a dev_hold
and ended using dev_put.

batman-adv adds a device to its own management structure in
hardif_add_interface and will release it in hardif_remove_interface.
Thus it must hold a reference all the time between those functions to
prevent any access to the already released net_device structure.
Reported-by: default avatarTim Glaremin <Tim.Glaremin@web.de>
Signed-off-by: default avatarSven Eckelmann <sven.eckelmann@gmx.de>
Cc: stable <stable@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 1189f130
...@@ -194,8 +194,6 @@ static void hardif_activate_interface(struct net_device *net_dev, ...@@ -194,8 +194,6 @@ static void hardif_activate_interface(struct net_device *net_dev,
if (batman_if->if_status != IF_INACTIVE) if (batman_if->if_status != IF_INACTIVE)
return; return;
dev_hold(batman_if->net_dev);
update_mac_addresses(batman_if); update_mac_addresses(batman_if);
batman_if->if_status = IF_TO_BE_ACTIVATED; batman_if->if_status = IF_TO_BE_ACTIVATED;
...@@ -222,8 +220,6 @@ static void hardif_deactivate_interface(struct net_device *net_dev, ...@@ -222,8 +220,6 @@ static void hardif_deactivate_interface(struct net_device *net_dev,
(batman_if->if_status != IF_TO_BE_ACTIVATED)) (batman_if->if_status != IF_TO_BE_ACTIVATED))
return; return;
dev_put(batman_if->net_dev);
batman_if->if_status = IF_INACTIVE; batman_if->if_status = IF_INACTIVE;
bat_info(net_dev, "Interface deactivated: %s\n", batman_if->dev); bat_info(net_dev, "Interface deactivated: %s\n", batman_if->dev);
...@@ -318,11 +314,13 @@ static struct batman_if *hardif_add_interface(struct net_device *net_dev) ...@@ -318,11 +314,13 @@ static struct batman_if *hardif_add_interface(struct net_device *net_dev)
if (ret != 1) if (ret != 1)
goto out; goto out;
dev_hold(net_dev);
batman_if = kmalloc(sizeof(struct batman_if), GFP_ATOMIC); batman_if = kmalloc(sizeof(struct batman_if), GFP_ATOMIC);
if (!batman_if) { if (!batman_if) {
pr_err("Can't add interface (%s): out of memory\n", pr_err("Can't add interface (%s): out of memory\n",
net_dev->name); net_dev->name);
goto out; goto release_dev;
} }
batman_if->dev = kstrdup(net_dev->name, GFP_ATOMIC); batman_if->dev = kstrdup(net_dev->name, GFP_ATOMIC);
...@@ -346,6 +344,8 @@ static struct batman_if *hardif_add_interface(struct net_device *net_dev) ...@@ -346,6 +344,8 @@ static struct batman_if *hardif_add_interface(struct net_device *net_dev)
kfree(batman_if->dev); kfree(batman_if->dev);
free_if: free_if:
kfree(batman_if); kfree(batman_if);
release_dev:
dev_put(net_dev);
out: out:
return NULL; return NULL;
} }
...@@ -374,6 +374,7 @@ static void hardif_remove_interface(struct batman_if *batman_if) ...@@ -374,6 +374,7 @@ static void hardif_remove_interface(struct batman_if *batman_if)
batman_if->if_status = IF_TO_BE_REMOVED; batman_if->if_status = IF_TO_BE_REMOVED;
list_del_rcu(&batman_if->list); list_del_rcu(&batman_if->list);
sysfs_del_hardif(&batman_if->hardif_obj); sysfs_del_hardif(&batman_if->hardif_obj);
dev_put(batman_if->net_dev);
call_rcu(&batman_if->rcu, hardif_free_interface); call_rcu(&batman_if->rcu, hardif_free_interface);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment