From: Emil Tantilov NULL pointer dereference is reported in cases where idpf_vport_open() fails during soft reset: ./xdpsock -i -q -r -N [ 3179.186687] idpf 0000:83:00.0: Failed to initialize queue ids for vport 0: -12 [ 3179.276739] BUG: kernel NULL pointer dereference, address: 0000000000000010 [ 3179.277636] #PF: supervisor read access in kernel mode [ 3179.278470] #PF: error_code(0x0000) - not-present page [ 3179.279285] PGD 0 [ 3179.280083] Oops: Oops: 0000 [#1] SMP NOPTI ... [ 3179.283997] Workqueue: events xp_release_deferred [ 3179.284770] RIP: 0010:idpf_find_rxq_vec+0x17/0x30 [idpf] ... [ 3179.291937] Call Trace: [ 3179.292392] [ 3179.292843] idpf_qp_switch+0x25/0x820 [idpf] [ 3179.293325] idpf_xsk_pool_setup+0x7c/0x520 [idpf] [ 3179.293803] idpf_xdp+0x59/0x240 [idpf] [ 3179.294275] xp_disable_drv_zc+0x62/0xb0 [ 3179.294743] xp_clear_dev+0x40/0xb0 [ 3179.295198] xp_release_deferred+0x1f/0xa0 [ 3179.295648] process_one_work+0x226/0x730 [ 3179.296106] worker_thread+0x19e/0x340 [ 3179.296557] ? __pfx_worker_thread+0x10/0x10 [ 3179.297009] kthread+0xf4/0x130 [ 3179.297459] ? __pfx_kthread+0x10/0x10 [ 3179.297910] ret_from_fork+0x32c/0x410 [ 3179.298361] ? __pfx_kthread+0x10/0x10 [ 3179.298702] ret_from_fork_asm+0x1a/0x30 Fix the error handling of the soft reset in idpf_xdp_setup_prog() by restoring the vport->xdp_prog to the old value. This avoids referencing the orphaned prog that was copied to vport->xdp_prog in the soft reset and prevents subsequent false positive by idpf_xdp_enabled(). Update the restart check in idpf_xsk_pool_setup() to use IDPF_VPORT_UP bit instead of netif_running(). The idpf_vport_stop/start() calls will not update the __LINK_STATE_START bit, making this test a false positive should the soft reset fail. Fixes: 3d57b2c00f09 ("idpf: add XSk pool initialization") Cc: stable@vger.kernel.org Signed-off-by: Emil Tantilov Reviewed-by: Aleksandr Loktionov Tested-by: Patryk Holda Signed-off-by: Jacob Keller --- drivers/net/ethernet/intel/idpf/xdp.c | 1 + drivers/net/ethernet/intel/idpf/xsk.c | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/idpf/xdp.c b/drivers/net/ethernet/intel/idpf/xdp.c index cbccd4546768..18a6e7062863 100644 --- a/drivers/net/ethernet/intel/idpf/xdp.c +++ b/drivers/net/ethernet/intel/idpf/xdp.c @@ -488,6 +488,7 @@ static int idpf_xdp_setup_prog(struct idpf_vport *vport, "Could not reopen the vport after XDP setup"); cfg->user_config.xdp_prog = old; + vport->xdp_prog = old; old = prog; } diff --git a/drivers/net/ethernet/intel/idpf/xsk.c b/drivers/net/ethernet/intel/idpf/xsk.c index d95d3efdfd36..3d8c430efd2b 100644 --- a/drivers/net/ethernet/intel/idpf/xsk.c +++ b/drivers/net/ethernet/intel/idpf/xsk.c @@ -553,6 +553,7 @@ int idpf_xskrq_poll(struct idpf_rx_queue *rxq, u32 budget) int idpf_xsk_pool_setup(struct idpf_vport *vport, struct netdev_bpf *bpf) { + const struct idpf_netdev_priv *np = netdev_priv(vport->netdev); struct xsk_buff_pool *pool = bpf->xsk.pool; u32 qid = bpf->xsk.queue_id; bool restart; @@ -568,7 +569,8 @@ int idpf_xsk_pool_setup(struct idpf_vport *vport, struct netdev_bpf *bpf) return -EINVAL; } - restart = idpf_xdp_enabled(vport) && netif_running(vport->netdev); + restart = idpf_xdp_enabled(vport) && + test_bit(IDPF_VPORT_UP, np->state); if (!restart) goto pool; -- 2.53.0.1066.g1eceb487f285