[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250225141157-oscmaes92@gmail.com>
Date: Tue, 25 Feb 2025 15:11:57 +0100
From: Oscar Maes <oscmaes92@...il.com>
To: Ido Schimmel <idosch@...sch.org>
Cc: netdev@...r.kernel.org, davem@...emloft.net, edumazet@...gle.com,
kuba@...nel.org, pabeni@...hat.com, horms@...nel.org,
viro@...iv.linux.org.uk, jiri@...nulli.us,
linux-kernel@...r.kernel.org, security@...nel.org,
syzbot <syzbot+91161fe81857b396c8a0@...kaller.appspotmail.com>
Subject: Re: [PATCH net] net: 802: enforce underlying device type for GARP
and MRP
On Wed, Feb 12, 2025 at 04:29:43PM +0200, Ido Schimmel wrote:
> On Wed, Feb 12, 2025 at 12:32:18PM +0100, Oscar Maes wrote:
> > When creating a VLAN device, we initialize GARP (garp_init_applicant)
> > and MRP (mrp_init_applicant) for the underlying device.
> >
> > As part of the initialization process, we add the multicast address of
> > each applicant to the underlying device, by calling dev_mc_add.
> >
> > __dev_mc_add uses dev->addr_len to determine the length of the new
> > multicast address.
> >
> > This causes an out-of-bounds read if dev->addr_len is greater than 6,
> > since the multicast addresses provided by GARP and MRP are only 6 bytes
> > long.
> >
> > This behaviour can be reproduced using the following commands:
> >
> > ip tunnel add gretest mode ip6gre local ::1 remote ::2 dev lo
> > ip l set up dev gretest
> > ip link add link gretest name vlantest type vlan id 100
> >
> > Then, the following command will display the address of garp_pdu_rcv:
> >
> > ip maddr show | grep 01:80:c2:00:00:21
> >
> > Fix this by enforcing the type and address length of
> > the underlying device during GARP and MRP initialization.
> >
> > Fixes: 22bedad3ce11 ("net: convert multicast list to list_head")
> > Reported-by: syzbot <syzbot+91161fe81857b396c8a0@...kaller.appspotmail.com>
> > Closes: https://lore.kernel.org/netdev/000000000000ca9a81061a01ec20@google.com/
> > Signed-off-by: Oscar Maes <oscmaes92@...il.com>
> > ---
> > net/802/garp.c | 5 +++++
> > net/802/mrp.c | 5 +++++
> > 2 files changed, 10 insertions(+)
> >
> > diff --git a/net/802/garp.c b/net/802/garp.c
> > index 27f0ab146..2f383ee73 100644
> > --- a/net/802/garp.c
> > +++ b/net/802/garp.c
> > @@ -9,6 +9,7 @@
> > #include <linux/skbuff.h>
> > #include <linux/netdevice.h>
> > #include <linux/etherdevice.h>
> > +#include <linux/if_arp.h>
> > #include <linux/rtnetlink.h>
> > #include <linux/llc.h>
> > #include <linux/slab.h>
> > @@ -574,6 +575,10 @@ int garp_init_applicant(struct net_device *dev, struct garp_application *appl)
> >
> > ASSERT_RTNL();
> >
> > + err = -EINVAL;
> > + if (dev->type != ARPHRD_ETHER || dev->addr_len != ETH_ALEN)
>
> Checking for 'ARPHRD_ETHER' is not enough? Other virtual devices such as
> macsec, macvlan and ipvlan only look at 'dev->type' AFAICT.
Agreed, I will change this.
>
> Also, how about moving this to vlan_check_real_dev()? It's common to
> both the IOCTL and netlink paths.
{garp,mrp}_init_applicant assume that the address length is 6-bytes, when they call dev_mc_add
with a 6-byte buffer.
I think that the ARPHRD check should be right before calling dev_mc_add.
Currently, GARP is only used by VLAN, which means your suggestion would technically work,
but this assumption might be violated by future protocol implementations like GMRP, which
could potentially resurface this bug.
>
> > + goto err1;
> > +
> > if (!rtnl_dereference(dev->garp_port)) {
> > err = garp_init_port(dev);
> > if (err < 0)
> > diff --git a/net/802/mrp.c b/net/802/mrp.c
> > index e0c96d0da..1efee0b39 100644
> > --- a/net/802/mrp.c
> > +++ b/net/802/mrp.c
> > @@ -12,6 +12,7 @@
> > #include <linux/skbuff.h>
> > #include <linux/netdevice.h>
> > #include <linux/etherdevice.h>
> > +#include <linux/if_arp.h>
> > #include <linux/rtnetlink.h>
> > #include <linux/slab.h>
> > #include <linux/module.h>
> > @@ -859,6 +860,10 @@ int mrp_init_applicant(struct net_device *dev, struct mrp_application *appl)
> >
> > ASSERT_RTNL();
> >
> > + err = -EINVAL;
> > + if (dev->type != ARPHRD_ETHER || dev->addr_len != ETH_ALEN)
> > + goto err1;
> > +
> > if (!rtnl_dereference(dev->mrp_port)) {
> > err = mrp_init_port(dev);
> > if (err < 0)
> > --
> > 2.39.5
> >
> >
Powered by blists - more mailing lists