Commit 3f95a747 authored by Xiaomeng Tong's avatar Xiaomeng Tong Committed by Jakub Kicinski

i40e: i40e_main: fix a missing check on list iterator

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.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 8b796475
...@@ -7549,42 +7549,43 @@ static void i40e_free_macvlan_channels(struct i40e_vsi *vsi) ...@@ -7549,42 +7549,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.
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment