Eelco Chaudron <echau...@redhat.com> writes:

> On 23 Jun 2025, at 14:37, Aaron Conole wrote:
>
>> Eelco Chaudron via dev <ovs-dev@openvswitch.org> writes:
>>
>>> If an MLD packet is not large enough to contain the
>>> message-specific data, it may lead to a NULL pointer access.
>>> This patch fixes the issue by adding appropriate length checks.
>>>
>>> Fixes: 06994f879c9d ("mcast-snooping: Add Multicast Listener
>>> Discovery support")
>>> Signed-off-by: Eelco Chaudron <echau...@redhat.com>
>>> ---
>>
>> Hi Eelco,
>>
>>>  lib/mcast-snooping.c | 8 ++++++++
>>>  1 file changed, 8 insertions(+)
>>>
>>> diff --git a/lib/mcast-snooping.c b/lib/mcast-snooping.c
>>> index b279c1229..1f290083e 100644
>>> --- a/lib/mcast-snooping.c
>>> +++ b/lib/mcast-snooping.c
>>> @@ -543,6 +543,14 @@ mcast_snooping_add_mld(struct mcast_snooping *ms,
>>>      offset += MLD_HEADER_LEN;
>>>      addr = dp_packet_at(p, offset, sizeof(struct in6_addr));
>>>
>>> +    if (!addr) {
>>> +        /* We error out if the provided packet is not large enough to 
>>> handle
>>> +         * the types below. The BUILD_ASSERT() ensures that we can always 
>>> reach
>>> +         * the MLD2_REPORT type. */
>>> +        BUILD_ASSERT(sizeof(struct mld2_record) > sizeof(struct in6_addr));
>>
>> Would it make sense instead to have a BUILD_ASSERT_DECL in lib/packets.h
>> that covers the ovs_16aligned_in6_addr type?  I think it might make it a
>> bit more readable (it's a bit jarring to see the build-time assert
>> here).  Then the mld2_record should be covered by default (since the
>> condition for sizeof union ovs_16aligned_in6_addr >= struct in6_addr
>> should carry forward).
>
> Thanks for the suggestion. I'm not sure I fully follow the idea of
> moving the BUILD_ASSERT_DECL to lib/packets.h. From my understanding,
> the assertion isn't related to the layout or size of the packet
> structures in general, but rather to the specific logic flow in this
> function.
>
> In particular, the addr variable is only meaningful in two of the
> three switch cases. The build-time assertion ensures that the third
> case is valid — specifically, that sizeof(struct mld2_record) is
> always greater than or equal to sizeof(struct in6_addr), which is
> required for the access pattern used later in the code.
>
> So while I agree the assert is a bit odd inline, it seems
> context-specific enough that putting it in a shared header like
> packets.h might reduce clarity rather than improve it.
>
> Thoughts?

Sure - here's the definition of mld2_record::

  #define MLD2_RECORD_LEN 20
  struct mld2_record {
      uint8_t type;
      uint8_t aux_len;
      ovs_be16 nsrcs;
      union ovs_16aligned_in6_addr maddr;
  };
  BUILD_ASSERT_DECL(MLD2_RECORD_LEN == sizeof(struct mld2_record));

Notice that mld2_record already contains a copy of
ovs_16aligned_in6_addr type.  That type looks like::

  union ovs_16aligned_in6_addr {
      ovs_be16 be16[8];
      ovs_16aligned_be32 be32[4];
  };

So I suggest adding::
  BUILD_ASSERT_DECL(sizeof(ovs_16aligned_in6_addr) >= sizeof(struct in6_addr))

mld2_record contains a copy, so it should always be >= the size, and
therefore we should have a correct structure.

Does it make sense?

>> Otherwise, the change looks good to me.
>>
>>> +        return 0;
>>> +    }
>>> +
>>>      switch (mld->type) {
>>>      case MLD_REPORT:
>>>          ret = mcast_snooping_add_group(ms, addr, vlan, port,

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to