Skip to content

Commit 3d4548c

Browse files
ecsvgregkh
authored andcommitted
batman-adv: v: prevent OGM aggregation on disabled hardif
commit d11c00b upstream. When an interface gets disabled, the worker is correctly disabled by batadv_hardif_disable_interface() -> ... -> batadv_v_ogm_iface_disable(). In this process, the skb aggr_list is also freed. But batadv_v_ogm_send_meshif() can still queue new skbs (via batadv_v_ogm_queue_on_if()) to the aggr_list. This will only stop after all cores can no longer find the RCU protected list of hard interfaces. These queued skbs will never be freed or consumed by batadv_v_ogm_aggr_work. The batadv_v_ogm_iface_disable() function must block batadv_v_ogm_queue_on_if() to avoid leak of skbs. Cc: stable@kernel.org Fixes: f89255a ("batman-adv: BATMAN_V: introduce per hard-iface OGMv2 queues") [ Context ] Signed-off-by: Sven Eckelmann <sven@narfation.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 44ae137 commit 3d4548c

3 files changed

Lines changed: 19 additions & 0 deletions

File tree

net/batman-adv/bat_v.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,7 @@ void batadv_v_hardif_init(struct batadv_hard_iface *hard_iface)
817817

818818
hard_iface->bat_v.aggr_len = 0;
819819
skb_queue_head_init(&hard_iface->bat_v.aggr_list);
820+
hard_iface->bat_v.aggr_list_enabled = false;
820821
INIT_DELAYED_WORK(&hard_iface->bat_v.aggr_wq,
821822
batadv_v_ogm_aggr_work);
822823
}

net/batman-adv/bat_v_ogm.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,11 +252,18 @@ static void batadv_v_ogm_queue_on_if(struct batadv_priv *bat_priv,
252252
}
253253

254254
spin_lock_bh(&hard_iface->bat_v.aggr_list.lock);
255+
if (!hard_iface->bat_v.aggr_list_enabled) {
256+
kfree_skb(skb);
257+
goto unlock;
258+
}
259+
255260
if (!batadv_v_ogm_queue_left(skb, hard_iface))
256261
batadv_v_ogm_aggr_send(bat_priv, hard_iface);
257262

258263
hard_iface->bat_v.aggr_len += batadv_v_ogm_len(skb);
259264
__skb_queue_tail(&hard_iface->bat_v.aggr_list, skb);
265+
266+
unlock:
260267
spin_unlock_bh(&hard_iface->bat_v.aggr_list.lock);
261268
}
262269

@@ -417,6 +424,10 @@ int batadv_v_ogm_iface_enable(struct batadv_hard_iface *hard_iface)
417424
{
418425
struct batadv_priv *bat_priv = netdev_priv(hard_iface->mesh_iface);
419426

427+
spin_lock_bh(&hard_iface->bat_v.aggr_list.lock);
428+
hard_iface->bat_v.aggr_list_enabled = true;
429+
spin_unlock_bh(&hard_iface->bat_v.aggr_list.lock);
430+
420431
batadv_v_ogm_start_queue_timer(hard_iface);
421432
batadv_v_ogm_start_timer(bat_priv);
422433

@@ -432,6 +443,7 @@ void batadv_v_ogm_iface_disable(struct batadv_hard_iface *hard_iface)
432443
cancel_delayed_work_sync(&hard_iface->bat_v.aggr_wq);
433444

434445
spin_lock_bh(&hard_iface->bat_v.aggr_list.lock);
446+
hard_iface->bat_v.aggr_list_enabled = false;
435447
batadv_v_ogm_aggr_list_free(hard_iface);
436448
spin_unlock_bh(&hard_iface->bat_v.aggr_list.lock);
437449
}

net/batman-adv/types.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,12 @@ struct batadv_hard_iface_bat_v {
130130
/** @aggr_list: queue for to be aggregated OGM packets */
131131
struct sk_buff_head aggr_list;
132132

133+
/**
134+
* @aggr_list_enabled: aggr_list is active and new skbs can be
135+
* enqueued. Protected by aggr_list.lock after initialization
136+
*/
137+
bool aggr_list_enabled:1;
138+
133139
/** @aggr_len: size of the OGM aggregate (excluding ethernet header) */
134140
unsigned int aggr_len;
135141

0 commit comments

Comments
 (0)