diff mbox series

[ovs-dev] pinctrl: Cap the max size of a prefix delegation DUID value.

Message ID 20230714123907.417977-1-dceara@redhat.com
State Accepted
Headers show
Series [ovs-dev] pinctrl: Cap the max size of a prefix delegation DUID value. | expand

Checks

Context Check Description
ovsrobot/apply-robot warning apply and check: warning
ovsrobot/github-robot-_Build_and_Test fail github build: failed
ovsrobot/github-robot-_ovn-kubernetes success github build: passed

Commit Message

Dumitru Ceara July 14, 2023, 12:39 p.m. UTC
It's specified in RFC 8415.  This also avoids having to free/realloc the
pfd->uuid.data memory.  That part was not correct anyway and was flagged
by ASAN as a memleak:

  Direct leak of 42 byte(s) in 3 object(s) allocated from:
      #0 0x55e5b6354c9e in malloc (/workspace/ovn-tmp/controller/ovn-controller+0x2edc9e) (BuildId: f963f8c756bd5a2207a9b3c922d4362e46bb3162)
      #1 0x55e5b671878d in xmalloc__ /workspace/ovn-tmp/ovs/lib/util.c:140:15
      #2 0x55e5b671878d in xmalloc /workspace/ovn-tmp/ovs/lib/util.c:175:12
      #3 0x55e5b642cebc in pinctrl_parse_dhcpv6_reply /workspace/ovn-tmp/controller/pinctrl.c:997:20
      #4 0x55e5b642cebc in pinctrl_handle_dhcp6_server /workspace/ovn-tmp/controller/pinctrl.c:1040:9
      #5 0x55e5b642cebc in process_packet_in /workspace/ovn-tmp/controller/pinctrl.c:3210:9
      #6 0x55e5b642cebc in pinctrl_recv /workspace/ovn-tmp/controller/pinctrl.c:3290:9
      #7 0x55e5b642cebc in pinctrl_handler /workspace/ovn-tmp/controller/pinctrl.c:3385:17
      #8 0x55e5b66ef664 in ovsthread_wrapper /workspace/ovn-tmp/ovs/lib/ovs-thread.c:423:12
      #9 0x7faa30194b42  (/lib/x86_64-linux-gnu/libc.so.6+0x94b42) (BuildId: 69389d485a9793dbe873f0ea2c93e02efaa9aa3d)

Fixes: faa44a0c60a3 ("controller: IPv6 Prefix-Delegation: introduce RENEW/REBIND msg support")
Signed-off-by: Dumitru Ceara <dceara@redhat.com>
---
 controller/pinctrl.c | 33 ++++++++++++++++-----------------
 1 file changed, 16 insertions(+), 17 deletions(-)

Comments

Dumitru Ceara July 14, 2023, 12:44 p.m. UTC | #1
On 7/14/23 14:39, Dumitru Ceara wrote:
> It's specified in RFC 8415.  This also avoids having to free/realloc the
> pfd->uuid.data memory.  That part was not correct anyway and was flagged
> by ASAN as a memleak:
> 
>   Direct leak of 42 byte(s) in 3 object(s) allocated from:
>       #0 0x55e5b6354c9e in malloc (/workspace/ovn-tmp/controller/ovn-controller+0x2edc9e) (BuildId: f963f8c756bd5a2207a9b3c922d4362e46bb3162)
>       #1 0x55e5b671878d in xmalloc__ /workspace/ovn-tmp/ovs/lib/util.c:140:15
>       #2 0x55e5b671878d in xmalloc /workspace/ovn-tmp/ovs/lib/util.c:175:12
>       #3 0x55e5b642cebc in pinctrl_parse_dhcpv6_reply /workspace/ovn-tmp/controller/pinctrl.c:997:20
>       #4 0x55e5b642cebc in pinctrl_handle_dhcp6_server /workspace/ovn-tmp/controller/pinctrl.c:1040:9
>       #5 0x55e5b642cebc in process_packet_in /workspace/ovn-tmp/controller/pinctrl.c:3210:9
>       #6 0x55e5b642cebc in pinctrl_recv /workspace/ovn-tmp/controller/pinctrl.c:3290:9
>       #7 0x55e5b642cebc in pinctrl_handler /workspace/ovn-tmp/controller/pinctrl.c:3385:17
>       #8 0x55e5b66ef664 in ovsthread_wrapper /workspace/ovn-tmp/ovs/lib/ovs-thread.c:423:12
>       #9 0x7faa30194b42  (/lib/x86_64-linux-gnu/libc.so.6+0x94b42) (BuildId: 69389d485a9793dbe873f0ea2c93e02efaa9aa3d)
> 
> Fixes: faa44a0c60a3 ("controller: IPv6 Prefix-Delegation: introduce RENEW/REBIND msg support")

I forgot to add Ales as co-author, I apologize.

Co-authored-by: Ales Musil <amusil@redhat.com>
Signed-off-by: Ales Musil <amusil@redhat.com>

> Signed-off-by: Dumitru Ceara <dceara@redhat.com>
> ---
>  controller/pinctrl.c | 33 ++++++++++++++++-----------------
>  1 file changed, 16 insertions(+), 17 deletions(-)
> 
> diff --git a/controller/pinctrl.c b/controller/pinctrl.c
> index 6027ba0afb..bed90fe0b7 100644
> --- a/controller/pinctrl.c
> +++ b/controller/pinctrl.c
> @@ -674,6 +674,14 @@ enum {
>      PREFIX_REBIND,
>  };
>  
> +/* According to RFC 8415, section 11:
> + *   A DUID consists of a 2-octet type code represented in network byte
> + *   order, followed by a variable number of octets that make up the
> + *   actual identifier.  The length of the DUID (not including the type
> + *   code) is at least 1 octet and at most 128 octets.
> +*/
> +#define DHCPV6_MAX_DUID_LEN 130
> +
>  struct ipv6_prefixd_state {
>      long long int next_announce;
>      long long int last_complete;
> @@ -683,7 +691,7 @@ struct ipv6_prefixd_state {
>      struct eth_addr sa;
>      /* server_id_info */
>      struct {
> -        uint8_t *data;
> +        uint8_t data[DHCPV6_MAX_DUID_LEN];
>          uint8_t len;
>      } uuid;
>      struct in6_addr ipv6_addr;
> @@ -899,7 +907,7 @@ pinctrl_prefixd_state_handler(const struct flow *ip_flow,
>                                struct eth_addr sa, struct in6_addr server_addr,
>                                char prefix_len, unsigned t1, unsigned t2,
>                                unsigned plife_time, unsigned vlife_time,
> -                              uint8_t *uuid, uint8_t uuid_len)
> +                              const uint8_t *uuid, uint8_t uuid_len)
>  {
>      struct ipv6_prefixd_state *pfd;
>  
> @@ -908,7 +916,7 @@ pinctrl_prefixd_state_handler(const struct flow *ip_flow,
>          pfd->state = PREFIX_PENDING;
>          pfd->server_addr = server_addr;
>          pfd->sa = sa;
> -        pfd->uuid.data = uuid;
> +        memcpy(pfd->uuid.data, uuid, uuid_len);
>          pfd->uuid.len = uuid_len;
>          pfd->plife_time = plife_time * 1000;
>          pfd->vlife_time = vlife_time * 1000;
> @@ -933,8 +941,9 @@ pinctrl_parse_dhcpv6_reply(struct dp_packet *pkt_in,
>      unsigned char *in_dhcpv6_data = (unsigned char *)(udp_in + 1);
>      size_t dlen = MIN(ntohs(udp_in->udp_len), dp_packet_l4_size(pkt_in));
>      unsigned t1 = 0, t2 = 0, vlife_time = 0, plife_time = 0;
> -    uint8_t *end = (uint8_t *)udp_in + dlen, *uuid = NULL;
> +    uint8_t *end = (uint8_t *) udp_in + dlen;
>      uint8_t prefix_len = 0, uuid_len = 0;
> +    uint8_t uuid[DHCPV6_MAX_DUID_LEN];
>      struct in6_addr ipv6 = in6addr_any;
>      bool status = false;
>      unsigned aid = 0;
> @@ -993,8 +1002,7 @@ pinctrl_parse_dhcpv6_reply(struct dp_packet *pkt_in,
>              break;
>          }
>          case DHCPV6_OPT_SERVER_ID_CODE:
> -            uuid_len = ntohs(in_opt->len);
> -            uuid = xmalloc(uuid_len);
> +            uuid_len = MIN(ntohs(in_opt->len), DHCPV6_MAX_DUID_LEN);
>              memcpy(uuid, in_opt + 1, uuid_len);
>              break;
>          default:
> @@ -1014,8 +1022,6 @@ pinctrl_parse_dhcpv6_reply(struct dp_packet *pkt_in,
>          pinctrl_prefixd_state_handler(ip_flow, ipv6, aid, eth->eth_src,
>                                        ip6_src, prefix_len, t1, t2,
>                                        plife_time, vlife_time, uuid, uuid_len);
> -    } else if (uuid) {
> -        free(uuid);
>      }
>  }
>  
> @@ -1212,10 +1218,7 @@ static bool ipv6_prefixd_should_inject(void)
>          if (pfd->state == PREFIX_RENEW &&
>              cur_time > pfd->last_complete + pfd->t2) {
>              pfd->state = PREFIX_REBIND;
> -            if (pfd->uuid.len) {
> -                free(pfd->uuid.data);
> -                pfd->uuid.len = 0;
> -            }
> +            pfd->uuid.len = 0;
>              return true;
>          }
>          if (pfd->state == PREFIX_REBIND &&
> @@ -1409,12 +1412,8 @@ prepare_ipv6_prefixd(struct ovsdb_idl_txn *ovnsb_idl_txn,
>      SHASH_FOR_EACH_SAFE (iter, &ipv6_prefixd) {
>          struct ipv6_prefixd_state *pfd = iter->data;
>          if (pfd->last_used + IPV6_PREFIXD_STALE_TIMEOUT < time_msec()) {
> -            if (pfd->uuid.len) {
> -                free(pfd->uuid.data);
> -                pfd->uuid.len = 0;
> -            }
> -            free(pfd);
>              shash_delete(&ipv6_prefixd, iter);
> +            free(pfd);
>          }
>      }
>
Ales Musil July 14, 2023, 12:49 p.m. UTC | #2
On Fri, Jul 14, 2023 at 2:44 PM Dumitru Ceara <dceara@redhat.com> wrote:

> On 7/14/23 14:39, Dumitru Ceara wrote:
> > It's specified in RFC 8415.  This also avoids having to free/realloc the
> > pfd->uuid.data memory.  That part was not correct anyway and was flagged
> > by ASAN as a memleak:
> >
> >   Direct leak of 42 byte(s) in 3 object(s) allocated from:
> >       #0 0x55e5b6354c9e in malloc
> (/workspace/ovn-tmp/controller/ovn-controller+0x2edc9e) (BuildId:
> f963f8c756bd5a2207a9b3c922d4362e46bb3162)
> >       #1 0x55e5b671878d in xmalloc__
> /workspace/ovn-tmp/ovs/lib/util.c:140:15
> >       #2 0x55e5b671878d in xmalloc
> /workspace/ovn-tmp/ovs/lib/util.c:175:12
> >       #3 0x55e5b642cebc in pinctrl_parse_dhcpv6_reply
> /workspace/ovn-tmp/controller/pinctrl.c:997:20
> >       #4 0x55e5b642cebc in pinctrl_handle_dhcp6_server
> /workspace/ovn-tmp/controller/pinctrl.c:1040:9
> >       #5 0x55e5b642cebc in process_packet_in
> /workspace/ovn-tmp/controller/pinctrl.c:3210:9
> >       #6 0x55e5b642cebc in pinctrl_recv
> /workspace/ovn-tmp/controller/pinctrl.c:3290:9
> >       #7 0x55e5b642cebc in pinctrl_handler
> /workspace/ovn-tmp/controller/pinctrl.c:3385:17
> >       #8 0x55e5b66ef664 in ovsthread_wrapper
> /workspace/ovn-tmp/ovs/lib/ovs-thread.c:423:12
> >       #9 0x7faa30194b42  (/lib/x86_64-linux-gnu/libc.so.6+0x94b42)
> (BuildId: 69389d485a9793dbe873f0ea2c93e02efaa9aa3d)
> >
> > Fixes: faa44a0c60a3 ("controller: IPv6 Prefix-Delegation: introduce
> RENEW/REBIND msg support")
>
> I forgot to add Ales as co-author, I apologize.
>
> Co-authored-by: Ales Musil <amusil@redhat.com>
> Signed-off-by: Ales Musil <amusil@redhat.com>
>
> > Signed-off-by: Dumitru Ceara <dceara@redhat.com>
> > ---
> >  controller/pinctrl.c | 33 ++++++++++++++++-----------------
> >  1 file changed, 16 insertions(+), 17 deletions(-)
> >
> > diff --git a/controller/pinctrl.c b/controller/pinctrl.c
> > index 6027ba0afb..bed90fe0b7 100644
> > --- a/controller/pinctrl.c
> > +++ b/controller/pinctrl.c
> > @@ -674,6 +674,14 @@ enum {
> >      PREFIX_REBIND,
> >  };
> >
> > +/* According to RFC 8415, section 11:
> > + *   A DUID consists of a 2-octet type code represented in network byte
> > + *   order, followed by a variable number of octets that make up the
> > + *   actual identifier.  The length of the DUID (not including the type
> > + *   code) is at least 1 octet and at most 128 octets.
> > +*/
> > +#define DHCPV6_MAX_DUID_LEN 130
> > +
> >  struct ipv6_prefixd_state {
> >      long long int next_announce;
> >      long long int last_complete;
> > @@ -683,7 +691,7 @@ struct ipv6_prefixd_state {
> >      struct eth_addr sa;
> >      /* server_id_info */
> >      struct {
> > -        uint8_t *data;
> > +        uint8_t data[DHCPV6_MAX_DUID_LEN];
> >          uint8_t len;
> >      } uuid;
> >      struct in6_addr ipv6_addr;
> > @@ -899,7 +907,7 @@ pinctrl_prefixd_state_handler(const struct flow
> *ip_flow,
> >                                struct eth_addr sa, struct in6_addr
> server_addr,
> >                                char prefix_len, unsigned t1, unsigned t2,
> >                                unsigned plife_time, unsigned vlife_time,
> > -                              uint8_t *uuid, uint8_t uuid_len)
> > +                              const uint8_t *uuid, uint8_t uuid_len)
> >  {
> >      struct ipv6_prefixd_state *pfd;
> >
> > @@ -908,7 +916,7 @@ pinctrl_prefixd_state_handler(const struct flow
> *ip_flow,
> >          pfd->state = PREFIX_PENDING;
> >          pfd->server_addr = server_addr;
> >          pfd->sa = sa;
> > -        pfd->uuid.data = uuid;
> > +        memcpy(pfd->uuid.data, uuid, uuid_len);
> >          pfd->uuid.len = uuid_len;
> >          pfd->plife_time = plife_time * 1000;
> >          pfd->vlife_time = vlife_time * 1000;
> > @@ -933,8 +941,9 @@ pinctrl_parse_dhcpv6_reply(struct dp_packet *pkt_in,
> >      unsigned char *in_dhcpv6_data = (unsigned char *)(udp_in + 1);
> >      size_t dlen = MIN(ntohs(udp_in->udp_len),
> dp_packet_l4_size(pkt_in));
> >      unsigned t1 = 0, t2 = 0, vlife_time = 0, plife_time = 0;
> > -    uint8_t *end = (uint8_t *)udp_in + dlen, *uuid = NULL;
> > +    uint8_t *end = (uint8_t *) udp_in + dlen;
> >      uint8_t prefix_len = 0, uuid_len = 0;
> > +    uint8_t uuid[DHCPV6_MAX_DUID_LEN];
> >      struct in6_addr ipv6 = in6addr_any;
> >      bool status = false;
> >      unsigned aid = 0;
> > @@ -993,8 +1002,7 @@ pinctrl_parse_dhcpv6_reply(struct dp_packet *pkt_in,
> >              break;
> >          }
> >          case DHCPV6_OPT_SERVER_ID_CODE:
> > -            uuid_len = ntohs(in_opt->len);
> > -            uuid = xmalloc(uuid_len);
> > +            uuid_len = MIN(ntohs(in_opt->len), DHCPV6_MAX_DUID_LEN);
> >              memcpy(uuid, in_opt + 1, uuid_len);
> >              break;
> >          default:
> > @@ -1014,8 +1022,6 @@ pinctrl_parse_dhcpv6_reply(struct dp_packet
> *pkt_in,
> >          pinctrl_prefixd_state_handler(ip_flow, ipv6, aid, eth->eth_src,
> >                                        ip6_src, prefix_len, t1, t2,
> >                                        plife_time, vlife_time, uuid,
> uuid_len);
> > -    } else if (uuid) {
> > -        free(uuid);
> >      }
> >  }
> >
> > @@ -1212,10 +1218,7 @@ static bool ipv6_prefixd_should_inject(void)
> >          if (pfd->state == PREFIX_RENEW &&
> >              cur_time > pfd->last_complete + pfd->t2) {
> >              pfd->state = PREFIX_REBIND;
> > -            if (pfd->uuid.len) {
> > -                free(pfd->uuid.data);
> > -                pfd->uuid.len = 0;
> > -            }
> > +            pfd->uuid.len = 0;
> >              return true;
> >          }
> >          if (pfd->state == PREFIX_REBIND &&
> > @@ -1409,12 +1412,8 @@ prepare_ipv6_prefixd(struct ovsdb_idl_txn
> *ovnsb_idl_txn,
> >      SHASH_FOR_EACH_SAFE (iter, &ipv6_prefixd) {
> >          struct ipv6_prefixd_state *pfd = iter->data;
> >          if (pfd->last_used + IPV6_PREFIXD_STALE_TIMEOUT < time_msec()) {
> > -            if (pfd->uuid.len) {
> > -                free(pfd->uuid.data);
> > -                pfd->uuid.len = 0;
> > -            }
> > -            free(pfd);
> >              shash_delete(&ipv6_prefixd, iter);
> > +            free(pfd);
> >          }
> >      }
> >
>
>
Looks good to me, thanks.

Acked-by: Ales Musil <amusil@redhat.com>
0-day Robot July 14, 2023, 12:57 p.m. UTC | #3
Bleep bloop.  Greetings Dumitru Ceara, I am a robot and I have tried out your patch.
Thanks for your contribution.

I encountered some error that I wasn't expecting.  See the details below.


checkpatch:
WARNING: Unexpected sign-offs from developers who are not authors or co-authors or committers: Ales Musil <amusil@redhat.com>
Lines checked: 135, Warnings: 1, Errors: 0


Please check this out.  If you feel there has been an error, please email aconole@redhat.com

Thanks,
0-day Robot
Lorenzo Bianconi July 14, 2023, 3:17 p.m. UTC | #4
> It's specified in RFC 8415.  This also avoids having to free/realloc the
> pfd->uuid.data memory.  That part was not correct anyway and was flagged
> by ASAN as a memleak:
> 
>   Direct leak of 42 byte(s) in 3 object(s) allocated from:
>       #0 0x55e5b6354c9e in malloc (/workspace/ovn-tmp/controller/ovn-controller+0x2edc9e) (BuildId: f963f8c756bd5a2207a9b3c922d4362e46bb3162)
>       #1 0x55e5b671878d in xmalloc__ /workspace/ovn-tmp/ovs/lib/util.c:140:15
>       #2 0x55e5b671878d in xmalloc /workspace/ovn-tmp/ovs/lib/util.c:175:12
>       #3 0x55e5b642cebc in pinctrl_parse_dhcpv6_reply /workspace/ovn-tmp/controller/pinctrl.c:997:20
>       #4 0x55e5b642cebc in pinctrl_handle_dhcp6_server /workspace/ovn-tmp/controller/pinctrl.c:1040:9
>       #5 0x55e5b642cebc in process_packet_in /workspace/ovn-tmp/controller/pinctrl.c:3210:9
>       #6 0x55e5b642cebc in pinctrl_recv /workspace/ovn-tmp/controller/pinctrl.c:3290:9
>       #7 0x55e5b642cebc in pinctrl_handler /workspace/ovn-tmp/controller/pinctrl.c:3385:17
>       #8 0x55e5b66ef664 in ovsthread_wrapper /workspace/ovn-tmp/ovs/lib/ovs-thread.c:423:12
>       #9 0x7faa30194b42  (/lib/x86_64-linux-gnu/libc.so.6+0x94b42) (BuildId: 69389d485a9793dbe873f0ea2c93e02efaa9aa3d)
> 
> Fixes: faa44a0c60a3 ("controller: IPv6 Prefix-Delegation: introduce RENEW/REBIND msg support")
> Signed-off-by: Dumitru Ceara <dceara@redhat.com>
> ---
>  controller/pinctrl.c | 33 ++++++++++++++++-----------------
>  1 file changed, 16 insertions(+), 17 deletions(-)

thx for fixing it.

Acked-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>

> 
> diff --git a/controller/pinctrl.c b/controller/pinctrl.c
> index 6027ba0afb..bed90fe0b7 100644
> --- a/controller/pinctrl.c
> +++ b/controller/pinctrl.c
> @@ -674,6 +674,14 @@ enum {
>      PREFIX_REBIND,
>  };
>  
> +/* According to RFC 8415, section 11:
> + *   A DUID consists of a 2-octet type code represented in network byte
> + *   order, followed by a variable number of octets that make up the
> + *   actual identifier.  The length of the DUID (not including the type
> + *   code) is at least 1 octet and at most 128 octets.
> +*/
> +#define DHCPV6_MAX_DUID_LEN 130
> +
>  struct ipv6_prefixd_state {
>      long long int next_announce;
>      long long int last_complete;
> @@ -683,7 +691,7 @@ struct ipv6_prefixd_state {
>      struct eth_addr sa;
>      /* server_id_info */
>      struct {
> -        uint8_t *data;
> +        uint8_t data[DHCPV6_MAX_DUID_LEN];
>          uint8_t len;
>      } uuid;
>      struct in6_addr ipv6_addr;
> @@ -899,7 +907,7 @@ pinctrl_prefixd_state_handler(const struct flow *ip_flow,
>                                struct eth_addr sa, struct in6_addr server_addr,
>                                char prefix_len, unsigned t1, unsigned t2,
>                                unsigned plife_time, unsigned vlife_time,
> -                              uint8_t *uuid, uint8_t uuid_len)
> +                              const uint8_t *uuid, uint8_t uuid_len)
>  {
>      struct ipv6_prefixd_state *pfd;
>  
> @@ -908,7 +916,7 @@ pinctrl_prefixd_state_handler(const struct flow *ip_flow,
>          pfd->state = PREFIX_PENDING;
>          pfd->server_addr = server_addr;
>          pfd->sa = sa;
> -        pfd->uuid.data = uuid;
> +        memcpy(pfd->uuid.data, uuid, uuid_len);
>          pfd->uuid.len = uuid_len;
>          pfd->plife_time = plife_time * 1000;
>          pfd->vlife_time = vlife_time * 1000;
> @@ -933,8 +941,9 @@ pinctrl_parse_dhcpv6_reply(struct dp_packet *pkt_in,
>      unsigned char *in_dhcpv6_data = (unsigned char *)(udp_in + 1);
>      size_t dlen = MIN(ntohs(udp_in->udp_len), dp_packet_l4_size(pkt_in));
>      unsigned t1 = 0, t2 = 0, vlife_time = 0, plife_time = 0;
> -    uint8_t *end = (uint8_t *)udp_in + dlen, *uuid = NULL;
> +    uint8_t *end = (uint8_t *) udp_in + dlen;
>      uint8_t prefix_len = 0, uuid_len = 0;
> +    uint8_t uuid[DHCPV6_MAX_DUID_LEN];
>      struct in6_addr ipv6 = in6addr_any;
>      bool status = false;
>      unsigned aid = 0;
> @@ -993,8 +1002,7 @@ pinctrl_parse_dhcpv6_reply(struct dp_packet *pkt_in,
>              break;
>          }
>          case DHCPV6_OPT_SERVER_ID_CODE:
> -            uuid_len = ntohs(in_opt->len);
> -            uuid = xmalloc(uuid_len);
> +            uuid_len = MIN(ntohs(in_opt->len), DHCPV6_MAX_DUID_LEN);
>              memcpy(uuid, in_opt + 1, uuid_len);
>              break;
>          default:
> @@ -1014,8 +1022,6 @@ pinctrl_parse_dhcpv6_reply(struct dp_packet *pkt_in,
>          pinctrl_prefixd_state_handler(ip_flow, ipv6, aid, eth->eth_src,
>                                        ip6_src, prefix_len, t1, t2,
>                                        plife_time, vlife_time, uuid, uuid_len);
> -    } else if (uuid) {
> -        free(uuid);
>      }
>  }
>  
> @@ -1212,10 +1218,7 @@ static bool ipv6_prefixd_should_inject(void)
>          if (pfd->state == PREFIX_RENEW &&
>              cur_time > pfd->last_complete + pfd->t2) {
>              pfd->state = PREFIX_REBIND;
> -            if (pfd->uuid.len) {
> -                free(pfd->uuid.data);
> -                pfd->uuid.len = 0;
> -            }
> +            pfd->uuid.len = 0;
>              return true;
>          }
>          if (pfd->state == PREFIX_REBIND &&
> @@ -1409,12 +1412,8 @@ prepare_ipv6_prefixd(struct ovsdb_idl_txn *ovnsb_idl_txn,
>      SHASH_FOR_EACH_SAFE (iter, &ipv6_prefixd) {
>          struct ipv6_prefixd_state *pfd = iter->data;
>          if (pfd->last_used + IPV6_PREFIXD_STALE_TIMEOUT < time_msec()) {
> -            if (pfd->uuid.len) {
> -                free(pfd->uuid.data);
> -                pfd->uuid.len = 0;
> -            }
> -            free(pfd);
>              shash_delete(&ipv6_prefixd, iter);
> +            free(pfd);
>          }
>      }
>  
> -- 
> 2.31.1
>
Dumitru Ceara July 14, 2023, 8:55 p.m. UTC | #5
On 7/14/23 17:17, Lorenzo Bianconi wrote:
>> It's specified in RFC 8415.  This also avoids having to free/realloc the
>> pfd->uuid.data memory.  That part was not correct anyway and was flagged
>> by ASAN as a memleak:
>>
>>   Direct leak of 42 byte(s) in 3 object(s) allocated from:
>>       #0 0x55e5b6354c9e in malloc (/workspace/ovn-tmp/controller/ovn-controller+0x2edc9e) (BuildId: f963f8c756bd5a2207a9b3c922d4362e46bb3162)
>>       #1 0x55e5b671878d in xmalloc__ /workspace/ovn-tmp/ovs/lib/util.c:140:15
>>       #2 0x55e5b671878d in xmalloc /workspace/ovn-tmp/ovs/lib/util.c:175:12
>>       #3 0x55e5b642cebc in pinctrl_parse_dhcpv6_reply /workspace/ovn-tmp/controller/pinctrl.c:997:20
>>       #4 0x55e5b642cebc in pinctrl_handle_dhcp6_server /workspace/ovn-tmp/controller/pinctrl.c:1040:9
>>       #5 0x55e5b642cebc in process_packet_in /workspace/ovn-tmp/controller/pinctrl.c:3210:9
>>       #6 0x55e5b642cebc in pinctrl_recv /workspace/ovn-tmp/controller/pinctrl.c:3290:9
>>       #7 0x55e5b642cebc in pinctrl_handler /workspace/ovn-tmp/controller/pinctrl.c:3385:17
>>       #8 0x55e5b66ef664 in ovsthread_wrapper /workspace/ovn-tmp/ovs/lib/ovs-thread.c:423:12
>>       #9 0x7faa30194b42  (/lib/x86_64-linux-gnu/libc.so.6+0x94b42) (BuildId: 69389d485a9793dbe873f0ea2c93e02efaa9aa3d)
>>
>> Fixes: faa44a0c60a3 ("controller: IPv6 Prefix-Delegation: introduce RENEW/REBIND msg support")
>> Signed-off-by: Dumitru Ceara <dceara@redhat.com>
>> ---
>>  controller/pinctrl.c | 33 ++++++++++++++++-----------------
>>  1 file changed, 16 insertions(+), 17 deletions(-)
> 
> thx for fixing it.
> 
> Acked-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
> 

Thanks, Lorenzo and Ales!  I applied this to main and to all branches
down to 22.03.

Regards,
Dumitru
diff mbox series

Patch

diff --git a/controller/pinctrl.c b/controller/pinctrl.c
index 6027ba0afb..bed90fe0b7 100644
--- a/controller/pinctrl.c
+++ b/controller/pinctrl.c
@@ -674,6 +674,14 @@  enum {
     PREFIX_REBIND,
 };
 
+/* According to RFC 8415, section 11:
+ *   A DUID consists of a 2-octet type code represented in network byte
+ *   order, followed by a variable number of octets that make up the
+ *   actual identifier.  The length of the DUID (not including the type
+ *   code) is at least 1 octet and at most 128 octets.
+*/
+#define DHCPV6_MAX_DUID_LEN 130
+
 struct ipv6_prefixd_state {
     long long int next_announce;
     long long int last_complete;
@@ -683,7 +691,7 @@  struct ipv6_prefixd_state {
     struct eth_addr sa;
     /* server_id_info */
     struct {
-        uint8_t *data;
+        uint8_t data[DHCPV6_MAX_DUID_LEN];
         uint8_t len;
     } uuid;
     struct in6_addr ipv6_addr;
@@ -899,7 +907,7 @@  pinctrl_prefixd_state_handler(const struct flow *ip_flow,
                               struct eth_addr sa, struct in6_addr server_addr,
                               char prefix_len, unsigned t1, unsigned t2,
                               unsigned plife_time, unsigned vlife_time,
-                              uint8_t *uuid, uint8_t uuid_len)
+                              const uint8_t *uuid, uint8_t uuid_len)
 {
     struct ipv6_prefixd_state *pfd;
 
@@ -908,7 +916,7 @@  pinctrl_prefixd_state_handler(const struct flow *ip_flow,
         pfd->state = PREFIX_PENDING;
         pfd->server_addr = server_addr;
         pfd->sa = sa;
-        pfd->uuid.data = uuid;
+        memcpy(pfd->uuid.data, uuid, uuid_len);
         pfd->uuid.len = uuid_len;
         pfd->plife_time = plife_time * 1000;
         pfd->vlife_time = vlife_time * 1000;
@@ -933,8 +941,9 @@  pinctrl_parse_dhcpv6_reply(struct dp_packet *pkt_in,
     unsigned char *in_dhcpv6_data = (unsigned char *)(udp_in + 1);
     size_t dlen = MIN(ntohs(udp_in->udp_len), dp_packet_l4_size(pkt_in));
     unsigned t1 = 0, t2 = 0, vlife_time = 0, plife_time = 0;
-    uint8_t *end = (uint8_t *)udp_in + dlen, *uuid = NULL;
+    uint8_t *end = (uint8_t *) udp_in + dlen;
     uint8_t prefix_len = 0, uuid_len = 0;
+    uint8_t uuid[DHCPV6_MAX_DUID_LEN];
     struct in6_addr ipv6 = in6addr_any;
     bool status = false;
     unsigned aid = 0;
@@ -993,8 +1002,7 @@  pinctrl_parse_dhcpv6_reply(struct dp_packet *pkt_in,
             break;
         }
         case DHCPV6_OPT_SERVER_ID_CODE:
-            uuid_len = ntohs(in_opt->len);
-            uuid = xmalloc(uuid_len);
+            uuid_len = MIN(ntohs(in_opt->len), DHCPV6_MAX_DUID_LEN);
             memcpy(uuid, in_opt + 1, uuid_len);
             break;
         default:
@@ -1014,8 +1022,6 @@  pinctrl_parse_dhcpv6_reply(struct dp_packet *pkt_in,
         pinctrl_prefixd_state_handler(ip_flow, ipv6, aid, eth->eth_src,
                                       ip6_src, prefix_len, t1, t2,
                                       plife_time, vlife_time, uuid, uuid_len);
-    } else if (uuid) {
-        free(uuid);
     }
 }
 
@@ -1212,10 +1218,7 @@  static bool ipv6_prefixd_should_inject(void)
         if (pfd->state == PREFIX_RENEW &&
             cur_time > pfd->last_complete + pfd->t2) {
             pfd->state = PREFIX_REBIND;
-            if (pfd->uuid.len) {
-                free(pfd->uuid.data);
-                pfd->uuid.len = 0;
-            }
+            pfd->uuid.len = 0;
             return true;
         }
         if (pfd->state == PREFIX_REBIND &&
@@ -1409,12 +1412,8 @@  prepare_ipv6_prefixd(struct ovsdb_idl_txn *ovnsb_idl_txn,
     SHASH_FOR_EACH_SAFE (iter, &ipv6_prefixd) {
         struct ipv6_prefixd_state *pfd = iter->data;
         if (pfd->last_used + IPV6_PREFIXD_STALE_TIMEOUT < time_msec()) {
-            if (pfd->uuid.len) {
-                free(pfd->uuid.data);
-                pfd->uuid.len = 0;
-            }
-            free(pfd);
             shash_delete(&ipv6_prefixd, iter);
+            free(pfd);
         }
     }