History

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.

Xiaomeng Tong committed 4 years ago

Commit 3f95a741 parent 8b796471 file · +14 −13Browse files

Unified · Split

drivers/net/ethernet/intel/i40e/i40e_main.c+14−13
@@ -7549,42 +7549,43 @@ static void i40e_free_macvlan_channels(struct i40e_vsi *vsi) · 7548 unmodified lines
7549static int i40e_fwd_ring_up(struct i40e_vsi *vsi, struct net_device *vdev,7549static int i40e_fwd_ring_up(struct i40e_vsi *vsi, struct net_device *vdev,
7550 struct i40e_fwd_adapter *fwd)7550 struct i40e_fwd_adapter *fwd)
7551{7551{
7552 struct i40e_channel *ch = NULL, *ch_tmp, *iter;
7552 int ret = 0, num_tc = 1, i, aq_err;7553 int ret = 0, num_tc = 1, i, aq_err;
7553 struct i40e_channel *ch, *ch_tmp;
7554 struct i40e_pf *pf = vsi->back;7554 struct i40e_pf *pf = vsi->back;
7555 struct i40e_hw *hw = &pf->hw;7555 struct i40e_hw *hw = &pf->hw;
7556 7556
7557 if (list_empty(&vsi->macvlan_list))
7558 return -EINVAL;
7559
7560 /* Go through the list and find an available channel */7557 /* Go through the list and find an available channel */
7561 list_for_each_entry_safe(ch, ch_tmp, &vsi->macvlan_list, list) {7558 list_for_each_entry_safe(iter, ch_tmp, &vsi->macvlan_list, list) {
7562 if (!i40e_is_channel_macvlan(ch)) {7559 if (!i40e_is_channel_macvlan(iter)) {
7563 ch->fwd = fwd;7560 iter->fwd = fwd;
7564 /* record configuration for macvlan interface in vdev */7561 /* record configuration for macvlan interface in vdev */
7565 for (i = 0; i < num_tc; i++)7562 for (i = 0; i < num_tc; i++)
7566 netdev_bind_sb_channel_queue(vsi->netdev, vdev,7563 netdev_bind_sb_channel_queue(vsi->netdev, vdev,
7567 i,7564 i,
7568 ch->num_queue_pairs,7565 iter->num_queue_pairs,
7569 ch->base_queue);7566 iter->base_queue);
7570 for (i = 0; i < ch->num_queue_pairs; i++) {7567 for (i = 0; i < iter->num_queue_pairs; i++) {
7571 struct i40e_ring *tx_ring, *rx_ring;7568 struct i40e_ring *tx_ring, *rx_ring;
7572 u16 pf_q;7569 u16 pf_q;
7573 7570
7574 pf_q = ch->base_queue + i;7571 pf_q = iter->base_queue + i;
7575 7572
7576 /* Get to TX ring ptr */7573 /* Get to TX ring ptr */
7577 tx_ring = vsi->tx_rings[pf_q];7574 tx_ring = vsi->tx_rings[pf_q];
7578 tx_ring->ch = ch;7575 tx_ring->ch = iter;
7579 7576
7580 /* Get the RX ring ptr */7577 /* Get the RX ring ptr */
7581 rx_ring = vsi->rx_rings[pf_q];7578 rx_ring = vsi->rx_rings[pf_q];
7582 rx_ring->ch = ch;7579 rx_ring->ch = iter;
7583 }7580 }
7581 ch = iter;
7584 break;7582 break;
7585 }7583 }
7586 }7584 }
7587 7585
7586 if (!ch)
7587 return -EINVAL;
7588
7588 /* Guarantee all rings are updated before we update the7589 /* Guarantee all rings are updated before we update the
7589 * MAC address filter.7590 * MAC address filter.
7590 */7591 */