Skip to content

Commit 290f1c0

Browse files
alobakinkuba-moo
authored andcommitted
idpf: fix UAFs when destroying the queues
The second tagged commit started sometimes (very rarely, but possible) throwing WARNs from net/core/page_pool.c:page_pool_disable_direct_recycling(). Turned out idpf frees interrupt vectors with embedded NAPIs *before* freeing the queues making page_pools' NAPI pointers lead to freed memory before these pools are destroyed by libeth. It's not clear whether there are other accesses to the freed vectors when destroying the queues, but anyway, we usually free queue/interrupt vectors only when the queues are destroyed and the NAPIs are guaranteed to not be referenced anywhere. Invert the allocation and freeing logic making queue/interrupt vectors be allocated first and freed last. Vectors don't require queues to be present, so this is safe. Additionally, this change allows to remove that useless queue->q_vector pointer cleanup, as vectors are still valid when freeing the queues (+ both are freed within one function, so it's not clear why nullify the pointers at all). Fixes: 1c325aa ("idpf: configure resources for TX queues") Fixes: 90912f9 ("idpf: convert header split mode to libeth + napi_build_skb()") Reported-by: Michal Kubiak <[email protected]> Signed-off-by: Alexander Lobakin <[email protected]> Reviewed-by: Simon Horman <[email protected]> Tested-by: Krishneil Singh <[email protected]> Signed-off-by: Tony Nguyen <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 3cc88e8 commit 290f1c0

File tree

2 files changed

+13
-35
lines changed

2 files changed

+13
-35
lines changed

drivers/net/ethernet/intel/idpf/idpf_lib.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -900,8 +900,8 @@ static void idpf_vport_stop(struct idpf_vport *vport)
900900

901901
vport->link_up = false;
902902
idpf_vport_intr_deinit(vport);
903-
idpf_vport_intr_rel(vport);
904903
idpf_vport_queues_rel(vport);
904+
idpf_vport_intr_rel(vport);
905905
np->state = __IDPF_VPORT_DOWN;
906906
}
907907

@@ -1349,43 +1349,43 @@ static int idpf_vport_open(struct idpf_vport *vport)
13491349
/* we do not allow interface up just yet */
13501350
netif_carrier_off(vport->netdev);
13511351

1352-
err = idpf_vport_queues_alloc(vport);
1353-
if (err)
1354-
return err;
1355-
13561352
err = idpf_vport_intr_alloc(vport);
13571353
if (err) {
13581354
dev_err(&adapter->pdev->dev, "Failed to allocate interrupts for vport %u: %d\n",
13591355
vport->vport_id, err);
1360-
goto queues_rel;
1356+
return err;
13611357
}
13621358

1359+
err = idpf_vport_queues_alloc(vport);
1360+
if (err)
1361+
goto intr_rel;
1362+
13631363
err = idpf_vport_queue_ids_init(vport);
13641364
if (err) {
13651365
dev_err(&adapter->pdev->dev, "Failed to initialize queue ids for vport %u: %d\n",
13661366
vport->vport_id, err);
1367-
goto intr_rel;
1367+
goto queues_rel;
13681368
}
13691369

13701370
err = idpf_vport_intr_init(vport);
13711371
if (err) {
13721372
dev_err(&adapter->pdev->dev, "Failed to initialize interrupts for vport %u: %d\n",
13731373
vport->vport_id, err);
1374-
goto intr_rel;
1374+
goto queues_rel;
13751375
}
13761376

13771377
err = idpf_rx_bufs_init_all(vport);
13781378
if (err) {
13791379
dev_err(&adapter->pdev->dev, "Failed to initialize RX buffers for vport %u: %d\n",
13801380
vport->vport_id, err);
1381-
goto intr_rel;
1381+
goto queues_rel;
13821382
}
13831383

13841384
err = idpf_queue_reg_init(vport);
13851385
if (err) {
13861386
dev_err(&adapter->pdev->dev, "Failed to initialize queue registers for vport %u: %d\n",
13871387
vport->vport_id, err);
1388-
goto intr_rel;
1388+
goto queues_rel;
13891389
}
13901390

13911391
idpf_rx_init_buf_tail(vport);
@@ -1452,10 +1452,10 @@ static int idpf_vport_open(struct idpf_vport *vport)
14521452
idpf_send_map_unmap_queue_vector_msg(vport, false);
14531453
intr_deinit:
14541454
idpf_vport_intr_deinit(vport);
1455-
intr_rel:
1456-
idpf_vport_intr_rel(vport);
14571455
queues_rel:
14581456
idpf_vport_queues_rel(vport);
1457+
intr_rel:
1458+
idpf_vport_intr_rel(vport);
14591459

14601460
return err;
14611461
}

drivers/net/ethernet/intel/idpf/idpf_txrx.c

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3576,9 +3576,7 @@ static void idpf_vport_intr_napi_dis_all(struct idpf_vport *vport)
35763576
*/
35773577
void idpf_vport_intr_rel(struct idpf_vport *vport)
35783578
{
3579-
int i, j, v_idx;
3580-
3581-
for (v_idx = 0; v_idx < vport->num_q_vectors; v_idx++) {
3579+
for (u32 v_idx = 0; v_idx < vport->num_q_vectors; v_idx++) {
35823580
struct idpf_q_vector *q_vector = &vport->q_vectors[v_idx];
35833581

35843582
kfree(q_vector->complq);
@@ -3593,26 +3591,6 @@ void idpf_vport_intr_rel(struct idpf_vport *vport)
35933591
free_cpumask_var(q_vector->affinity_mask);
35943592
}
35953593

3596-
/* Clean up the mapping of queues to vectors */
3597-
for (i = 0; i < vport->num_rxq_grp; i++) {
3598-
struct idpf_rxq_group *rx_qgrp = &vport->rxq_grps[i];
3599-
3600-
if (idpf_is_queue_model_split(vport->rxq_model))
3601-
for (j = 0; j < rx_qgrp->splitq.num_rxq_sets; j++)
3602-
rx_qgrp->splitq.rxq_sets[j]->rxq.q_vector = NULL;
3603-
else
3604-
for (j = 0; j < rx_qgrp->singleq.num_rxq; j++)
3605-
rx_qgrp->singleq.rxqs[j]->q_vector = NULL;
3606-
}
3607-
3608-
if (idpf_is_queue_model_split(vport->txq_model))
3609-
for (i = 0; i < vport->num_txq_grp; i++)
3610-
vport->txq_grps[i].complq->q_vector = NULL;
3611-
else
3612-
for (i = 0; i < vport->num_txq_grp; i++)
3613-
for (j = 0; j < vport->txq_grps[i].num_txq; j++)
3614-
vport->txq_grps[i].txqs[j]->q_vector = NULL;
3615-
36163594
kfree(vport->q_vectors);
36173595
vport->q_vectors = NULL;
36183596
}

0 commit comments

Comments
 (0)