2020-07-05 18:28:54

by Linus Lüssing

[permalink] [raw]
Subject: [PATCH net] bridge: mcast: Fix MLD2 Report IPv6 payload length check

Commit e57f61858b7c ("net: bridge: mcast: fix stale nsrcs pointer in
igmp3/mld2 report handling") introduced a small bug which would potentially
lead to accepting an MLD2 Report with a broken IPv6 header payload length
field.

The check needs to take into account the 2 bytes for the "Number of
Sources" field in the "Multicast Address Record" before reading it.
And not the size of a pointer to this field.

Fixes: e57f61858b7c ("net: bridge: mcast: fix stale nsrcs pointer in igmp3/mld2 report handling")
Signed-off-by: Linus Lüssing <[email protected]>
---
net/bridge/br_multicast.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 83490bf73a13..4c4a93abde68 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -1000,21 +1000,21 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br,
num = ntohs(icmp6h->icmp6_dataun.un_data16[1]);
len = skb_transport_offset(skb) + sizeof(*icmp6h);

for (i = 0; i < num; i++) {
__be16 *_nsrcs, __nsrcs;
u16 nsrcs;

nsrcs_offset = len + offsetof(struct mld2_grec, grec_nsrcs);

if (skb_transport_offset(skb) + ipv6_transport_len(skb) <
- nsrcs_offset + sizeof(_nsrcs))
+ nsrcs_offset + sizeof(__nsrcs))
return -EINVAL;

_nsrcs = skb_header_pointer(skb, nsrcs_offset,
sizeof(__nsrcs), &__nsrcs);
if (!_nsrcs)
return -EINVAL;

nsrcs = ntohs(*_nsrcs);
grec_len = struct_size(grec, grec_src, nsrcs);

--
2.27.0


2020-07-05 18:35:23

by Nikolay Aleksandrov

[permalink] [raw]
Subject: Re: [PATCH net] bridge: mcast: Fix MLD2 Report IPv6 payload length check

On 05/07/2020 21:22, Linus Lüssing wrote:
> Commit e57f61858b7c ("net: bridge: mcast: fix stale nsrcs pointer in
> igmp3/mld2 report handling") introduced a small bug which would potentially
> lead to accepting an MLD2 Report with a broken IPv6 header payload length
> field.
>
> The check needs to take into account the 2 bytes for the "Number of
> Sources" field in the "Multicast Address Record" before reading it.
> And not the size of a pointer to this field.
>
> Fixes: e57f61858b7c ("net: bridge: mcast: fix stale nsrcs pointer in igmp3/mld2 report handling")
> Signed-off-by: Linus Lüssing <[email protected]>
> ---
> net/bridge/br_multicast.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>

I'd rather be more concerned with it rejecting a valid report due to wrong size. The ptr
size would always be bigger. :)

Thanks!
Acked-by: Nikolay Aleksandrov <[email protected]>

> diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
> index 83490bf73a13..4c4a93abde68 100644
> --- a/net/bridge/br_multicast.c
> +++ b/net/bridge/br_multicast.c
> @@ -1000,21 +1000,21 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br,
> num = ntohs(icmp6h->icmp6_dataun.un_data16[1]);
> len = skb_transport_offset(skb) + sizeof(*icmp6h);
>
> for (i = 0; i < num; i++) {
> __be16 *_nsrcs, __nsrcs;
> u16 nsrcs;
>
> nsrcs_offset = len + offsetof(struct mld2_grec, grec_nsrcs);
>
> if (skb_transport_offset(skb) + ipv6_transport_len(skb) <
> - nsrcs_offset + sizeof(_nsrcs))
> + nsrcs_offset + sizeof(__nsrcs))
> return -EINVAL;
>
> _nsrcs = skb_header_pointer(skb, nsrcs_offset,
> sizeof(__nsrcs), &__nsrcs);
> if (!_nsrcs)
> return -EINVAL;
>
> nsrcs = ntohs(*_nsrcs);
> grec_len = struct_size(grec, grec_src, nsrcs);
>
>

2020-07-05 19:09:26

by Linus Lüssing

[permalink] [raw]
Subject: Re: [PATCH net] bridge: mcast: Fix MLD2 Report IPv6 payload length check

On Sun, Jul 05, 2020 at 09:33:13PM +0300, Nikolay Aleksandrov wrote:
> On 05/07/2020 21:22, Linus Lüssing wrote:
> > Commit e57f61858b7c ("net: bridge: mcast: fix stale nsrcs pointer in
> > igmp3/mld2 report handling") introduced a small bug which would potentially
> > lead to accepting an MLD2 Report with a broken IPv6 header payload length
> > field.
> >
> > The check needs to take into account the 2 bytes for the "Number of
> > Sources" field in the "Multicast Address Record" before reading it.
> > And not the size of a pointer to this field.
> >
> > Fixes: e57f61858b7c ("net: bridge: mcast: fix stale nsrcs pointer in igmp3/mld2 report handling")
> > Signed-off-by: Linus Lüssing <[email protected]>
> > ---
> > net/bridge/br_multicast.c | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
>
> I'd rather be more concerned with it rejecting a valid report due to wrong size. The ptr
> size would always be bigger. :)
>
> Thanks!
> Acked-by: Nikolay Aleksandrov <[email protected]>

Aiy, you're right, it's the other way round. I'll update the
commit message and send a v2 in a minute, with your Acked-by
included.

2020-07-05 19:12:46

by Nikolay Aleksandrov

[permalink] [raw]
Subject: Re: [PATCH net] bridge: mcast: Fix MLD2 Report IPv6 payload length check

On 7/5/20 10:08 PM, Linus Lüssing wrote:
> On Sun, Jul 05, 2020 at 09:33:13PM +0300, Nikolay Aleksandrov wrote:
>> On 05/07/2020 21:22, Linus Lüssing wrote:
>>> Commit e57f61858b7c ("net: bridge: mcast: fix stale nsrcs pointer in
>>> igmp3/mld2 report handling") introduced a small bug which would potentially
>>> lead to accepting an MLD2 Report with a broken IPv6 header payload length
>>> field.
>>>
>>> The check needs to take into account the 2 bytes for the "Number of
>>> Sources" field in the "Multicast Address Record" before reading it.
>>> And not the size of a pointer to this field.
>>>
>>> Fixes: e57f61858b7c ("net: bridge: mcast: fix stale nsrcs pointer in igmp3/mld2 report handling")
>>> Signed-off-by: Linus Lüssing <[email protected]>
>>> ---
>>> net/bridge/br_multicast.c | 2 +-
>>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>>
>>
>> I'd rather be more concerned with it rejecting a valid report due to wrong size. The ptr
>> size would always be bigger. :)
>>
>> Thanks!
>> Acked-by: Nikolay Aleksandrov <[email protected]>
>
> Aiy, you're right, it's the other way round. I'll update the
> commit message and send a v2 in a minute, with your Acked-by
> included.
>

By the way, I can't verify at the moment, but I think we can drop that whole
hunk altogether since skb_header_pointer() is used and it will simply return
an error if there isn't enough data for nsrcs.

2020-07-05 19:50:28

by Linus Lüssing

[permalink] [raw]
Subject: Re: [PATCH net] bridge: mcast: Fix MLD2 Report IPv6 payload length check

On Sun, Jul 05, 2020 at 10:11:39PM +0300, Nikolay Aleksandrov wrote:
> On 7/5/20 10:08 PM, Linus Lüssing wrote:
> > On Sun, Jul 05, 2020 at 09:33:13PM +0300, Nikolay Aleksandrov wrote:
> > > On 05/07/2020 21:22, Linus Lüssing wrote:
> > > > Commit e57f61858b7c ("net: bridge: mcast: fix stale nsrcs pointer in
> > > > igmp3/mld2 report handling") introduced a small bug which would potentially
> > > > lead to accepting an MLD2 Report with a broken IPv6 header payload length
> > > > field.
> > > >
> > > > The check needs to take into account the 2 bytes for the "Number of
> > > > Sources" field in the "Multicast Address Record" before reading it.
> > > > And not the size of a pointer to this field.
> > > >
> > > > Fixes: e57f61858b7c ("net: bridge: mcast: fix stale nsrcs pointer in igmp3/mld2 report handling")
> > > > Signed-off-by: Linus Lüssing <[email protected]>
> > > > ---
> > > > net/bridge/br_multicast.c | 2 +-
> > > > 1 file changed, 1 insertion(+), 1 deletion(-)
> > > >
> > >
> > > I'd rather be more concerned with it rejecting a valid report due to wrong size. The ptr
> > > size would always be bigger. :)
> > >
> > > Thanks!
> > > Acked-by: Nikolay Aleksandrov <[email protected]>
> >
> > Aiy, you're right, it's the other way round. I'll update the
> > commit message and send a v2 in a minute, with your Acked-by
> > included.
> >
>
> By the way, I can't verify at the moment, but I think we can drop that whole
> hunk altogether since skb_header_pointer() is used and it will simply return
> an error if there isn't enough data for nsrcs.
>

Hm, while unlikely, the IPv6 packet / header payload length might be
shorter than the frame / skb size.

And even though it wouldn't crash reading over the IPv6 packet
length, especially as skb_header_pointer() is used, I think we should
still avoid reading over the size indicated by the IPv6 header payload
length field, to stay protocol compliant.

Does that make sense?

2020-07-05 20:19:55

by Nikolay Aleksandrov

[permalink] [raw]
Subject: Re: [PATCH net] bridge: mcast: Fix MLD2 Report IPv6 payload length check

On 7/5/20 10:49 PM, Linus Lüssing wrote:
> On Sun, Jul 05, 2020 at 10:11:39PM +0300, Nikolay Aleksandrov wrote:
>> On 7/5/20 10:08 PM, Linus Lüssing wrote:
>>> On Sun, Jul 05, 2020 at 09:33:13PM +0300, Nikolay Aleksandrov wrote:
>>>> On 05/07/2020 21:22, Linus Lüssing wrote:
>>>>> Commit e57f61858b7c ("net: bridge: mcast: fix stale nsrcs pointer in
>>>>> igmp3/mld2 report handling") introduced a small bug which would potentially
>>>>> lead to accepting an MLD2 Report with a broken IPv6 header payload length
>>>>> field.
>>>>>
>>>>> The check needs to take into account the 2 bytes for the "Number of
>>>>> Sources" field in the "Multicast Address Record" before reading it.
>>>>> And not the size of a pointer to this field.
>>>>>
>>>>> Fixes: e57f61858b7c ("net: bridge: mcast: fix stale nsrcs pointer in igmp3/mld2 report handling")
>>>>> Signed-off-by: Linus Lüssing <[email protected]>
>>>>> ---
>>>>> net/bridge/br_multicast.c | 2 +-
>>>>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>>>>
>>>>
>>>> I'd rather be more concerned with it rejecting a valid report due to wrong size. The ptr
>>>> size would always be bigger. :)
>>>>
>>>> Thanks!
>>>> Acked-by: Nikolay Aleksandrov <[email protected]>
>>>
>>> Aiy, you're right, it's the other way round. I'll update the
>>> commit message and send a v2 in a minute, with your Acked-by
>>> included.
>>>
>>
>> By the way, I can't verify at the moment, but I think we can drop that whole
>> hunk altogether since skb_header_pointer() is used and it will simply return
>> an error if there isn't enough data for nsrcs.
>>
>
> Hm, while unlikely, the IPv6 packet / header payload length might be
> shorter than the frame / skb size.
>
> And even though it wouldn't crash reading over the IPv6 packet
> length, especially as skb_header_pointer() is used, I think we should
> still avoid reading over the size indicated by the IPv6 header payload
> length field, to stay protocol compliant.
>
> Does that make sense?
>

Sure, I just thought the ipv6_mc_may_pull() call after that includes those 2 bytes as well, so
we're covered. That is, it seems to be doing the same check with the full grec size included.

2020-07-06 10:14:12

by Linus Lüssing

[permalink] [raw]
Subject: Re: [PATCH net] bridge: mcast: Fix MLD2 Report IPv6 payload length check

On Sun, Jul 05, 2020 at 11:18:36PM +0300, Nikolay Aleksandrov wrote:
> > > By the way, I can't verify at the moment, but I think we can drop that whole
> > > hunk altogether since skb_header_pointer() is used and it will simply return
> > > an error if there isn't enough data for nsrcs.
> > >
> >
> > Hm, while unlikely, the IPv6 packet / header payload length might be
> > shorter than the frame / skb size.
> >
> > And even though it wouldn't crash reading over the IPv6 packet
> > length, especially as skb_header_pointer() is used, I think we should
> > still avoid reading over the size indicated by the IPv6 header payload
> > length field, to stay protocol compliant.
> >
> > Does that make sense?
> >
>
> Sure, I just thought the ipv6_mc_may_pull() call after that includes those 2 bytes as well, so
> we're covered. That is, it seems to be doing the same check with the full grec size included.
>

Ah, okay, that's what you mean! You're right, technically the
ipv6_mc_may_pull() later would cover it, too. And it should work,
even if nsrcs were outside of the IPv6 packet and had a bogus
value. (I think.)

My brain linearly parsing the parser code would probably get a bit
confused initially, as it'd look like a bit like a bug. But the
current check for nsrcs might look confusing, too (q.e.d.).

So as you prefer, I'd be okay with both leaving that check for
consistency or removing it for brevity.