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