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
75497549 static int i40e_fwd_ring_up(struct i40e_vsi *vsi, struct net_device *vdev,
75507550 struct i40e_fwd_adapter *fwd)
75517551 {
7552+ struct i40e_channel *ch = NULL, *ch_tmp, *iter;
75527553 int ret = 0, num_tc = 1, i, aq_err;
7553− struct i40e_channel *ch, *ch_tmp;
75547554 struct i40e_pf *pf = vsi->back;
75557555 struct i40e_hw *hw = &pf->hw;
75567556
7557− if (list_empty(&vsi->macvlan_list))
7558− return -EINVAL;
7559−
75607557 /* Go through the list and find an available channel */
7561− list_for_each_entry_safe(ch, ch_tmp, &vsi->macvlan_list, list) {
7562− if (!i40e_is_channel_macvlan(ch)) {
7563− ch->fwd = fwd;
7558+ list_for_each_entry_safe(iter, ch_tmp, &vsi->macvlan_list, list) {
7559+ if (!i40e_is_channel_macvlan(iter)) {
7560+ iter->fwd = fwd;
75647561 /* record configuration for macvlan interface in vdev */
75657562 for (i = 0; i < num_tc; i++)
75667563 netdev_bind_sb_channel_queue(vsi->netdev, vdev,
75677564 i,
7568− ch->num_queue_pairs,
7569− ch->base_queue);
7570− for (i = 0; i < ch->num_queue_pairs; i++) {
7565+ iter->num_queue_pairs,
7566+ iter->base_queue);
7567+ for (i = 0; i < iter->num_queue_pairs; i++) {
75717568 struct i40e_ring *tx_ring, *rx_ring;
75727569 u16 pf_q;
75737570
7574− pf_q = ch->base_queue + i;
7571+ pf_q = iter->base_queue + i;
75757572
75767573 /* Get to TX ring ptr */
75777574 tx_ring = vsi->tx_rings[pf_q];
7578− tx_ring->ch = ch;
7575+ tx_ring->ch = iter;
75797576
75807577 /* Get the RX ring ptr */
75817578 rx_ring = vsi->rx_rings[pf_q];
7582− rx_ring->ch = ch;
7579+ rx_ring->ch = iter;
75837580 }
7581+ ch = iter;
75847582 break;
75857583 }
75867584 }
75877585
7586+ if (!ch)
7587+ return -EINVAL;
7588+
75887589 /* Guarantee all rings are updated before we update the
75897590 * MAC address filter.
75907591 */