Skip to content

Commit b4afe3f

Browse files
author
Paolo Abeni
committed
Merge branch 'net-lan966x-fix-page_pool-error-handling-and-error-paths'
David Carlier says: ==================== net: lan966x: fix page_pool error handling and error paths This series fixes error handling around the lan966x page pool: 1/3 adds the missing IS_ERR check after page_pool_create(), preventing a kernel oops when the error pointer flows into xdp_rxq_info_reg_mem_model(). 2/3 plugs page pool leaks in the lan966x_fdma_rx_alloc() and lan966x_fdma_init() error paths, now reachable after 1/3. 3/3 fixes a use-after-free and page pool leak in the lan966x_fdma_reload() restore path, where the hardware could resume DMA into pages already returned to the page pool. ==================== Link: https://patch.msgid.link/20260405055241.35767-1-devnexen@gmail.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2 parents c71ba66 + 59c3d55 commit b4afe3f

1 file changed

Lines changed: 24 additions & 4 deletions

File tree

drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ static int lan966x_fdma_rx_alloc_page_pool(struct lan966x_rx *rx)
9191
pp_params.dma_dir = DMA_BIDIRECTIONAL;
9292

9393
rx->page_pool = page_pool_create(&pp_params);
94+
if (unlikely(IS_ERR(rx->page_pool)))
95+
return PTR_ERR(rx->page_pool);
9496

9597
for (int i = 0; i < lan966x->num_phys_ports; ++i) {
9698
struct lan966x_port *port;
@@ -117,8 +119,10 @@ static int lan966x_fdma_rx_alloc(struct lan966x_rx *rx)
117119
return PTR_ERR(rx->page_pool);
118120

119121
err = fdma_alloc_coherent(lan966x->dev, fdma);
120-
if (err)
122+
if (err) {
123+
page_pool_destroy(rx->page_pool);
121124
return err;
125+
}
122126

123127
fdma_dcbs_init(fdma, FDMA_DCB_INFO_DATAL(fdma->db_size),
124128
FDMA_DCB_STATUS_INTR);
@@ -808,9 +812,15 @@ static int lan966x_qsys_sw_status(struct lan966x *lan966x)
808812

809813
static int lan966x_fdma_reload(struct lan966x *lan966x, int new_mtu)
810814
{
815+
struct page *(*old_pages)[FDMA_RX_DCB_MAX_DBS];
811816
struct page_pool *page_pool;
812817
struct fdma fdma_rx_old;
813-
int err;
818+
int err, i, j;
819+
820+
old_pages = kmemdup(lan966x->rx.page, sizeof(lan966x->rx.page),
821+
GFP_KERNEL);
822+
if (!old_pages)
823+
return -ENOMEM;
814824

815825
/* Store these for later to free them */
816826
memcpy(&fdma_rx_old, &lan966x->rx.fdma, sizeof(struct fdma));
@@ -821,27 +831,36 @@ static int lan966x_fdma_reload(struct lan966x *lan966x, int new_mtu)
821831
lan966x_fdma_stop_netdev(lan966x);
822832

823833
lan966x_fdma_rx_disable(&lan966x->rx);
824-
lan966x_fdma_rx_free_pages(&lan966x->rx);
825834
lan966x->rx.page_order = round_up(new_mtu, PAGE_SIZE) / PAGE_SIZE - 1;
826835
lan966x->rx.max_mtu = new_mtu;
827836
err = lan966x_fdma_rx_alloc(&lan966x->rx);
828837
if (err)
829838
goto restore;
830839
lan966x_fdma_rx_start(&lan966x->rx);
831840

841+
for (i = 0; i < fdma_rx_old.n_dcbs; ++i)
842+
for (j = 0; j < fdma_rx_old.n_dbs; ++j)
843+
page_pool_put_full_page(page_pool,
844+
old_pages[i][j], false);
845+
832846
fdma_free_coherent(lan966x->dev, &fdma_rx_old);
833847

834848
page_pool_destroy(page_pool);
835849

836850
lan966x_fdma_wakeup_netdev(lan966x);
837851
napi_enable(&lan966x->napi);
838852

839-
return err;
853+
kfree(old_pages);
854+
return 0;
840855
restore:
841856
lan966x->rx.page_pool = page_pool;
842857
memcpy(&lan966x->rx.fdma, &fdma_rx_old, sizeof(struct fdma));
843858
lan966x_fdma_rx_start(&lan966x->rx);
844859

860+
lan966x_fdma_wakeup_netdev(lan966x);
861+
napi_enable(&lan966x->napi);
862+
863+
kfree(old_pages);
845864
return err;
846865
}
847866

@@ -955,6 +974,7 @@ int lan966x_fdma_init(struct lan966x *lan966x)
955974
err = lan966x_fdma_tx_alloc(&lan966x->tx);
956975
if (err) {
957976
fdma_free_coherent(lan966x->dev, &lan966x->rx.fdma);
977+
page_pool_destroy(lan966x->rx.page_pool);
958978
return err;
959979
}
960980

0 commit comments

Comments
 (0)