Re: [PATCH batadv v2 5/5] batman-adv: v: stop OGMv2 on disabled interface

Yuan Tan <[email protected]>
Newsgroups org.open-mesh.lists.batman
Message-ID <CAPuPA7KEnOyK1cs1T=pQo7fye2TeMPZZw_pBiMCpJoQ4eXAE5g@mail.gmail.com>
On Wed, May 13, 2026 at 12:01 AM Sven Eckelmann <[email protected]> wrote:
>
> When a batadv_hard_iface is disabled, its mesh_iface pointer is set to
> NULL. However, batadv_v_ogm_send_meshif() may still dispatch OGMs via
> batadv_v_ogm_queue_on_if() for interfaces that have since lost their
> mesh_iface association. This results in a NULL pointer dereference when
> batadv_v_ogm_queue_on_if() unconditionally calls netdev_priv() on the
> now NULL hard_iface->mesh_iface to retrieve the batadv_priv.
>
> It is necessary to ensure that the batadv_v_ogm_queue_on_if() checks that
> it is using the same mesh_iface for which batadv_v_ogm_send_meshif() was
> called.
>
> Cc: [email protected]
> Fixes: 0da0035942d4 ("batman-adv: OGMv2 - add basic infrastructure")
> Reported-by: Yuan Tan <[email protected]>
> Reported-by: Yifan Wu <[email protected]>
> Reported-by: Juefei Pu <[email protected]>
> Reported-by: Xin Liu <[email protected]>
> Signed-off-by: Sven Eckelmann <[email protected]>
> ---
>  net/batman-adv/bat_v_ogm.c | 39 +++++++++++++++++++++++++++------------
>  1 file changed, 27 insertions(+), 12 deletions(-)
>
> diff --git a/net/batman-adv/bat_v_ogm.c b/net/batman-adv/bat_v_ogm.c
> index e3870492..0643a723 100644
> --- a/net/batman-adv/bat_v_ogm.c
> +++ b/net/batman-adv/bat_v_ogm.c
> @@ -113,14 +113,14 @@ static void batadv_v_ogm_start_timer(struct batadv_priv *bat_priv)
>
>  /**
>   * batadv_v_ogm_send_to_if() - send a batman ogm using a given interface
> + * @bat_priv: the bat priv with all the mesh interface information
>   * @skb: the OGM to send
>   * @hard_iface: the interface to use to send the OGM
>   */
> -static void batadv_v_ogm_send_to_if(struct sk_buff *skb,
> +static void batadv_v_ogm_send_to_if(struct batadv_priv *bat_priv,
> +                                   struct sk_buff *skb,
>                                     struct batadv_hard_iface *hard_iface)
>  {
> -       struct batadv_priv *bat_priv = netdev_priv(hard_iface->mesh_iface);
> -
>         if (hard_iface->if_status != BATADV_IF_ACTIVE) {
>                 kfree_skb(skb);
>                 return;
> @@ -187,6 +187,7 @@ static void batadv_v_ogm_aggr_list_free(struct batadv_hard_iface *hard_iface)
>
>  /**
>   * batadv_v_ogm_aggr_send() - flush & send aggregation queue
> + * @bat_priv: the bat priv with all the mesh interface information
>   * @hard_iface: the interface with the aggregation queue to flush
>   *
>   * Aggregates all OGMv2 packets currently in the aggregation queue into a
> @@ -196,7 +197,8 @@ static void batadv_v_ogm_aggr_list_free(struct batadv_hard_iface *hard_iface)
>   *
>   * Caller needs to hold the hard_iface->bat_v.aggr_list.lock.
>   */
> -static void batadv_v_ogm_aggr_send(struct batadv_hard_iface *hard_iface)
> +static void batadv_v_ogm_aggr_send(struct batadv_priv *bat_priv,
> +                                  struct batadv_hard_iface *hard_iface)
>  {
>         unsigned int aggr_len = hard_iface->bat_v.aggr_len;
>         struct sk_buff *skb_aggr;
> @@ -226,27 +228,32 @@ static void batadv_v_ogm_aggr_send(struct batadv_hard_iface *hard_iface)
>                 consume_skb(skb);
>         }
>
> -       batadv_v_ogm_send_to_if(skb_aggr, hard_iface);
> +       batadv_v_ogm_send_to_if(bat_priv, skb_aggr, hard_iface);
>  }
>
>  /**
>   * batadv_v_ogm_queue_on_if() - queue a batman ogm on a given interface
> + * @bat_priv: the bat priv with all the mesh interface information
>   * @skb: the OGM to queue
>   * @hard_iface: the interface to queue the OGM on
>   */
> -static void batadv_v_ogm_queue_on_if(struct sk_buff *skb,
> +static void batadv_v_ogm_queue_on_if(struct batadv_priv *bat_priv,
> +                                    struct sk_buff *skb,
>                                      struct batadv_hard_iface *hard_iface)
>  {
> -       struct batadv_priv *bat_priv = netdev_priv(hard_iface->mesh_iface);
> +       if (hard_iface->mesh_iface != bat_priv->mesh_iface) {
> +               kfree_skb(skb);
> +               return;
> +       }
>
>         if (!atomic_read(&bat_priv->aggregated_ogms)) {
> -               batadv_v_ogm_send_to_if(skb, hard_iface);
> +               batadv_v_ogm_send_to_if(bat_priv, skb, hard_iface);
>                 return;
>         }
>
>         spin_lock_bh(&hard_iface->bat_v.aggr_list.lock);
>         if (!batadv_v_ogm_queue_left(skb, hard_iface))
> -               batadv_v_ogm_aggr_send(hard_iface);
> +               batadv_v_ogm_aggr_send(bat_priv, hard_iface);
>
>         hard_iface->bat_v.aggr_len += batadv_v_ogm_len(skb);
>         __skb_queue_tail(&hard_iface->bat_v.aggr_list, skb);
> @@ -343,7 +350,7 @@ static void batadv_v_ogm_send_meshif(struct batadv_priv *bat_priv)
>                         break;
>                 }
>
> -               batadv_v_ogm_queue_on_if(skb_tmp, hard_iface);
> +               batadv_v_ogm_queue_on_if(bat_priv, skb_tmp, hard_iface);
>                 batadv_hardif_put(hard_iface);
>         }
>         rcu_read_unlock();
> @@ -383,12 +390,20 @@ void batadv_v_ogm_aggr_work(struct work_struct *work)
>  {
>         struct batadv_hard_iface_bat_v *batv;
>         struct batadv_hard_iface *hard_iface;
> +       struct batadv_priv *bat_priv;
> +       struct net_device *meshif;
>
>         batv = container_of(work, struct batadv_hard_iface_bat_v, aggr_wq.work);
>         hard_iface = container_of(batv, struct batadv_hard_iface, bat_v);
> +       meshif = hard_iface->mesh_iface;
> +
> +       if (!meshif)
> +               return;
> +
> +       bat_priv = netdev_priv(meshif);
>
>         spin_lock_bh(&hard_iface->bat_v.aggr_list.lock);
> -       batadv_v_ogm_aggr_send(hard_iface);
> +       batadv_v_ogm_aggr_send(bat_priv, hard_iface);
>         spin_unlock_bh(&hard_iface->bat_v.aggr_list.lock);
>
>         batadv_v_ogm_start_queue_timer(hard_iface);
> @@ -578,7 +593,7 @@ static void batadv_v_ogm_forward(struct batadv_priv *bat_priv,
>                    if_outgoing->net_dev->name, ntohl(ogm_forward->throughput),
>                    ogm_forward->ttl, if_incoming->net_dev->name);
>
> -       batadv_v_ogm_queue_on_if(skb, if_outgoing);
> +       batadv_v_ogm_queue_on_if(bat_priv, skb, if_outgoing);
>
>  out:
>         batadv_orig_ifinfo_put(orig_ifinfo);
>
> --
> 2.47.3
>

Reviewed-by: Yuan Tan <[email protected]>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.