diff options
author | Sven Eckelmann <sven.eckelmann@gmx.de> | 2010-08-21 08:18:09 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-08-23 21:15:37 -0400 |
commit | 51a00eaf6e008b60943af6ab68c17ac3622208dc (patch) | |
tree | 4333cdeeb875c4378e83c37681729619e6e1034e | |
parent | 1189f130f89b73eecb6117c0fc5e90abbcb7faa0 (diff) |
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: Tim Glaremin <Tim.Glaremin@web.de>
Signed-off-by: Sven Eckelmann <sven.eckelmann@gmx.de>
Cc: stable <stable@kernel.org>
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 892166b86dd8..d08491ed5455 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 net_device *net_dev, | |||
194 | if (batman_if->if_status != IF_INACTIVE) | 194 | if (batman_if->if_status != IF_INACTIVE) |
195 | return; | 195 | return; |
196 | 196 | ||
197 | dev_hold(batman_if->net_dev); | ||
198 | |||
199 | update_mac_addresses(batman_if); | 197 | update_mac_addresses(batman_if); |
200 | batman_if->if_status = IF_TO_BE_ACTIVATED; | 198 | batman_if->if_status = IF_TO_BE_ACTIVATED; |
201 | 199 | ||
@@ -222,8 +220,6 @@ static void hardif_deactivate_interface(struct net_device *net_dev, | |||
222 | (batman_if->if_status != IF_TO_BE_ACTIVATED)) | 220 | (batman_if->if_status != IF_TO_BE_ACTIVATED)) |
223 | return; | 221 | return; |
224 | 222 | ||
225 | dev_put(batman_if->net_dev); | ||
226 | |||
227 | batman_if->if_status = IF_INACTIVE; | 223 | batman_if->if_status = IF_INACTIVE; |
228 | 224 | ||
229 | bat_info(net_dev, "Interface deactivated: %s\n", batman_if->dev); | 225 | 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 | if (ret != 1) | 314 | if (ret != 1) |
319 | goto out; | 315 | goto out; |
320 | 316 | ||
317 | dev_hold(net_dev); | ||
318 | |||
321 | batman_if = kmalloc(sizeof(struct batman_if), GFP_ATOMIC); | 319 | batman_if = kmalloc(sizeof(struct batman_if), GFP_ATOMIC); |
322 | if (!batman_if) { | 320 | if (!batman_if) { |
323 | pr_err("Can't add interface (%s): out of memory\n", | 321 | pr_err("Can't add interface (%s): out of memory\n", |
324 | net_dev->name); | 322 | net_dev->name); |
325 | goto out; | 323 | goto release_dev; |
326 | } | 324 | } |
327 | 325 | ||
328 | batman_if->dev = kstrdup(net_dev->name, GFP_ATOMIC); | 326 | batman_if->dev = kstrdup(net_dev->name, GFP_ATOMIC); |
@@ -346,6 +344,8 @@ free_dev: | |||
346 | kfree(batman_if->dev); | 344 | kfree(batman_if->dev); |
347 | free_if: | 345 | free_if: |
348 | kfree(batman_if); | 346 | kfree(batman_if); |
347 | release_dev: | ||
348 | dev_put(net_dev); | ||
349 | out: | 349 | out: |
350 | return NULL; | 350 | return NULL; |
351 | } | 351 | } |
@@ -374,6 +374,7 @@ static void hardif_remove_interface(struct batman_if *batman_if) | |||
374 | batman_if->if_status = IF_TO_BE_REMOVED; | 374 | batman_if->if_status = IF_TO_BE_REMOVED; |
375 | list_del_rcu(&batman_if->list); | 375 | list_del_rcu(&batman_if->list); |
376 | sysfs_del_hardif(&batman_if->hardif_obj); | 376 | sysfs_del_hardif(&batman_if->hardif_obj); |
377 | dev_put(batman_if->net_dev); | ||
377 | call_rcu(&batman_if->rcu, hardif_free_interface); | 378 | call_rcu(&batman_if->rcu, hardif_free_interface); |
378 | } | 379 | } |
379 | 380 | ||