2022-03-27 08:46:10

by Xiaomeng Tong

[permalink] [raw]
Subject: [PATCH] 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: [email protected]
Fixes: 1d8d80b4e4ff6 ("i40e: Add macvlan support on i40e")
Signed-off-by: Xiaomeng Tong <[email protected]>
---
drivers/net/ethernet/intel/i40e/i40e_main.c | 27 +++++++++++----------
1 file changed, 14 insertions(+), 13 deletions(-)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 31b03fe78d3b..6224c98d275f 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -7536,41 +7536,42 @@ static int i40e_fwd_ring_up(struct i40e_vsi *vsi, struct net_device *vdev,
struct i40e_fwd_adapter *fwd)
{
int ret = 0, num_tc = 1, i, aq_err;
- struct i40e_channel *ch, *ch_tmp;
+ struct i40e_channel *ch = NULL, *ch_tmp, *iter;
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.
*/
--
2.17.1


2022-04-07 20:16:36

by G, GurucharanX

[permalink] [raw]
Subject: RE: [Intel-wired-lan] [PATCH] i40e: i40e_main: fix a missing check on list iterator



> -----Original Message-----
> From: Intel-wired-lan <[email protected]> On Behalf Of
> Xiaomeng Tong
> Sent: Sunday, March 27, 2022 12:06 PM
> To: Brandeburg, Jesse <[email protected]>
> Cc: [email protected]; [email protected]; linux-
> [email protected]; [email protected]; Xiaomeng Tong
> <[email protected]>; [email protected];
> [email protected]; [email protected]; [email protected]
> Subject: [Intel-wired-lan] [PATCH] 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: [email protected]
> Fixes: 1d8d80b4e4ff6 ("i40e: Add macvlan support on i40e")
> Signed-off-by: Xiaomeng Tong <[email protected]>
> ---
> drivers/net/ethernet/intel/i40e/i40e_main.c | 27 +++++++++++----------
> 1 file changed, 14 insertions(+), 13 deletions(-)
>

Tested-by: Gurucharan <[email protected]> (A Contingent worker at Intel)