If auxiliary_device_add() fails, idpf_plug_core_aux_dev() calls auxiliary_device_uninit(adev), whose release callback idpf_core_adev_release() frees the containing struct iidc_rdma_core_auxiliary_dev. The current error path then accesses adev->id and later frees iadev again, which may lead to a use-after-free and double free. Fix it by storing the allocated auxiliary device id in a local variable and avoiding direct freeing of iadev after auxiliary_device_uninit(). Fixes: f4312e6bfa2a ("idpf: implement core RDMA auxiliary dev create, init, and destroy") Cc: stable@vger.kernel.org Signed-off-by: Guangshuo Li --- drivers/net/ethernet/intel/idpf/idpf_idc.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/idpf/idpf_idc.c b/drivers/net/ethernet/intel/idpf/idpf_idc.c index 6dad0593f7f2..0fcbf9f1ddbb 100644 --- a/drivers/net/ethernet/intel/idpf/idpf_idc.c +++ b/drivers/net/ethernet/intel/idpf/idpf_idc.c @@ -197,6 +197,7 @@ static int idpf_plug_core_aux_dev(struct iidc_rdma_core_dev_info *cdev_info) char name[IDPF_IDC_MAX_ADEV_NAME_LEN]; struct auxiliary_device *adev; int ret; + int id; iadev = kzalloc(sizeof(*iadev), GFP_KERNEL); if (!iadev) @@ -211,12 +212,16 @@ static int idpf_plug_core_aux_dev(struct iidc_rdma_core_dev_info *cdev_info) pr_err("failed to allocate unique device ID for Auxiliary driver\n"); goto err_ida_alloc; } - adev->id = ret; + id = ret; + adev->id = id; adev->dev.release = idpf_core_adev_release; adev->dev.parent = &cdev_info->pdev->dev; sprintf(name, "%04x.rdma.core", cdev_info->pdev->vendor); adev->name = name; + /* iadev is owned by the auxiliary device */ + iadev = NULL; + ret = auxiliary_device_init(adev); if (ret) goto err_aux_dev_init; @@ -230,7 +235,7 @@ static int idpf_plug_core_aux_dev(struct iidc_rdma_core_dev_info *cdev_info) err_aux_dev_add: auxiliary_device_uninit(adev); err_aux_dev_init: - ida_free(&idpf_idc_ida, adev->id); + ida_free(&idpf_idc_ida, id); err_ida_alloc: cdev_info->adev = NULL; kfree(iadev); -- 2.43.0