On 12/11/25 4:24 PM, Ales Musil wrote:
> The struct route_data includes an ovs_list, by copying it into vector
> we might be copying soon to be invalid pointers, in other words
> pointers to stack variables. This wasn't an issue until now because
> we didn't reference anything within the list, however it has become
> an issue with the nexthop reference added later on.
> 
> Fixes: 13d1a5cbae68 ("controller: Postpone the route deletion after the dump 
> is done.")
> Signed-off-by: Ales Musil <[email protected]>
> ---
> v3: New patch in the series.
> ---

Hi Ales,

Thanks for the patch!

>  controller/route-exchange-netlink.c | 72 ++++++++++++++---------------
>  controller/route-exchange-netlink.h |  7 ++-
>  controller/route.c                  | 12 +++++
>  controller/route.h                  |  3 ++
>  4 files changed, 54 insertions(+), 40 deletions(-)
> 
> diff --git a/controller/route-exchange-netlink.c 
> b/controller/route-exchange-netlink.c
> index 60bae4781..d6358343d 100644
> --- a/controller/route-exchange-netlink.c
> +++ b/controller/route-exchange-netlink.c
> @@ -97,11 +97,10 @@ re_nl_delete_vrf(const char *ifname)
>  
>  static int
>  modify_route(uint32_t type, uint32_t flags_arg, uint32_t table_id,
> -             const struct in6_addr *dst, unsigned int plen,
> -             unsigned int priority)
> +             const struct advertise_route_entry *re)
>  {
>      uint32_t flags = NLM_F_REQUEST | NLM_F_ACK;
> -    bool is_ipv4 = IN6_IS_ADDR_V4MAPPED(dst);
> +    bool is_ipv4 = IN6_IS_ADDR_V4MAPPED(&re->addr);
>      struct rtmsg *rt;
>      int err;
>  
> @@ -119,15 +118,16 @@ modify_route(uint32_t type, uint32_t flags_arg, 
> uint32_t table_id,
>      rt->rtm_protocol = RTPROT_OVN;
>      rt->rtm_type = RTN_BLACKHOLE;
>      rt->rtm_scope = RT_SCOPE_UNIVERSE;
> -    rt->rtm_dst_len = plen;
> +    rt->rtm_dst_len = re->plen;
>  
>      nl_msg_put_u32(&request, RTA_TABLE, table_id);
> -    nl_msg_put_u32(&request, RTA_PRIORITY, priority);
> +    nl_msg_put_u32(&request, RTA_PRIORITY, re->priority);
>  
>      if (is_ipv4) {
> -        nl_msg_put_be32(&request, RTA_DST, in6_addr_get_mapped_ipv4(dst));
> +        nl_msg_put_be32(&request, RTA_DST,
> +                        in6_addr_get_mapped_ipv4(&re->addr));
>      } else {
> -        nl_msg_put_in6_addr(&request, RTA_DST, dst);
> +        nl_msg_put_in6_addr(&request, RTA_DST, &re->addr);
>      }
>  
>      if (VLOG_IS_DBG_ENABLED()) {
> @@ -140,13 +140,13 @@ modify_route(uint32_t type, uint32_t flags_arg, 
> uint32_t table_id,
>          }
>  
>          ds_put_format(&msg, "table %"PRIu32 " for prefix ", table_id);
> -        if (IN6_IS_ADDR_V4MAPPED(dst)) {
> +        if (IN6_IS_ADDR_V4MAPPED(&re->addr)) {

We're changing this line anyway, I guess we could also just do:

if (is_ipv4) {

>              ds_put_format(&msg, IP_FMT,
> -                          IP_ARGS(in6_addr_get_mapped_ipv4(dst)));
> +                          IP_ARGS(in6_addr_get_mapped_ipv4(&re->addr)));
>          } else {
> -            ipv6_format_addr(dst, &msg);
> +            ipv6_format_addr(&re->addr, &msg);
>          }
> -        ds_put_format(&msg, "/%u", plen);
> +        ds_put_format(&msg, "/%u", re->plen);
>  
>          VLOG_DBG("%s", ds_cstr(&msg));
>          ds_destroy(&msg);
> @@ -159,8 +159,7 @@ modify_route(uint32_t type, uint32_t flags_arg, uint32_t 
> table_id,
>  }
>  
>  int
> -re_nl_add_route(uint32_t table_id, const struct in6_addr *dst,
> -                unsigned int plen, unsigned int priority)
> +re_nl_add_route(uint32_t table_id, const struct advertise_route_entry *re)
>  {
>      if (!TABLE_ID_VALID(table_id)) {
>          static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
> @@ -170,13 +169,11 @@ re_nl_add_route(uint32_t table_id, const struct 
> in6_addr *dst,
>          return EINVAL;
>      }
>  
> -    return modify_route(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, table_id,
> -                        dst, plen, priority);
> +    return modify_route(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, table_id, 
> re);
>  }
>  
>  int
> -re_nl_delete_route(uint32_t table_id, const struct in6_addr *dst,
> -                   unsigned int plen, unsigned int priority)
> +re_nl_delete_route(uint32_t table_id, const struct advertise_route_entry *re)
>  {
>      if (!TABLE_ID_VALID(table_id)) {
>          static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
> @@ -186,7 +183,7 @@ re_nl_delete_route(uint32_t table_id, const struct 
> in6_addr *dst,
>          return EINVAL;
>      }
>  
> -    return modify_route(RTM_DELROUTE, 0, table_id, dst, plen, priority);
> +    return modify_route(RTM_DELROUTE, 0, table_id, re);
>  }
>  
>  struct route_msg_handle_data {
> @@ -248,12 +245,14 @@ handle_route_msg(const struct route_table_msg *msg, 
> void *data)
>          return;
>      }
>  
> +    const struct advertise_route_entry re =
> +            advertise_route_from_route_data(rd);
>      if (handle_data->routes_to_advertise) {
> -        uint32_t hash = advertise_route_hash(&rd->rta_dst, rd->rtm_dst_len);
> +        uint32_t hash = advertise_route_hash(&re.addr, re.plen);
>          HMAP_FOR_EACH_WITH_HASH (ar, node, hash, handle_data->routes) {
> -            if (ipv6_addr_equals(&ar->addr, &rd->rta_dst)
> -                    && ar->plen == rd->rtm_dst_len
> -                    && ar->priority == rd->rta_priority) {
> +            if (ipv6_addr_equals(&ar->addr, &re.addr)
> +                    && ar->plen == re.plen
> +                    && ar->priority == re.priority) {
>                  hmapx_find_and_delete(handle_data->routes_to_advertise, ar);
>                  return;
>              }
> @@ -261,27 +260,26 @@ handle_route_msg(const struct route_table_msg *msg, 
> void *data)
>      }
>  
>      if (handle_data->stale_routes) {
> -        vector_push(handle_data->stale_routes, rd);
> +        vector_push(handle_data->stale_routes, &re);
>      }
>  }
>  
>  static int
> -re_nl_delete_stale_routes(const struct vector *stale_routes)
> +re_nl_delete_stale_routes(uint32_t table_id, const struct vector 
> *stale_routes)
>  {
>      int ret = 0;
>  
> -    const struct route_data *rd;
> -    VECTOR_FOR_EACH_PTR (stale_routes, rd) {
> -        int err = re_nl_delete_route(rd->rta_table_id, &rd->rta_dst,
> -                                     rd->rtm_dst_len, rd->rta_priority);
> +    const struct advertise_route_entry *re;
> +    VECTOR_FOR_EACH_PTR (stale_routes, re) {
> +        int err = re_nl_delete_route(table_id, re);
>          if (err) {
>              char addr_s[INET6_ADDRSTRLEN + 1];
>              static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
>              VLOG_WARN_RL(&rl, "Delete route table_id=%"PRIu32" dst=%s 
> plen=%d "
> -                         "failed: %s", rd->rta_table_id,
> +                         "failed: %s", table_id,
>                           ipv6_string_mapped(
> -                             addr_s, &rd->rta_dst) ? addr_s : "(invalid)",
> -                         rd->rtm_dst_len,
> +                             addr_s, &re->addr) ? addr_s : "(invalid)",
> +                         re->plen,
>                           ovs_strerror(err));
>              if (!ret) {
>                  ret = err;
> @@ -298,7 +296,8 @@ re_nl_sync_routes(uint32_t table_id, const struct hmap 
> *routes,
>                    const struct sbrec_datapath_binding *db)
>  {
>      struct hmapx routes_to_advertise = 
> HMAPX_INITIALIZER(&routes_to_advertise);
> -    struct vector stale_routes = VECTOR_EMPTY_INITIALIZER(struct route_data);
> +    struct vector stale_routes =
> +        VECTOR_EMPTY_INITIALIZER(struct advertise_route_entry);
>      struct advertise_route_entry *ar;
>  
>      HMAP_FOR_EACH (ar, node, routes) {
> @@ -318,14 +317,14 @@ re_nl_sync_routes(uint32_t table_id, const struct hmap 
> *routes,
>      };
>      route_table_dump_one_table(table_id, handle_route_msg, &data);
>  
> -    int ret = re_nl_delete_stale_routes(&stale_routes);
> +    int ret = re_nl_delete_stale_routes(table_id, &stale_routes);
>  
>      /* Add any remaining routes in the routes_to_advertise hmapx to the
>       * system routing table. */
>      struct hmapx_node *hn;
>      HMAPX_FOR_EACH (hn, &routes_to_advertise) {
>          ar = hn->data;
> -        int err = re_nl_add_route(table_id, &ar->addr, ar->plen, 
> ar->priority);
> +        int err = re_nl_add_route(table_id, ar);
>          if (err) {
>              char addr_s[INET6_ADDRSTRLEN + 1];
>              static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
> @@ -352,7 +351,8 @@ re_nl_sync_routes(uint32_t table_id, const struct hmap 
> *routes,
>  int
>  re_nl_cleanup_routes(uint32_t table_id)
>  {
> -    struct vector stale_routes = VECTOR_EMPTY_INITIALIZER(struct route_data);
> +    struct vector stale_routes =
> +        VECTOR_EMPTY_INITIALIZER(struct advertise_route_entry);
>      /* Remove routes from the system that are not in the host_routes hmap and
>       * remove entries from host_routes hmap that match routes already 
> installed
>       * in the system. */
> @@ -364,7 +364,7 @@ re_nl_cleanup_routes(uint32_t table_id)
>      };
>      route_table_dump_one_table(table_id, handle_route_msg, &data);
>  
> -    int ret = re_nl_delete_stale_routes(&stale_routes);
> +    int ret = re_nl_delete_stale_routes(table_id, &stale_routes);
>      vector_destroy(&stale_routes);
>  
>      return ret;
> diff --git a/controller/route-exchange-netlink.h 
> b/controller/route-exchange-netlink.h
> index 1741f761d..ad1f0783b 100644
> --- a/controller/route-exchange-netlink.h
> +++ b/controller/route-exchange-netlink.h
> @@ -52,10 +52,9 @@ struct re_nl_received_route_node {
>  int re_nl_create_vrf(const char *ifname, uint32_t table_id);
>  int re_nl_delete_vrf(const char *ifname);
>  
> -int re_nl_add_route(uint32_t table_id, const struct in6_addr *dst,
> -                    unsigned int plen, unsigned int priority);
> -int re_nl_delete_route(uint32_t table_id, const struct in6_addr *dst,
> -                       unsigned int plen, unsigned int priority);
> +int re_nl_add_route(uint32_t table_id, const struct advertise_route_entry *);
> +int re_nl_delete_route(uint32_t table_id,
> +                       const struct advertise_route_entry *);
>  
>  int re_nl_sync_routes(uint32_t table_id, const struct hmap *routes,
>                        struct vector *learned_routes,
> diff --git a/controller/route.c b/controller/route.c
> index 093306c5b..dcf1984ab 100644
> --- a/controller/route.c
> +++ b/controller/route.c
> @@ -31,6 +31,8 @@
>  #include "local_data.h"
>  #include "route.h"
>  
> +#include "route-table.h"
> +
>  VLOG_DEFINE_THIS_MODULE(exchange);
>  
>  #define PRIORITY_DEFAULT 1000
> @@ -49,6 +51,16 @@ advertise_route_hash(const struct in6_addr *dst, unsigned 
> int plen)
>      return hash_int(plen, hash);
>  }
>  
> +struct advertise_route_entry
> +advertise_route_from_route_data(const struct route_data *rd)
> +{
> +    return (struct advertise_route_entry) {
> +        .addr = rd->rta_dst,
> +        .plen = rd->rtm_dst_len,
> +        .priority = rd->rta_priority,
> +    };
> +}
> +
>  const struct sbrec_port_binding*
>  route_exchange_find_port(struct ovsdb_idl_index *sbrec_port_binding_by_name,
>                           const struct sbrec_chassis *chassis,
> diff --git a/controller/route.h b/controller/route.h
> index 5c800f4ab..a1dd61d53 100644
> --- a/controller/route.h
> +++ b/controller/route.h
> @@ -27,6 +27,7 @@
>  
>  struct hmap;
>  struct ovsdb_idl_index;
> +struct route_data;
>  struct sbrec_chassis;
>  struct sbrec_port_binding;
>  struct sbrec_datapath_binding;
> @@ -89,6 +90,8 @@ const struct sbrec_port_binding *route_exchange_find_port(
>      const struct sbrec_port_binding *pb,
>      const char **dynamic_routing_port_name);
>  uint32_t advertise_route_hash(const struct in6_addr *dst, unsigned int plen);
> +struct advertise_route_entry
> +advertise_route_from_route_data(const struct route_data *);
>  void route_run(struct route_ctx_in *, struct route_ctx_out *);
>  void route_cleanup(struct hmap *announce_routes);
>  uint32_t route_get_table_id(const struct sbrec_datapath_binding *);

Looks good to me, thanks!

Acked-by: Dumitru Ceara <[email protected]>

Regards,
Dumitru


_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to