Skip to content

Commit 55793d2

Browse files
committed
Merge tag 'batadv-net-for-davem-20191025' of git://git.open-mesh.org/linux-merge
Simon Wunderlich says: ==================== Here are two batman-adv bugfixes: * Fix free/alloc race for OGM and OGMv2, by Sven Eckelmann (2 patches) ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 0a29ac5 + 40e220b commit 55793d2

File tree

4 files changed

+94
-17
lines changed

4 files changed

+94
-17
lines changed

net/batman-adv/bat_iv_ogm.c

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include <linux/kernel.h>
2323
#include <linux/kref.h>
2424
#include <linux/list.h>
25+
#include <linux/lockdep.h>
26+
#include <linux/mutex.h>
2527
#include <linux/netdevice.h>
2628
#include <linux/netlink.h>
2729
#include <linux/pkt_sched.h>
@@ -193,14 +195,18 @@ static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface)
193195
unsigned char *ogm_buff;
194196
u32 random_seqno;
195197

198+
mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex);
199+
196200
/* randomize initial seqno to avoid collision */
197201
get_random_bytes(&random_seqno, sizeof(random_seqno));
198202
atomic_set(&hard_iface->bat_iv.ogm_seqno, random_seqno);
199203

200204
hard_iface->bat_iv.ogm_buff_len = BATADV_OGM_HLEN;
201205
ogm_buff = kmalloc(hard_iface->bat_iv.ogm_buff_len, GFP_ATOMIC);
202-
if (!ogm_buff)
206+
if (!ogm_buff) {
207+
mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
203208
return -ENOMEM;
209+
}
204210

205211
hard_iface->bat_iv.ogm_buff = ogm_buff;
206212

@@ -212,35 +218,59 @@ static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface)
212218
batadv_ogm_packet->reserved = 0;
213219
batadv_ogm_packet->tq = BATADV_TQ_MAX_VALUE;
214220

221+
mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
222+
215223
return 0;
216224
}
217225

218226
static void batadv_iv_ogm_iface_disable(struct batadv_hard_iface *hard_iface)
219227
{
228+
mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex);
229+
220230
kfree(hard_iface->bat_iv.ogm_buff);
221231
hard_iface->bat_iv.ogm_buff = NULL;
232+
233+
mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
222234
}
223235

224236
static void batadv_iv_ogm_iface_update_mac(struct batadv_hard_iface *hard_iface)
225237
{
226238
struct batadv_ogm_packet *batadv_ogm_packet;
227-
unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff;
239+
void *ogm_buff;
228240

229-
batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
241+
mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex);
242+
243+
ogm_buff = hard_iface->bat_iv.ogm_buff;
244+
if (!ogm_buff)
245+
goto unlock;
246+
247+
batadv_ogm_packet = ogm_buff;
230248
ether_addr_copy(batadv_ogm_packet->orig,
231249
hard_iface->net_dev->dev_addr);
232250
ether_addr_copy(batadv_ogm_packet->prev_sender,
233251
hard_iface->net_dev->dev_addr);
252+
253+
unlock:
254+
mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
234255
}
235256

236257
static void
237258
batadv_iv_ogm_primary_iface_set(struct batadv_hard_iface *hard_iface)
238259
{
239260
struct batadv_ogm_packet *batadv_ogm_packet;
240-
unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff;
261+
void *ogm_buff;
241262

242-
batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
263+
mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex);
264+
265+
ogm_buff = hard_iface->bat_iv.ogm_buff;
266+
if (!ogm_buff)
267+
goto unlock;
268+
269+
batadv_ogm_packet = ogm_buff;
243270
batadv_ogm_packet->ttl = BATADV_TTL;
271+
272+
unlock:
273+
mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
244274
}
245275

246276
/* when do we schedule our own ogm to be sent */
@@ -742,7 +772,11 @@ batadv_iv_ogm_slide_own_bcast_window(struct batadv_hard_iface *hard_iface)
742772
}
743773
}
744774

745-
static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
775+
/**
776+
* batadv_iv_ogm_schedule_buff() - schedule submission of hardif ogm buffer
777+
* @hard_iface: interface whose ogm buffer should be transmitted
778+
*/
779+
static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface)
746780
{
747781
struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
748782
unsigned char **ogm_buff = &hard_iface->bat_iv.ogm_buff;
@@ -753,9 +787,7 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
753787
u16 tvlv_len = 0;
754788
unsigned long send_time;
755789

756-
if (hard_iface->if_status == BATADV_IF_NOT_IN_USE ||
757-
hard_iface->if_status == BATADV_IF_TO_BE_REMOVED)
758-
return;
790+
lockdep_assert_held(&hard_iface->bat_iv.ogm_buff_mutex);
759791

760792
/* the interface gets activated here to avoid race conditions between
761793
* the moment of activating the interface in
@@ -823,6 +855,17 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
823855
batadv_hardif_put(primary_if);
824856
}
825857

858+
static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
859+
{
860+
if (hard_iface->if_status == BATADV_IF_NOT_IN_USE ||
861+
hard_iface->if_status == BATADV_IF_TO_BE_REMOVED)
862+
return;
863+
864+
mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex);
865+
batadv_iv_ogm_schedule_buff(hard_iface);
866+
mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
867+
}
868+
826869
/**
827870
* batadv_iv_orig_ifinfo_sum() - Get bcast_own sum for originator over iterface
828871
* @orig_node: originator which reproadcasted the OGMs directly

net/batman-adv/bat_v_ogm.c

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/kref.h>
1919
#include <linux/list.h>
2020
#include <linux/lockdep.h>
21+
#include <linux/mutex.h>
2122
#include <linux/netdevice.h>
2223
#include <linux/random.h>
2324
#include <linux/rculist.h>
@@ -256,23 +257,20 @@ static void batadv_v_ogm_queue_on_if(struct sk_buff *skb,
256257
}
257258

258259
/**
259-
* batadv_v_ogm_send() - periodic worker broadcasting the own OGM
260-
* @work: work queue item
260+
* batadv_v_ogm_send_softif() - periodic worker broadcasting the own OGM
261+
* @bat_priv: the bat priv with all the soft interface information
261262
*/
262-
static void batadv_v_ogm_send(struct work_struct *work)
263+
static void batadv_v_ogm_send_softif(struct batadv_priv *bat_priv)
263264
{
264265
struct batadv_hard_iface *hard_iface;
265-
struct batadv_priv_bat_v *bat_v;
266-
struct batadv_priv *bat_priv;
267266
struct batadv_ogm2_packet *ogm_packet;
268267
struct sk_buff *skb, *skb_tmp;
269268
unsigned char *ogm_buff;
270269
int ogm_buff_len;
271270
u16 tvlv_len = 0;
272271
int ret;
273272

274-
bat_v = container_of(work, struct batadv_priv_bat_v, ogm_wq.work);
275-
bat_priv = container_of(bat_v, struct batadv_priv, bat_v);
273+
lockdep_assert_held(&bat_priv->bat_v.ogm_buff_mutex);
276274

277275
if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING)
278276
goto out;
@@ -363,6 +361,23 @@ static void batadv_v_ogm_send(struct work_struct *work)
363361
return;
364362
}
365363

364+
/**
365+
* batadv_v_ogm_send() - periodic worker broadcasting the own OGM
366+
* @work: work queue item
367+
*/
368+
static void batadv_v_ogm_send(struct work_struct *work)
369+
{
370+
struct batadv_priv_bat_v *bat_v;
371+
struct batadv_priv *bat_priv;
372+
373+
bat_v = container_of(work, struct batadv_priv_bat_v, ogm_wq.work);
374+
bat_priv = container_of(bat_v, struct batadv_priv, bat_v);
375+
376+
mutex_lock(&bat_priv->bat_v.ogm_buff_mutex);
377+
batadv_v_ogm_send_softif(bat_priv);
378+
mutex_unlock(&bat_priv->bat_v.ogm_buff_mutex);
379+
}
380+
366381
/**
367382
* batadv_v_ogm_aggr_work() - OGM queue periodic task per interface
368383
* @work: work queue item
@@ -424,11 +439,15 @@ void batadv_v_ogm_primary_iface_set(struct batadv_hard_iface *primary_iface)
424439
struct batadv_priv *bat_priv = netdev_priv(primary_iface->soft_iface);
425440
struct batadv_ogm2_packet *ogm_packet;
426441

442+
mutex_lock(&bat_priv->bat_v.ogm_buff_mutex);
427443
if (!bat_priv->bat_v.ogm_buff)
428-
return;
444+
goto unlock;
429445

430446
ogm_packet = (struct batadv_ogm2_packet *)bat_priv->bat_v.ogm_buff;
431447
ether_addr_copy(ogm_packet->orig, primary_iface->net_dev->dev_addr);
448+
449+
unlock:
450+
mutex_unlock(&bat_priv->bat_v.ogm_buff_mutex);
432451
}
433452

434453
/**
@@ -1050,6 +1069,8 @@ int batadv_v_ogm_init(struct batadv_priv *bat_priv)
10501069
atomic_set(&bat_priv->bat_v.ogm_seqno, random_seqno);
10511070
INIT_DELAYED_WORK(&bat_priv->bat_v.ogm_wq, batadv_v_ogm_send);
10521071

1072+
mutex_init(&bat_priv->bat_v.ogm_buff_mutex);
1073+
10531074
return 0;
10541075
}
10551076

@@ -1061,7 +1082,11 @@ void batadv_v_ogm_free(struct batadv_priv *bat_priv)
10611082
{
10621083
cancel_delayed_work_sync(&bat_priv->bat_v.ogm_wq);
10631084

1085+
mutex_lock(&bat_priv->bat_v.ogm_buff_mutex);
1086+
10641087
kfree(bat_priv->bat_v.ogm_buff);
10651088
bat_priv->bat_v.ogm_buff = NULL;
10661089
bat_priv->bat_v.ogm_buff_len = 0;
1090+
1091+
mutex_unlock(&bat_priv->bat_v.ogm_buff_mutex);
10671092
}

net/batman-adv/hard-interface.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/kref.h>
1919
#include <linux/limits.h>
2020
#include <linux/list.h>
21+
#include <linux/mutex.h>
2122
#include <linux/netdevice.h>
2223
#include <linux/printk.h>
2324
#include <linux/rculist.h>
@@ -929,6 +930,7 @@ batadv_hardif_add_interface(struct net_device *net_dev)
929930
INIT_LIST_HEAD(&hard_iface->list);
930931
INIT_HLIST_HEAD(&hard_iface->neigh_list);
931932

933+
mutex_init(&hard_iface->bat_iv.ogm_buff_mutex);
932934
spin_lock_init(&hard_iface->neigh_list_lock);
933935
kref_init(&hard_iface->refcount);
934936

net/batman-adv/types.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <linux/if.h>
1818
#include <linux/if_ether.h>
1919
#include <linux/kref.h>
20+
#include <linux/mutex.h>
2021
#include <linux/netdevice.h>
2122
#include <linux/netlink.h>
2223
#include <linux/sched.h> /* for linux/wait.h */
@@ -81,6 +82,9 @@ struct batadv_hard_iface_bat_iv {
8182

8283
/** @ogm_seqno: OGM sequence number - used to identify each OGM */
8384
atomic_t ogm_seqno;
85+
86+
/** @ogm_buff_mutex: lock protecting ogm_buff and ogm_buff_len */
87+
struct mutex ogm_buff_mutex;
8488
};
8589

8690
/**
@@ -1539,6 +1543,9 @@ struct batadv_priv_bat_v {
15391543
/** @ogm_seqno: OGM sequence number - used to identify each OGM */
15401544
atomic_t ogm_seqno;
15411545

1546+
/** @ogm_buff_mutex: lock protecting ogm_buff and ogm_buff_len */
1547+
struct mutex ogm_buff_mutex;
1548+
15421549
/** @ogm_wq: workqueue used to schedule OGM transmissions */
15431550
struct delayed_work ogm_wq;
15441551
};

0 commit comments

Comments
 (0)