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: 1d8d80b4e4 ("i40e: Add macvlan support on i40e")
Signed-off-by: Xiaomeng Tong <xiam0nd.tong@gmail.com>
Tested-by: Gurucharan <gurucharanx.g@intel.com> (A Contingent worker at Intel)
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Link: https://lore.kernel.org/r/20220510204846.2166999-1-anthony.l.nguyen@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Xiaomeng Tong 2022-05-10 13:48:46 -07:00 committed by Jakub Kicinski
parent 8b796475fd
commit 3f95a7472d
1 changed files with 14 additions and 13 deletions

View File

@ -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,
struct i40e_fwd_adapter *fwd)
{
struct i40e_channel *ch = NULL, *ch_tmp, *iter;
int ret = 0, num_tc = 1, i, aq_err;
struct i40e_channel *ch, *ch_tmp;
struct i40e_pf *pf = vsi->back;
struct i40e_hw *hw = &pf->hw;
if (list_empty(&vsi->macvlan_list))
return -EINVAL;
/* Go through the list and find an available channel */
list_for_each_entry_safe(ch, ch_tmp, &vsi->macvlan_list, list) {
if (!i40e_is_channel_macvlan(ch)) {
ch->fwd = fwd;
list_for_each_entry_safe(iter, ch_tmp, &vsi->macvlan_list, list) {
if (!i40e_is_channel_macvlan(iter)) {
iter->fwd = fwd;
/* record configuration for macvlan interface in vdev */
for (i = 0; i < num_tc; i++)
netdev_bind_sb_channel_queue(vsi->netdev, vdev,
i,
ch->num_queue_pairs,
ch->base_queue);
for (i = 0; i < ch->num_queue_pairs; i++) {
iter->num_queue_pairs,
iter->base_queue);
for (i = 0; i < iter->num_queue_pairs; i++) {
struct i40e_ring *tx_ring, *rx_ring;
u16 pf_q;
pf_q = ch->base_queue + i;
pf_q = iter->base_queue + i;
/* Get to TX ring ptr */
tx_ring = vsi->tx_rings[pf_q];
tx_ring->ch = ch;
tx_ring->ch = iter;
/* Get the RX ring ptr */
rx_ring = vsi->rx_rings[pf_q];
rx_ring->ch = ch;
rx_ring->ch = iter;
}
ch = iter;
break;
}
}
if (!ch)
return -EINVAL;
/* Guarantee all rings are updated before we update the
* MAC address filter.
*/