VYPR
Unrated severityNVD Advisory· Published May 28, 2026

CVE-2026-46206

CVE-2026-46206

Description

In the Linux kernel, the following vulnerability has been resolved:

batman-adv: reject new tp_meter sessions during teardown

Prevent tp_meter from starting new sender or receiver sessions after mesh_state has left BATADV_MESH_ACTIVE.

Affected products

3

Patches

10
e1e2194cc725

batman-adv: reject new tp_meter sessions during teardown

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitJiexun WangApr 27, 2026Fixed in 6.18.32via kernel-cna
1 file changed · +16 2
  • net/batman-adv/tp_meter.c+16 2 modified
    diff --git a/net/batman-adv/tp_meter.c b/net/batman-adv/tp_meter.c
    index 350b149e48bebf..f3c4b5e8427291 100644
    --- a/net/batman-adv/tp_meter.c
    +++ b/net/batman-adv/tp_meter.c
    @@ -947,6 +947,13 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst,
     
     	/* look for an already existing test towards this node */
     	spin_lock_bh(&bat_priv->tp_list_lock);
    +	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) {
    +		spin_unlock_bh(&bat_priv->tp_list_lock);
    +		batadv_tp_batctl_error_notify(BATADV_TP_REASON_DST_UNREACHABLE,
    +					      dst, bat_priv, session_cookie);
    +		return;
    +	}
    +
     	tp_vars = batadv_tp_list_find(bat_priv, dst);
     	if (tp_vars) {
     		spin_unlock_bh(&bat_priv->tp_list_lock);
    @@ -1329,9 +1336,12 @@ static struct batadv_tp_vars *
     batadv_tp_init_recv(struct batadv_priv *bat_priv,
     		    const struct batadv_icmp_tp_packet *icmp)
     {
    -	struct batadv_tp_vars *tp_vars;
    +	struct batadv_tp_vars *tp_vars = NULL;
     
     	spin_lock_bh(&bat_priv->tp_list_lock);
    +	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
    +		goto out_unlock;
    +
     	tp_vars = batadv_tp_list_find_session(bat_priv, icmp->orig,
     					      icmp->session);
     	if (tp_vars)
    @@ -1464,6 +1474,9 @@ void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb)
     {
     	struct batadv_icmp_tp_packet *icmp;
     
    +	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
    +		goto out;
    +
     	icmp = (struct batadv_icmp_tp_packet *)skb->data;
     
     	switch (icmp->subtype) {
    @@ -1478,6 +1491,8 @@ void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb)
     			   "Received unknown TP Metric packet type %u\n",
     			   icmp->subtype);
     	}
    +
    +out:
     	consume_skb(skb);
     }
     
    -- 
    cgit 1.3-korg
    
    
    
ca39545cf07c

batman-adv: reject new tp_meter sessions during teardown

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitJiexun WangApr 27, 2026Fixed in 7.0.9via kernel-cna
1 file changed · +16 2
  • net/batman-adv/tp_meter.c+16 2 modified
    diff --git a/net/batman-adv/tp_meter.c b/net/batman-adv/tp_meter.c
    index 2e42f6b348c83d..d9a80e459c2e4a 100644
    --- a/net/batman-adv/tp_meter.c
    +++ b/net/batman-adv/tp_meter.c
    @@ -947,6 +947,13 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst,
     
     	/* look for an already existing test towards this node */
     	spin_lock_bh(&bat_priv->tp_list_lock);
    +	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) {
    +		spin_unlock_bh(&bat_priv->tp_list_lock);
    +		batadv_tp_batctl_error_notify(BATADV_TP_REASON_DST_UNREACHABLE,
    +					      dst, bat_priv, session_cookie);
    +		return;
    +	}
    +
     	tp_vars = batadv_tp_list_find(bat_priv, dst);
     	if (tp_vars) {
     		spin_unlock_bh(&bat_priv->tp_list_lock);
    @@ -1329,9 +1336,12 @@ static struct batadv_tp_vars *
     batadv_tp_init_recv(struct batadv_priv *bat_priv,
     		    const struct batadv_icmp_tp_packet *icmp)
     {
    -	struct batadv_tp_vars *tp_vars;
    +	struct batadv_tp_vars *tp_vars = NULL;
     
     	spin_lock_bh(&bat_priv->tp_list_lock);
    +	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
    +		goto out_unlock;
    +
     	tp_vars = batadv_tp_list_find_session(bat_priv, icmp->orig,
     					      icmp->session);
     	if (tp_vars)
    @@ -1464,6 +1474,9 @@ void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb)
     {
     	struct batadv_icmp_tp_packet *icmp;
     
    +	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
    +		goto out;
    +
     	icmp = (struct batadv_icmp_tp_packet *)skb->data;
     
     	switch (icmp->subtype) {
    @@ -1478,6 +1491,8 @@ void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb)
     			   "Received unknown TP Metric packet type %u\n",
     			   icmp->subtype);
     	}
    +
    +out:
     	consume_skb(skb);
     }
     
    -- 
    cgit 1.3-korg
    
    
    
324354359242

batman-adv: reject new tp_meter sessions during teardown

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitJiexun WangApr 27, 2026Fixed in 7.1-rc4via kernel-cna
1 file changed · +16 2
  • net/batman-adv/tp_meter.c+16 2 modified
    diff --git a/net/batman-adv/tp_meter.c b/net/batman-adv/tp_meter.c
    index 2e42f6b348c83d..d9a80e459c2e4a 100644
    --- a/net/batman-adv/tp_meter.c
    +++ b/net/batman-adv/tp_meter.c
    @@ -947,6 +947,13 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst,
     
     	/* look for an already existing test towards this node */
     	spin_lock_bh(&bat_priv->tp_list_lock);
    +	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) {
    +		spin_unlock_bh(&bat_priv->tp_list_lock);
    +		batadv_tp_batctl_error_notify(BATADV_TP_REASON_DST_UNREACHABLE,
    +					      dst, bat_priv, session_cookie);
    +		return;
    +	}
    +
     	tp_vars = batadv_tp_list_find(bat_priv, dst);
     	if (tp_vars) {
     		spin_unlock_bh(&bat_priv->tp_list_lock);
    @@ -1329,9 +1336,12 @@ static struct batadv_tp_vars *
     batadv_tp_init_recv(struct batadv_priv *bat_priv,
     		    const struct batadv_icmp_tp_packet *icmp)
     {
    -	struct batadv_tp_vars *tp_vars;
    +	struct batadv_tp_vars *tp_vars = NULL;
     
     	spin_lock_bh(&bat_priv->tp_list_lock);
    +	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
    +		goto out_unlock;
    +
     	tp_vars = batadv_tp_list_find_session(bat_priv, icmp->orig,
     					      icmp->session);
     	if (tp_vars)
    @@ -1464,6 +1474,9 @@ void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb)
     {
     	struct batadv_icmp_tp_packet *icmp;
     
    +	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
    +		goto out;
    +
     	icmp = (struct batadv_icmp_tp_packet *)skb->data;
     
     	switch (icmp->subtype) {
    @@ -1478,6 +1491,8 @@ void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb)
     			   "Received unknown TP Metric packet type %u\n",
     			   icmp->subtype);
     	}
    +
    +out:
     	consume_skb(skb);
     }
     
    -- 
    cgit 1.3-korg
    
    
    
e4a3c4a4c8f6

batman-adv: reject new tp_meter sessions during teardown

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitJiexun WangApr 27, 2026Fixed in 6.6.140via kernel-cna
1 file changed · +16 2
  • net/batman-adv/tp_meter.c+16 2 modified
    diff --git a/net/batman-adv/tp_meter.c b/net/batman-adv/tp_meter.c
    index 7f3dd3c393e07a..56831f9fb071f5 100644
    --- a/net/batman-adv/tp_meter.c
    +++ b/net/batman-adv/tp_meter.c
    @@ -947,6 +947,13 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst,
     
     	/* look for an already existing test towards this node */
     	spin_lock_bh(&bat_priv->tp_list_lock);
    +	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) {
    +		spin_unlock_bh(&bat_priv->tp_list_lock);
    +		batadv_tp_batctl_error_notify(BATADV_TP_REASON_DST_UNREACHABLE,
    +					      dst, bat_priv, session_cookie);
    +		return;
    +	}
    +
     	tp_vars = batadv_tp_list_find(bat_priv, dst);
     	if (tp_vars) {
     		spin_unlock_bh(&bat_priv->tp_list_lock);
    @@ -1329,9 +1336,12 @@ static struct batadv_tp_vars *
     batadv_tp_init_recv(struct batadv_priv *bat_priv,
     		    const struct batadv_icmp_tp_packet *icmp)
     {
    -	struct batadv_tp_vars *tp_vars;
    +	struct batadv_tp_vars *tp_vars = NULL;
     
     	spin_lock_bh(&bat_priv->tp_list_lock);
    +	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
    +		goto out_unlock;
    +
     	tp_vars = batadv_tp_list_find_session(bat_priv, icmp->orig,
     					      icmp->session);
     	if (tp_vars)
    @@ -1464,6 +1474,9 @@ void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb)
     {
     	struct batadv_icmp_tp_packet *icmp;
     
    +	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
    +		goto out;
    +
     	icmp = (struct batadv_icmp_tp_packet *)skb->data;
     
     	switch (icmp->subtype) {
    @@ -1478,6 +1491,8 @@ void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb)
     			   "Received unknown TP Metric packet type %u\n",
     			   icmp->subtype);
     	}
    +
    +out:
     	consume_skb(skb);
     }
     
    -- 
    cgit 1.3-korg
    
    
    
ff93f86ecbb5

batman-adv: reject new tp_meter sessions during teardown

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitJiexun WangApr 27, 2026Fixed in 6.12.90via kernel-cna
1 file changed · +16 2
  • net/batman-adv/tp_meter.c+16 2 modified
    diff --git a/net/batman-adv/tp_meter.c b/net/batman-adv/tp_meter.c
    index 7f3dd3c393e07a..56831f9fb071f5 100644
    --- a/net/batman-adv/tp_meter.c
    +++ b/net/batman-adv/tp_meter.c
    @@ -947,6 +947,13 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst,
     
     	/* look for an already existing test towards this node */
     	spin_lock_bh(&bat_priv->tp_list_lock);
    +	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) {
    +		spin_unlock_bh(&bat_priv->tp_list_lock);
    +		batadv_tp_batctl_error_notify(BATADV_TP_REASON_DST_UNREACHABLE,
    +					      dst, bat_priv, session_cookie);
    +		return;
    +	}
    +
     	tp_vars = batadv_tp_list_find(bat_priv, dst);
     	if (tp_vars) {
     		spin_unlock_bh(&bat_priv->tp_list_lock);
    @@ -1329,9 +1336,12 @@ static struct batadv_tp_vars *
     batadv_tp_init_recv(struct batadv_priv *bat_priv,
     		    const struct batadv_icmp_tp_packet *icmp)
     {
    -	struct batadv_tp_vars *tp_vars;
    +	struct batadv_tp_vars *tp_vars = NULL;
     
     	spin_lock_bh(&bat_priv->tp_list_lock);
    +	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
    +		goto out_unlock;
    +
     	tp_vars = batadv_tp_list_find_session(bat_priv, icmp->orig,
     					      icmp->session);
     	if (tp_vars)
    @@ -1464,6 +1474,9 @@ void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb)
     {
     	struct batadv_icmp_tp_packet *icmp;
     
    +	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
    +		goto out;
    +
     	icmp = (struct batadv_icmp_tp_packet *)skb->data;
     
     	switch (icmp->subtype) {
    @@ -1478,6 +1491,8 @@ void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb)
     			   "Received unknown TP Metric packet type %u\n",
     			   icmp->subtype);
     	}
    +
    +out:
     	consume_skb(skb);
     }
     
    -- 
    cgit 1.3-korg
    
    
    
e4a3c4a4c8f6

batman-adv: reject new tp_meter sessions during teardown

1 file changed · +16 2
  • net/batman-adv/tp_meter.c+16 2 modified
    diff --git a/net/batman-adv/tp_meter.c b/net/batman-adv/tp_meter.c
    index 7f3dd3c393e07a..56831f9fb071f5 100644
    --- a/net/batman-adv/tp_meter.c
    +++ b/net/batman-adv/tp_meter.c
    @@ -947,6 +947,13 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst,
     
     	/* look for an already existing test towards this node */
     	spin_lock_bh(&bat_priv->tp_list_lock);
    +	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) {
    +		spin_unlock_bh(&bat_priv->tp_list_lock);
    +		batadv_tp_batctl_error_notify(BATADV_TP_REASON_DST_UNREACHABLE,
    +					      dst, bat_priv, session_cookie);
    +		return;
    +	}
    +
     	tp_vars = batadv_tp_list_find(bat_priv, dst);
     	if (tp_vars) {
     		spin_unlock_bh(&bat_priv->tp_list_lock);
    @@ -1329,9 +1336,12 @@ static struct batadv_tp_vars *
     batadv_tp_init_recv(struct batadv_priv *bat_priv,
     		    const struct batadv_icmp_tp_packet *icmp)
     {
    -	struct batadv_tp_vars *tp_vars;
    +	struct batadv_tp_vars *tp_vars = NULL;
     
     	spin_lock_bh(&bat_priv->tp_list_lock);
    +	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
    +		goto out_unlock;
    +
     	tp_vars = batadv_tp_list_find_session(bat_priv, icmp->orig,
     					      icmp->session);
     	if (tp_vars)
    @@ -1464,6 +1474,9 @@ void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb)
     {
     	struct batadv_icmp_tp_packet *icmp;
     
    +	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
    +		goto out;
    +
     	icmp = (struct batadv_icmp_tp_packet *)skb->data;
     
     	switch (icmp->subtype) {
    @@ -1478,6 +1491,8 @@ void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb)
     			   "Received unknown TP Metric packet type %u\n",
     			   icmp->subtype);
     	}
    +
    +out:
     	consume_skb(skb);
     }
     
    -- 
    cgit 1.3-korg
    
    
    
e1e2194cc725

batman-adv: reject new tp_meter sessions during teardown

1 file changed · +16 2
  • net/batman-adv/tp_meter.c+16 2 modified
    diff --git a/net/batman-adv/tp_meter.c b/net/batman-adv/tp_meter.c
    index 350b149e48bebf..f3c4b5e8427291 100644
    --- a/net/batman-adv/tp_meter.c
    +++ b/net/batman-adv/tp_meter.c
    @@ -947,6 +947,13 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst,
     
     	/* look for an already existing test towards this node */
     	spin_lock_bh(&bat_priv->tp_list_lock);
    +	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) {
    +		spin_unlock_bh(&bat_priv->tp_list_lock);
    +		batadv_tp_batctl_error_notify(BATADV_TP_REASON_DST_UNREACHABLE,
    +					      dst, bat_priv, session_cookie);
    +		return;
    +	}
    +
     	tp_vars = batadv_tp_list_find(bat_priv, dst);
     	if (tp_vars) {
     		spin_unlock_bh(&bat_priv->tp_list_lock);
    @@ -1329,9 +1336,12 @@ static struct batadv_tp_vars *
     batadv_tp_init_recv(struct batadv_priv *bat_priv,
     		    const struct batadv_icmp_tp_packet *icmp)
     {
    -	struct batadv_tp_vars *tp_vars;
    +	struct batadv_tp_vars *tp_vars = NULL;
     
     	spin_lock_bh(&bat_priv->tp_list_lock);
    +	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
    +		goto out_unlock;
    +
     	tp_vars = batadv_tp_list_find_session(bat_priv, icmp->orig,
     					      icmp->session);
     	if (tp_vars)
    @@ -1464,6 +1474,9 @@ void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb)
     {
     	struct batadv_icmp_tp_packet *icmp;
     
    +	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
    +		goto out;
    +
     	icmp = (struct batadv_icmp_tp_packet *)skb->data;
     
     	switch (icmp->subtype) {
    @@ -1478,6 +1491,8 @@ void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb)
     			   "Received unknown TP Metric packet type %u\n",
     			   icmp->subtype);
     	}
    +
    +out:
     	consume_skb(skb);
     }
     
    -- 
    cgit 1.3-korg
    
    
    
ff93f86ecbb5

batman-adv: reject new tp_meter sessions during teardown

1 file changed · +16 2
  • net/batman-adv/tp_meter.c+16 2 modified
    diff --git a/net/batman-adv/tp_meter.c b/net/batman-adv/tp_meter.c
    index 7f3dd3c393e07a..56831f9fb071f5 100644
    --- a/net/batman-adv/tp_meter.c
    +++ b/net/batman-adv/tp_meter.c
    @@ -947,6 +947,13 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst,
     
     	/* look for an already existing test towards this node */
     	spin_lock_bh(&bat_priv->tp_list_lock);
    +	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) {
    +		spin_unlock_bh(&bat_priv->tp_list_lock);
    +		batadv_tp_batctl_error_notify(BATADV_TP_REASON_DST_UNREACHABLE,
    +					      dst, bat_priv, session_cookie);
    +		return;
    +	}
    +
     	tp_vars = batadv_tp_list_find(bat_priv, dst);
     	if (tp_vars) {
     		spin_unlock_bh(&bat_priv->tp_list_lock);
    @@ -1329,9 +1336,12 @@ static struct batadv_tp_vars *
     batadv_tp_init_recv(struct batadv_priv *bat_priv,
     		    const struct batadv_icmp_tp_packet *icmp)
     {
    -	struct batadv_tp_vars *tp_vars;
    +	struct batadv_tp_vars *tp_vars = NULL;
     
     	spin_lock_bh(&bat_priv->tp_list_lock);
    +	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
    +		goto out_unlock;
    +
     	tp_vars = batadv_tp_list_find_session(bat_priv, icmp->orig,
     					      icmp->session);
     	if (tp_vars)
    @@ -1464,6 +1474,9 @@ void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb)
     {
     	struct batadv_icmp_tp_packet *icmp;
     
    +	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
    +		goto out;
    +
     	icmp = (struct batadv_icmp_tp_packet *)skb->data;
     
     	switch (icmp->subtype) {
    @@ -1478,6 +1491,8 @@ void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb)
     			   "Received unknown TP Metric packet type %u\n",
     			   icmp->subtype);
     	}
    +
    +out:
     	consume_skb(skb);
     }
     
    -- 
    cgit 1.3-korg
    
    
    
324354359242

batman-adv: reject new tp_meter sessions during teardown

1 file changed · +16 2
  • net/batman-adv/tp_meter.c+16 2 modified
    diff --git a/net/batman-adv/tp_meter.c b/net/batman-adv/tp_meter.c
    index 2e42f6b348c83d..d9a80e459c2e4a 100644
    --- a/net/batman-adv/tp_meter.c
    +++ b/net/batman-adv/tp_meter.c
    @@ -947,6 +947,13 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst,
     
     	/* look for an already existing test towards this node */
     	spin_lock_bh(&bat_priv->tp_list_lock);
    +	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) {
    +		spin_unlock_bh(&bat_priv->tp_list_lock);
    +		batadv_tp_batctl_error_notify(BATADV_TP_REASON_DST_UNREACHABLE,
    +					      dst, bat_priv, session_cookie);
    +		return;
    +	}
    +
     	tp_vars = batadv_tp_list_find(bat_priv, dst);
     	if (tp_vars) {
     		spin_unlock_bh(&bat_priv->tp_list_lock);
    @@ -1329,9 +1336,12 @@ static struct batadv_tp_vars *
     batadv_tp_init_recv(struct batadv_priv *bat_priv,
     		    const struct batadv_icmp_tp_packet *icmp)
     {
    -	struct batadv_tp_vars *tp_vars;
    +	struct batadv_tp_vars *tp_vars = NULL;
     
     	spin_lock_bh(&bat_priv->tp_list_lock);
    +	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
    +		goto out_unlock;
    +
     	tp_vars = batadv_tp_list_find_session(bat_priv, icmp->orig,
     					      icmp->session);
     	if (tp_vars)
    @@ -1464,6 +1474,9 @@ void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb)
     {
     	struct batadv_icmp_tp_packet *icmp;
     
    +	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
    +		goto out;
    +
     	icmp = (struct batadv_icmp_tp_packet *)skb->data;
     
     	switch (icmp->subtype) {
    @@ -1478,6 +1491,8 @@ void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb)
     			   "Received unknown TP Metric packet type %u\n",
     			   icmp->subtype);
     	}
    +
    +out:
     	consume_skb(skb);
     }
     
    -- 
    cgit 1.3-korg
    
    
    
ca39545cf07c

batman-adv: reject new tp_meter sessions during teardown

1 file changed · +16 2
  • net/batman-adv/tp_meter.c+16 2 modified
    diff --git a/net/batman-adv/tp_meter.c b/net/batman-adv/tp_meter.c
    index 2e42f6b348c83d..d9a80e459c2e4a 100644
    --- a/net/batman-adv/tp_meter.c
    +++ b/net/batman-adv/tp_meter.c
    @@ -947,6 +947,13 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst,
     
     	/* look for an already existing test towards this node */
     	spin_lock_bh(&bat_priv->tp_list_lock);
    +	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) {
    +		spin_unlock_bh(&bat_priv->tp_list_lock);
    +		batadv_tp_batctl_error_notify(BATADV_TP_REASON_DST_UNREACHABLE,
    +					      dst, bat_priv, session_cookie);
    +		return;
    +	}
    +
     	tp_vars = batadv_tp_list_find(bat_priv, dst);
     	if (tp_vars) {
     		spin_unlock_bh(&bat_priv->tp_list_lock);
    @@ -1329,9 +1336,12 @@ static struct batadv_tp_vars *
     batadv_tp_init_recv(struct batadv_priv *bat_priv,
     		    const struct batadv_icmp_tp_packet *icmp)
     {
    -	struct batadv_tp_vars *tp_vars;
    +	struct batadv_tp_vars *tp_vars = NULL;
     
     	spin_lock_bh(&bat_priv->tp_list_lock);
    +	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
    +		goto out_unlock;
    +
     	tp_vars = batadv_tp_list_find_session(bat_priv, icmp->orig,
     					      icmp->session);
     	if (tp_vars)
    @@ -1464,6 +1474,9 @@ void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb)
     {
     	struct batadv_icmp_tp_packet *icmp;
     
    +	if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
    +		goto out;
    +
     	icmp = (struct batadv_icmp_tp_packet *)skb->data;
     
     	switch (icmp->subtype) {
    @@ -1478,6 +1491,8 @@ void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb)
     			   "Received unknown TP Metric packet type %u\n",
     			   icmp->subtype);
     	}
    +
    +out:
     	consume_skb(skb);
     }
     
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"Missing state check in tp_meter allows new sender/receiver sessions to be created after the mesh has left BATADV_MESH_ACTIVE."

Attack vector

An attacker on the mesh network can send crafted ICMP throughput-meter packets (or trigger a local batctl tp_meter start command) during the brief window when the mesh interface is being torn down but before the tp_meter module has fully shut down. The functions batadv_tp_start, batadv_tp_init_recv, and batadv_tp_meter_recv in net/batman-adv/tp_meter.c previously did not check bat_priv->mesh_state, so they would proceed to allocate and initialize tp_vars structures even after the mesh state had transitioned away from BATADV_MESH_ACTIVE [patch_id=2897760]. This creates a use-after-free or race condition against the concurrent teardown code that is freeing the same data structures.

Affected code

The vulnerability exists in net/batman-adv/tp_meter.c in three functions: batadv_tp_start (line ~947), batadv_tp_init_recv (line ~1329), and batadv_tp_meter_recv (line ~1464) [patch_id=2897760]. All three lacked a check of bat_priv->mesh_state before proceeding with session creation or packet processing.

What the fix does

The patch adds an early check of atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE at three entry points in net/batman-adv/tp_meter.c [patch_id=2897760]. In batadv_tp_start, the check is placed after acquiring the tp_list_lock, returning with an error notification if the mesh is not active. In batadv_tp_init_recv, the check jumps to out_unlock, releasing the lock without creating a new receiver session. In batadv_tp_meter_recv, the check jumps to the out label, which consumes the skb without processing it. These guards ensure no new tp_meter sessions are created once teardown has begun, closing the race window.

Preconditions

  • configThe mesh interface must be in the process of being torn down (mesh_state != BATADV_MESH_ACTIVE)
  • networkAttacker must be able to send ICMP throughput-meter packets to the victim node, or have local access to trigger batctl tp_meter start

Generated on May 28, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.