Skip to content

Commit

Permalink
batman-adv: mcast: fix multicast tt/tvlv worker locking
Browse files Browse the repository at this point in the history
Syzbot has reported some issues with the locking assumptions made for
the multicast tt/tvlv worker: It was able to trigger the WARN_ON() in
batadv_mcast_mla_tt_retract() and batadv_mcast_mla_tt_add().
While hard/not reproduceable for us so far it seems that the
delayed_work_pending() we use might not be quite safe from reordering.

Therefore this patch adds an explicit, new spinlock to protect the
update of the mla_list and flags in bat_priv and then removes the
WARN_ON(delayed_work_pending()).

Reported-by: [email protected]
Reported-by: [email protected]
Reported-by: [email protected]
Reported-by: [email protected]
Fixes: cbebd36 ("batman-adv: Use own timer for multicast TT and TVLV updates")
Signed-off-by: Linus Lüssing <[email protected]>
Signed-off-by: Sven Eckelmann <[email protected]>
Signed-off-by: Simon Wunderlich <[email protected]>
  • Loading branch information
T-X authored and simonwunderlich committed May 6, 2019
1 parent bdc76fd commit a3c7cd0
Show file tree
Hide file tree
Showing 3 changed files with 9 additions and 8 deletions.
1 change: 1 addition & 0 deletions net/batman-adv/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ int batadv_mesh_init(struct net_device *soft_iface)
spin_lock_init(&bat_priv->tt.commit_lock);
spin_lock_init(&bat_priv->gw.list_lock);
#ifdef CONFIG_BATMAN_ADV_MCAST
spin_lock_init(&bat_priv->mcast.mla_lock);
spin_lock_init(&bat_priv->mcast.want_lists_lock);
#endif
spin_lock_init(&bat_priv->tvlv.container_list_lock);
Expand Down
11 changes: 3 additions & 8 deletions net/batman-adv/multicast.c
Original file line number Diff line number Diff line change
Expand Up @@ -325,17 +325,13 @@ static void batadv_mcast_mla_list_free(struct hlist_head *mcast_list)
* translation table except the ones listed in the given mcast_list.
*
* If mcast_list is NULL then all are retracted.
*
* Do not call outside of the mcast worker! (or cancel mcast worker first)
*/
static void batadv_mcast_mla_tt_retract(struct batadv_priv *bat_priv,
struct hlist_head *mcast_list)
{
struct batadv_hw_addr *mcast_entry;
struct hlist_node *tmp;

WARN_ON(delayed_work_pending(&bat_priv->mcast.work));

hlist_for_each_entry_safe(mcast_entry, tmp, &bat_priv->mcast.mla_list,
list) {
if (mcast_list &&
Expand All @@ -359,17 +355,13 @@ static void batadv_mcast_mla_tt_retract(struct batadv_priv *bat_priv,
*
* Adds multicast listener announcements from the given mcast_list to the
* translation table if they have not been added yet.
*
* Do not call outside of the mcast worker! (or cancel mcast worker first)
*/
static void batadv_mcast_mla_tt_add(struct batadv_priv *bat_priv,
struct hlist_head *mcast_list)
{
struct batadv_hw_addr *mcast_entry;
struct hlist_node *tmp;

WARN_ON(delayed_work_pending(&bat_priv->mcast.work));

if (!mcast_list)
return;

Expand Down Expand Up @@ -658,7 +650,10 @@ static void batadv_mcast_mla_update(struct work_struct *work)
priv_mcast = container_of(delayed_work, struct batadv_priv_mcast, work);
bat_priv = container_of(priv_mcast, struct batadv_priv, mcast);

spin_lock(&bat_priv->mcast.mla_lock);
__batadv_mcast_mla_update(bat_priv);
spin_unlock(&bat_priv->mcast.mla_lock);

batadv_mcast_start_timer(bat_priv);
}

Expand Down
5 changes: 5 additions & 0 deletions net/batman-adv/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -1223,6 +1223,11 @@ struct batadv_priv_mcast {
/** @bridged: whether the soft interface has a bridge on top */
unsigned char bridged:1;

/**
* @mla_lock: a lock protecting mla_list and mla_flags
*/
spinlock_t mla_lock;

/**
* @num_want_all_unsnoopables: number of nodes wanting unsnoopable IP
* traffic
Expand Down

0 comments on commit a3c7cd0

Please sign in to comment.