Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f25145c3 authored by Xiaomeng Tong's avatar Xiaomeng Tong Committed by Greg Kroah-Hartman
Browse files

i40e: i40e_main: fix a missing check on list iterator



commit 3f95a7472d14abef284d8968734fe2ae7ff4845f upstream.

The bug is here:
	ret = i40e_add_macvlan_filter(hw, ch->seid, vdev->dev_addr, &aq_err);

The list iterator 'ch' will point to a bogus position containing
HEAD if the list is empty or no element is found. This case must
be checked before any use of the iterator, otherwise it will
lead to a invalid memory access.

To fix this bug, use a new variable 'iter' as the list iterator,
while use the origin variable 'ch' as a dedicated pointer to
point to the found element.

Cc: stable@vger.kernel.org
Fixes: 1d8d80b4 ("i40e: Add macvlan support on i40e")
Signed-off-by: default avatarXiaomeng Tong <xiam0nd.tong@gmail.com>
Tested-by: Gurucharan <gurucharanx.g@intel.com> (A Contingent worker at Intel)
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
Link: https://lore.kernel.org/r/20220510204846.2166999-1-anthony.l.nguyen@intel.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 17c74471
Loading
Loading
Loading
Loading
+14 −13
Original line number Original line Diff line number Diff line
@@ -7120,42 +7120,43 @@ static void i40e_free_macvlan_channels(struct i40e_vsi *vsi)
static int i40e_fwd_ring_up(struct i40e_vsi *vsi, struct net_device *vdev,
static int i40e_fwd_ring_up(struct i40e_vsi *vsi, struct net_device *vdev,
			    struct i40e_fwd_adapter *fwd)
			    struct i40e_fwd_adapter *fwd)
{
{
	struct i40e_channel *ch = NULL, *ch_tmp, *iter;
	int ret = 0, num_tc = 1,  i, aq_err;
	int ret = 0, num_tc = 1,  i, aq_err;
	struct i40e_channel *ch, *ch_tmp;
	struct i40e_pf *pf = vsi->back;
	struct i40e_pf *pf = vsi->back;
	struct i40e_hw *hw = &pf->hw;
	struct i40e_hw *hw = &pf->hw;


	if (list_empty(&vsi->macvlan_list))
		return -EINVAL;

	/* Go through the list and find an available channel */
	/* Go through the list and find an available channel */
	list_for_each_entry_safe(ch, ch_tmp, &vsi->macvlan_list, list) {
	list_for_each_entry_safe(iter, ch_tmp, &vsi->macvlan_list, list) {
		if (!i40e_is_channel_macvlan(ch)) {
		if (!i40e_is_channel_macvlan(iter)) {
			ch->fwd = fwd;
			iter->fwd = fwd;
			/* record configuration for macvlan interface in vdev */
			/* record configuration for macvlan interface in vdev */
			for (i = 0; i < num_tc; i++)
			for (i = 0; i < num_tc; i++)
				netdev_bind_sb_channel_queue(vsi->netdev, vdev,
				netdev_bind_sb_channel_queue(vsi->netdev, vdev,
							     i,
							     i,
							     ch->num_queue_pairs,
							     iter->num_queue_pairs,
							     ch->base_queue);
							     iter->base_queue);
			for (i = 0; i < ch->num_queue_pairs; i++) {
			for (i = 0; i < iter->num_queue_pairs; i++) {
				struct i40e_ring *tx_ring, *rx_ring;
				struct i40e_ring *tx_ring, *rx_ring;
				u16 pf_q;
				u16 pf_q;


				pf_q = ch->base_queue + i;
				pf_q = iter->base_queue + i;


				/* Get to TX ring ptr */
				/* Get to TX ring ptr */
				tx_ring = vsi->tx_rings[pf_q];
				tx_ring = vsi->tx_rings[pf_q];
				tx_ring->ch = ch;
				tx_ring->ch = iter;


				/* Get the RX ring ptr */
				/* Get the RX ring ptr */
				rx_ring = vsi->rx_rings[pf_q];
				rx_ring = vsi->rx_rings[pf_q];
				rx_ring->ch = ch;
				rx_ring->ch = iter;
			}
			}
			ch = iter;
			break;
			break;
		}
		}
	}
	}


	if (!ch)
		return -EINVAL;

	/* Guarantee all rings are updated before we update the
	/* Guarantee all rings are updated before we update the
	 * MAC address filter.
	 * MAC address filter.
	 */
	 */