aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv
diff options
context:
space:
mode:
authorSven Eckelmann <sven@narfation.org>2011-03-04 16:36:41 -0500
committerMarek Lindner <lindner_marek@yahoo.de>2011-03-05 06:52:09 -0500
commite44d8fe2b5c27ecc230f886d4cc49fcbd86f87a0 (patch)
tree1ed6d2b1fa04a4fe333d8eda498b3e866129d4d3 /net/batman-adv
parent7cefb149a6b0e4f7c5adfa27dcf285b729063848 (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')
-rw-r--r--net/batman-adv/hard-interface.c34
-rw-r--r--net/batman-adv/soft-interface.c13
-rw-r--r--net/batman-adv/soft-interface.h1
3 files changed, 36 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
371err: 381err:
372 hardif_free_ref(hard_iface); 382 hardif_free_ref(hard_iface);
373 return -ENOMEM; 383 return ret;
374} 384}
375 385
376void hardif_disable_interface(struct hard_iface *hard_iface) 386void hardif_disable_interface(struct hard_iface *hard_iface)
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 6b514ecee5a2..9ed26140a269 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -622,6 +622,19 @@ void softif_destroy(struct net_device *soft_iface)
622 unregister_netdevice(soft_iface); 622 unregister_netdevice(soft_iface);
623} 623}
624 624
625int softif_is_valid(struct net_device *net_dev)
626{
627#ifdef HAVE_NET_DEVICE_OPS
628 if (net_dev->netdev_ops->ndo_start_xmit == interface_tx)
629 return 1;
630#else
631 if (net_dev->hard_start_xmit == interface_tx)
632 return 1;
633#endif
634
635 return 0;
636}
637
625/* ethtool */ 638/* ethtool */
626static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) 639static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
627{ 640{
diff --git a/net/batman-adv/soft-interface.h b/net/batman-adv/soft-interface.h
index 80a3607df186..4789b6f2a0b3 100644
--- a/net/batman-adv/soft-interface.h
+++ b/net/batman-adv/soft-interface.h
@@ -31,5 +31,6 @@ void interface_rx(struct net_device *soft_iface,
31 int hdr_size); 31 int hdr_size);
32struct net_device *softif_create(char *name); 32struct net_device *softif_create(char *name);
33void softif_destroy(struct net_device *soft_iface); 33void softif_destroy(struct net_device *soft_iface);
34int softif_is_valid(struct net_device *net_dev);
34 35
35#endif /* _NET_BATMAN_ADV_SOFT_INTERFACE_H_ */ 36#endif /* _NET_BATMAN_ADV_SOFT_INTERFACE_H_ */