diff mbox series

[net] lan966x: Fix crash when adding interface under a lag

Message ID 20240205080756.2134143-1-horatiu.vultur@microchip.com (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series [net] lan966x: Fix crash when adding interface under a lag | expand

Checks

Context Check Description
netdev/series_format success Single patches do not need cover letters
netdev/tree_selection success Clearly marked for net
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag present in non-next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 1064 this patch: 1064
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers success CCed 6 of 6 maintainers
netdev/build_clang success Errors and warnings before: 1081 this patch: 1081
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success Fixes tag looks correct
netdev/build_allmodconfig_warn success Errors and warnings before: 1081 this patch: 1081
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 26 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
netdev/contest success net-next-2024-02-05--12-00 (tests: 721)

Commit Message

Horatiu Vultur Feb. 5, 2024, 8:07 a.m. UTC
There is a crash when adding one of the lan966x interfaces under a lag
interface. The issue can be reproduced like this:
ip link add name bond0 type bond miimon 100 mode balance-xor
ip link set dev eth0 master bond0

The reason is because when adding a interface under the lag it would go
through all the ports and try to figure out which other ports are under
that lag interface. And the issue is that lan966x can have ports that are
NULL pointer as they are not probed. So then iterating over these ports
it would just crash as they are NULL pointers.
The fix consists in actually checking for NULL pointers before accessing
something from the ports. Like we do in other places.

Fixes: cabc9d49333d ("net: lan966x: Add lag support for lan966x")
Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
---
 drivers/net/ethernet/microchip/lan966x/lan966x_lag.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

Comments

Michal Swiatkowski Feb. 5, 2024, 8:44 a.m. UTC | #1
On Mon, Feb 05, 2024 at 09:07:56AM +0100, Horatiu Vultur wrote:
> There is a crash when adding one of the lan966x interfaces under a lag
> interface. The issue can be reproduced like this:
> ip link add name bond0 type bond miimon 100 mode balance-xor
> ip link set dev eth0 master bond0
> 
> The reason is because when adding a interface under the lag it would go
> through all the ports and try to figure out which other ports are under
> that lag interface. And the issue is that lan966x can have ports that are
> NULL pointer as they are not probed. So then iterating over these ports
> it would just crash as they are NULL pointers.
> The fix consists in actually checking for NULL pointers before accessing
> something from the ports. Like we do in other places.
> 
> Fixes: cabc9d49333d ("net: lan966x: Add lag support for lan966x")
> Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
> ---
>  drivers/net/ethernet/microchip/lan966x/lan966x_lag.c | 9 +++++++--
>  1 file changed, 7 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_lag.c b/drivers/net/ethernet/microchip/lan966x/lan966x_lag.c
> index 41fa2523d91d3..89a2c3176f1da 100644
> --- a/drivers/net/ethernet/microchip/lan966x/lan966x_lag.c
> +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_lag.c
> @@ -37,19 +37,24 @@ static void lan966x_lag_set_aggr_pgids(struct lan966x *lan966x)
>  
>  	/* Now, set PGIDs for each active LAG */
>  	for (lag = 0; lag < lan966x->num_phys_ports; ++lag) {
> -		struct net_device *bond = lan966x->ports[lag]->bond;
> +		struct lan966x_port *port = lan966x->ports[lag];
>  		int num_active_ports = 0;
> +		struct net_device *bond;
>  		unsigned long bond_mask;
>  		u8 aggr_idx[16];
>  
> -		if (!bond || (visited & BIT(lag)))
> +		if (!port || !port->bond || (visited & BIT(lag)))
>  			continue;
>  
> +		bond = lan966x->ports[lag]->bond;
Why not bond = port->bond?

>  		bond_mask = lan966x_lag_get_mask(lan966x, bond);
>  
>  		for_each_set_bit(p, &bond_mask, lan966x->num_phys_ports) {
>  			struct lan966x_port *port = lan966x->ports[p];
>  
> +			if (!port)
> +				continue;
> +
>  			lan_wr(ANA_PGID_PGID_SET(bond_mask),
>  			       lan966x, ANA_PGID(p));
>  			if (port->lag_tx_active)
> -- 
> 2.34.1
> 
Only nit, otherwise:
Reviewed-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>

Thanks,
Michal
Horatiu Vultur Feb. 5, 2024, 9:44 a.m. UTC | #2
The 02/05/2024 09:44, Michal Swiatkowski wrote:

Hi Michal,

> 
> On Mon, Feb 05, 2024 at 09:07:56AM +0100, Horatiu Vultur wrote:
> > There is a crash when adding one of the lan966x interfaces under a lag
> > interface. The issue can be reproduced like this:
> > ip link add name bond0 type bond miimon 100 mode balance-xor
> > ip link set dev eth0 master bond0
> >
> > The reason is because when adding a interface under the lag it would go
> > through all the ports and try to figure out which other ports are under
> > that lag interface. And the issue is that lan966x can have ports that are
> > NULL pointer as they are not probed. So then iterating over these ports
> > it would just crash as they are NULL pointers.
> > The fix consists in actually checking for NULL pointers before accessing
> > something from the ports. Like we do in other places.
> >
> > Fixes: cabc9d49333d ("net: lan966x: Add lag support for lan966x")
> > Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
> > ---
> >  drivers/net/ethernet/microchip/lan966x/lan966x_lag.c | 9 +++++++--
> >  1 file changed, 7 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_lag.c b/drivers/net/ethernet/microchip/lan966x/lan966x_lag.c
> > index 41fa2523d91d3..89a2c3176f1da 100644
> > --- a/drivers/net/ethernet/microchip/lan966x/lan966x_lag.c
> > +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_lag.c
> > @@ -37,19 +37,24 @@ static void lan966x_lag_set_aggr_pgids(struct lan966x *lan966x)
> >
> >       /* Now, set PGIDs for each active LAG */
> >       for (lag = 0; lag < lan966x->num_phys_ports; ++lag) {
> > -             struct net_device *bond = lan966x->ports[lag]->bond;
> > +             struct lan966x_port *port = lan966x->ports[lag];
> >               int num_active_ports = 0;
> > +             struct net_device *bond;
> >               unsigned long bond_mask;
> >               u8 aggr_idx[16];
> >
> > -             if (!bond || (visited & BIT(lag)))
> > +             if (!port || !port->bond || (visited & BIT(lag)))
> >                       continue;
> >
> > +             bond = lan966x->ports[lag]->bond;
> Why not bond = port->bond?

That is also correct and more clear.
I think I just copy the line that I have removed and put it here. As it
has the same effect.
I can update this in the next version.

> 
> >               bond_mask = lan966x_lag_get_mask(lan966x, bond);
> >
> >               for_each_set_bit(p, &bond_mask, lan966x->num_phys_ports) {
> >                       struct lan966x_port *port = lan966x->ports[p];
> >
> > +                     if (!port)
> > +                             continue;
> > +
> >                       lan_wr(ANA_PGID_PGID_SET(bond_mask),
> >                              lan966x, ANA_PGID(p));
> >                       if (port->lag_tx_active)
> > --
> > 2.34.1
> >
> Only nit, otherwise:
> Reviewed-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
> 
> Thanks,
> Michal
Michal Swiatkowski Feb. 5, 2024, 10:58 a.m. UTC | #3
On Mon, Feb 05, 2024 at 10:44:34AM +0100, Horatiu Vultur wrote:
> The 02/05/2024 09:44, Michal Swiatkowski wrote:
> 
> Hi Michal,
> 
> > 
> > On Mon, Feb 05, 2024 at 09:07:56AM +0100, Horatiu Vultur wrote:
> > > There is a crash when adding one of the lan966x interfaces under a lag
> > > interface. The issue can be reproduced like this:
> > > ip link add name bond0 type bond miimon 100 mode balance-xor
> > > ip link set dev eth0 master bond0
> > >
> > > The reason is because when adding a interface under the lag it would go
> > > through all the ports and try to figure out which other ports are under
> > > that lag interface. And the issue is that lan966x can have ports that are
> > > NULL pointer as they are not probed. So then iterating over these ports
> > > it would just crash as they are NULL pointers.
> > > The fix consists in actually checking for NULL pointers before accessing
> > > something from the ports. Like we do in other places.
> > >
> > > Fixes: cabc9d49333d ("net: lan966x: Add lag support for lan966x")
> > > Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
> > > ---
> > >  drivers/net/ethernet/microchip/lan966x/lan966x_lag.c | 9 +++++++--
> > >  1 file changed, 7 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_lag.c b/drivers/net/ethernet/microchip/lan966x/lan966x_lag.c
> > > index 41fa2523d91d3..89a2c3176f1da 100644
> > > --- a/drivers/net/ethernet/microchip/lan966x/lan966x_lag.c
> > > +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_lag.c
> > > @@ -37,19 +37,24 @@ static void lan966x_lag_set_aggr_pgids(struct lan966x *lan966x)
> > >
> > >       /* Now, set PGIDs for each active LAG */
> > >       for (lag = 0; lag < lan966x->num_phys_ports; ++lag) {
> > > -             struct net_device *bond = lan966x->ports[lag]->bond;
> > > +             struct lan966x_port *port = lan966x->ports[lag];
> > >               int num_active_ports = 0;
> > > +             struct net_device *bond;
> > >               unsigned long bond_mask;
> > >               u8 aggr_idx[16];
> > >
> > > -             if (!bond || (visited & BIT(lag)))
> > > +             if (!port || !port->bond || (visited & BIT(lag)))
> > >                       continue;
> > >
> > > +             bond = lan966x->ports[lag]->bond;
> > Why not bond = port->bond?
> 
> That is also correct and more clear.
> I think I just copy the line that I have removed and put it here. As it
> has the same effect.
> I can update this in the next version.
> 

Great, thanks, fell free to add my reviewed-by tag in next version.

Michal

> > 
> > >               bond_mask = lan966x_lag_get_mask(lan966x, bond);
> > >
> > >               for_each_set_bit(p, &bond_mask, lan966x->num_phys_ports) {
> > >                       struct lan966x_port *port = lan966x->ports[p];
> > >
> > > +                     if (!port)
> > > +                             continue;
> > > +
> > >                       lan_wr(ANA_PGID_PGID_SET(bond_mask),
> > >                              lan966x, ANA_PGID(p));
> > >                       if (port->lag_tx_active)
> > > --
> > > 2.34.1
> > >
> > Only nit, otherwise:
> > Reviewed-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
> > 
> > Thanks,
> > Michal
> 
> -- 
> /Horatiu
diff mbox series

Patch

diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_lag.c b/drivers/net/ethernet/microchip/lan966x/lan966x_lag.c
index 41fa2523d91d3..89a2c3176f1da 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_lag.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_lag.c
@@ -37,19 +37,24 @@  static void lan966x_lag_set_aggr_pgids(struct lan966x *lan966x)
 
 	/* Now, set PGIDs for each active LAG */
 	for (lag = 0; lag < lan966x->num_phys_ports; ++lag) {
-		struct net_device *bond = lan966x->ports[lag]->bond;
+		struct lan966x_port *port = lan966x->ports[lag];
 		int num_active_ports = 0;
+		struct net_device *bond;
 		unsigned long bond_mask;
 		u8 aggr_idx[16];
 
-		if (!bond || (visited & BIT(lag)))
+		if (!port || !port->bond || (visited & BIT(lag)))
 			continue;
 
+		bond = lan966x->ports[lag]->bond;
 		bond_mask = lan966x_lag_get_mask(lan966x, bond);
 
 		for_each_set_bit(p, &bond_mask, lan966x->num_phys_ports) {
 			struct lan966x_port *port = lan966x->ports[p];
 
+			if (!port)
+				continue;
+
 			lan_wr(ANA_PGID_PGID_SET(bond_mask),
 			       lan966x, ANA_PGID(p));
 			if (port->lag_tx_active)