diff options
author | Sven Eckelmann <sven@narfation.org> | 2011-03-04 16:36:41 -0500 |
---|---|---|
committer | Marek Lindner <lindner_marek@yahoo.de> | 2011-03-05 06:52:09 -0500 |
commit | e44d8fe2b5c27ecc230f886d4cc49fcbd86f87a0 (patch) | |
tree | 1ed6d2b1fa04a4fe333d8eda498b3e866129d4d3 /net/batman-adv/hard-interface.c | |
parent | 7cefb149a6b0e4f7c5adfa27dcf285b729063848 (diff) |
batman-adv: Disallow regular interface as mesh device
When trying to associate a net_device with another net_device which
already exists, batman-adv assumes that this interface is a fully
initialized batman mesh interface without checking it. The behaviour
when accessing data behind netdev_priv of a random net_device is
undefined and potentially dangerous.
Reported-by: Linus Lüssing <linus.luessing@ascom.ch>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Diffstat (limited to 'net/batman-adv/hard-interface.c')
-rw-r--r-- | net/batman-adv/hard-interface.c | 34 |
1 files changed, 22 insertions, 12 deletions
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index 95a35b695700..b3058e46ee6b 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c | |||
@@ -79,13 +79,8 @@ static int is_valid_iface(struct net_device *net_dev) | |||
79 | return 0; | 79 | return 0; |
80 | 80 | ||
81 | /* no batman over batman */ | 81 | /* no batman over batman */ |
82 | #ifdef HAVE_NET_DEVICE_OPS | 82 | if (softif_is_valid(net_dev)) |
83 | if (net_dev->netdev_ops->ndo_start_xmit == interface_tx) | ||
84 | return 0; | 83 | return 0; |
85 | #else | ||
86 | if (net_dev->hard_start_xmit == interface_tx) | ||
87 | return 0; | ||
88 | #endif | ||
89 | 84 | ||
90 | /* Device is being bridged */ | 85 | /* Device is being bridged */ |
91 | /* if (net_dev->priv_flags & IFF_BRIDGE_PORT) | 86 | /* if (net_dev->priv_flags & IFF_BRIDGE_PORT) |
@@ -282,6 +277,8 @@ int hardif_enable_interface(struct hard_iface *hard_iface, char *iface_name) | |||
282 | { | 277 | { |
283 | struct bat_priv *bat_priv; | 278 | struct bat_priv *bat_priv; |
284 | struct batman_packet *batman_packet; | 279 | struct batman_packet *batman_packet; |
280 | struct net_device *soft_iface; | ||
281 | int ret; | ||
285 | 282 | ||
286 | if (hard_iface->if_status != IF_NOT_IN_USE) | 283 | if (hard_iface->if_status != IF_NOT_IN_USE) |
287 | goto out; | 284 | goto out; |
@@ -289,18 +286,30 @@ int hardif_enable_interface(struct hard_iface *hard_iface, char *iface_name) | |||
289 | if (!atomic_inc_not_zero(&hard_iface->refcount)) | 286 | if (!atomic_inc_not_zero(&hard_iface->refcount)) |
290 | goto out; | 287 | goto out; |
291 | 288 | ||
292 | hard_iface->soft_iface = dev_get_by_name(&init_net, iface_name); | 289 | soft_iface = dev_get_by_name(&init_net, iface_name); |
293 | 290 | ||
294 | if (!hard_iface->soft_iface) { | 291 | if (!soft_iface) { |
295 | hard_iface->soft_iface = softif_create(iface_name); | 292 | soft_iface = softif_create(iface_name); |
296 | 293 | ||
297 | if (!hard_iface->soft_iface) | 294 | if (!soft_iface) { |
295 | ret = -ENOMEM; | ||
298 | goto err; | 296 | goto err; |
297 | } | ||
299 | 298 | ||
300 | /* dev_get_by_name() increases the reference counter for us */ | 299 | /* dev_get_by_name() increases the reference counter for us */ |
301 | dev_hold(hard_iface->soft_iface); | 300 | dev_hold(soft_iface); |
301 | } | ||
302 | |||
303 | if (!softif_is_valid(soft_iface)) { | ||
304 | pr_err("Can't create batman mesh interface %s: " | ||
305 | "already exists as regular interface\n", | ||
306 | soft_iface->name); | ||
307 | dev_put(soft_iface); | ||
308 | ret = -EINVAL; | ||
309 | goto err; | ||
302 | } | 310 | } |
303 | 311 | ||
312 | hard_iface->soft_iface = soft_iface; | ||
304 | bat_priv = netdev_priv(hard_iface->soft_iface); | 313 | bat_priv = netdev_priv(hard_iface->soft_iface); |
305 | hard_iface->packet_len = BAT_PACKET_LEN; | 314 | hard_iface->packet_len = BAT_PACKET_LEN; |
306 | hard_iface->packet_buff = kmalloc(hard_iface->packet_len, GFP_ATOMIC); | 315 | hard_iface->packet_buff = kmalloc(hard_iface->packet_len, GFP_ATOMIC); |
@@ -308,6 +317,7 @@ int hardif_enable_interface(struct hard_iface *hard_iface, char *iface_name) | |||
308 | if (!hard_iface->packet_buff) { | 317 | if (!hard_iface->packet_buff) { |
309 | bat_err(hard_iface->soft_iface, "Can't add interface packet " | 318 | bat_err(hard_iface->soft_iface, "Can't add interface packet " |
310 | "(%s): out of memory\n", hard_iface->net_dev->name); | 319 | "(%s): out of memory\n", hard_iface->net_dev->name); |
320 | ret = -ENOMEM; | ||
311 | goto err; | 321 | goto err; |
312 | } | 322 | } |
313 | 323 | ||
@@ -370,7 +380,7 @@ out: | |||
370 | 380 | ||
371 | err: | 381 | err: |
372 | hardif_free_ref(hard_iface); | 382 | hardif_free_ref(hard_iface); |
373 | return -ENOMEM; | 383 | return ret; |
374 | } | 384 | } |
375 | 385 | ||
376 | void hardif_disable_interface(struct hard_iface *hard_iface) | 386 | void hardif_disable_interface(struct hard_iface *hard_iface) |