Commit bea1898f authored by Dave Ertman's avatar Dave Ertman Committed by Tony Nguyen
Browse files

ice: Fix KASAN error in LAG NETDEV_UNREGISTER handler



Currently, the same handler is called for both a NETDEV_BONDING_INFO
LAG unlink notification as for a NETDEV_UNREGISTER call.  This is
causing a problem though, since the netdev_notifier_info passed has
a different structure depending on which event is passed.  The problem
manifests as a call trace from a BUG: KASAN stack-out-of-bounds error.

Fix this by creating a handler specific to NETDEV_UNREGISTER that only
is passed valid elements in the netdev_notifier_info struct for the
NETDEV_UNREGISTER event.

Also included is the removal of an unbalanced dev_put on the peer_netdev
and related braces.

Fixes: 6a8b3572 ("ice: Respond to a NETDEV_UNREGISTER event for LAG")
Signed-off-by: default avatarDave Ertman <david.m.ertman@intel.com>
Acked-by: default avatarJonathan Toppins <jtoppins@redhat.com>
Tested-by: default avatarSunitha Mekala <sunithax.d.mekala@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent 46b699c5
Loading
Loading
Loading
Loading
+28 −6
Original line number Original line Diff line number Diff line
@@ -204,13 +204,35 @@ ice_lag_unlink(struct ice_lag *lag,
		lag->upper_netdev = NULL;
		lag->upper_netdev = NULL;
	}
	}


	if (lag->peer_netdev) {
		dev_put(lag->peer_netdev);
	lag->peer_netdev = NULL;
	lag->peer_netdev = NULL;
	ice_set_sriov_cap(pf);
	ice_set_rdma_cap(pf);
	lag->bonded = false;
	lag->role = ICE_LAG_NONE;
}
}


/**
 * ice_lag_unregister - handle netdev unregister events
 * @lag: LAG info struct
 * @netdev: netdev reporting the event
 */
static void ice_lag_unregister(struct ice_lag *lag, struct net_device *netdev)
{
	struct ice_pf *pf = lag->pf;

	/* check to see if this event is for this netdev
	 * check that we are in an aggregate
	 */
	if (netdev != lag->netdev || !lag->bonded)
		return;

	if (lag->upper_netdev) {
		dev_put(lag->upper_netdev);
		lag->upper_netdev = NULL;
		ice_set_sriov_cap(pf);
		ice_set_sriov_cap(pf);
		ice_set_rdma_cap(pf);
		ice_set_rdma_cap(pf);
	}
	/* perform some cleanup in case we come back */
	lag->bonded = false;
	lag->bonded = false;
	lag->role = ICE_LAG_NONE;
	lag->role = ICE_LAG_NONE;
}
}
@@ -307,7 +329,7 @@ ice_lag_event_handler(struct notifier_block *notif_blk, unsigned long event,
		ice_lag_info_event(lag, ptr);
		ice_lag_info_event(lag, ptr);
		break;
		break;
	case NETDEV_UNREGISTER:
	case NETDEV_UNREGISTER:
		ice_lag_unlink(lag, ptr);
		ice_lag_unregister(lag, netdev);
		break;
		break;
	default:
	default:
		break;
		break;