ice_init_lag() registers the netdevice notifier before it creates the LAG
recipes, but when creating any of them fails, the error path frees the lag
struct without unregistering the notifier. A failure of ice_init_lag() is
not fatal to probe, and pf->lag is set to NULL, so ice_deinit_lag() won't
unregister it later either. The next netdev event then makes
ice_lag_event_handler() use the freed lag struct.
Register the notifier last, after the recipes are created and associated
with the profiles, so the error paths have no handler, nor queued work for
it, that could use the lag struct or its recipes. Free the recipes if the
registration itself fails.
Fixes: ec5a6c5f79ed ("ice: process events created by lag netdev event handler")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/bug/linux-e0559bca-fcfd-4435-96f2-15f7e3d74184
Signed-off-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
---
drivers/net/ethernet/intel/ice/ice_lag.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/intel/ice/ice_lag.c b/drivers/net/ethernet/intel/ice/ice_lag.c
index 08a17ded0ad5..c4b8af01e2af 100644
--- a/drivers/net/ethernet/intel/ice/ice_lag.c
+++ b/drivers/net/ethernet/intel/ice/ice_lag.c
@@ -2601,12 +2601,6 @@ int ice_init_lag(struct ice_pf *pf)
lag->notif_block.notifier_call = NULL;
memset(lag->sec_vf, 0, sizeof(lag->sec_vf));
- err = ice_register_lag_handler(lag);
- if (err) {
- dev_warn(dev, "INIT LAG: Failed to register event handler\n");
- goto lag_error;
- }
-
err = ice_create_lag_recipe(&pf->hw, &lag->pf_recipe,
ice_dflt_vsi_rcp, 1);
if (err)@@ -2638,11 +2632,20 @@ int ice_init_lag(struct ice_pf *pf)
}
}
+ err = ice_register_lag_handler(lag);
+ if (err) {
+ dev_warn(dev, "INIT LAG: Failed to register event handler\n");
+ goto free_act_act_res;
+ }
+
ice_display_lag_info(lag);
dev_dbg(dev, "INIT LAG complete\n");
return 0;
+free_act_act_res:
+ ice_free_hw_res(&pf->hw, ICE_AQC_RES_TYPE_RECIPE, 1,
+ &lag->act_act_recipe);
free_lport_res:
ice_free_hw_res(&pf->hw, ICE_AQC_RES_TYPE_RECIPE, 1,
&lag->lport_recipe);--
2.54.0