diff options
author | Sven Eckelmann <sven.eckelmann@gmx.de> | 2010-08-21 14:18:09 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-08-26 16:46:22 -0700 |
commit | b6c68ad83cbc3bcf4ff83f62340fbf891f44735c (patch) | |
tree | e36251aec832144867d4cbe2bde22d5cc15e059c | |
parent | 6e5cab8eac427fd754cc70aba0906228277cdea2 (diff) |
Staging: batman-adv: Don't use net_dev after dev_put
commit 51a00eaf6e008b60943af6ab68c17ac3622208dc upstream.
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: Tim Glaremin <Tim.Glaremin@web.de>
Signed-off-by: Sven Eckelmann <sven.eckelmann@gmx.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/staging/batman-adv/hard-interface.c | 11 |
1 files changed, 6 insertions, 5 deletions
diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c index 92997327ae9f..d108fa1eb733 100644 --- a/drivers/staging/batman-adv/hard-interface.c +++ b/drivers/staging/batman-adv/hard-interface.c @@ -194,8 +194,6 @@ static void hardif_activate_interface(struct bat_priv *bat_priv, if (batman_if->if_status != IF_INACTIVE) return; - dev_hold(batman_if->net_dev); - update_mac_addresses(batman_if); batman_if->if_status = IF_TO_BE_ACTIVATED; @@ -222,8 +220,6 @@ static void hardif_deactivate_interface(struct batman_if *batman_if) (batman_if->if_status != IF_TO_BE_ACTIVATED)) return; - dev_put(batman_if->net_dev); - batman_if->if_status = IF_INACTIVE; printk(KERN_INFO "batman-adv:Interface deactivated: %s\n", @@ -321,12 +317,14 @@ static struct batman_if *hardif_add_interface(struct net_device *net_dev) if (ret != 1) goto out; + dev_hold(net_dev); + batman_if = kmalloc(sizeof(struct batman_if), GFP_ATOMIC); if (!batman_if) { printk(KERN_ERR "batman-adv:" "Can't add interface (%s): out of memory\n", net_dev->name); - goto out; + goto release_dev; } batman_if->dev = kstrdup(net_dev->name, GFP_ATOMIC); @@ -350,6 +348,8 @@ free_dev: kfree(batman_if->dev); free_if: kfree(batman_if); +release_dev: + dev_put(net_dev); out: return NULL; } @@ -378,6 +378,7 @@ static void hardif_remove_interface(struct batman_if *batman_if) batman_if->if_status = IF_TO_BE_REMOVED; list_del_rcu(&batman_if->list); sysfs_del_hardif(&batman_if->hardif_obj); + dev_put(batman_if->net_dev); call_rcu(&batman_if->rcu, hardif_free_interface); } |