Release PTP, which cancels the aux worker, before the unwind frees the
vports, matching the idpf_vc_core_deinit() order. Previously it was
possible for idpf_ptp_update_cached_phctime() which runs via the PTP
auxiliary worker to read a non-NULL but already freed slot, pass its NULL
check, and dereference the freed vport. This can happen on driver load,
where any vport past the first fails to initialize:

  BUG: KASAN: slab-use-after-free in idpf_ptp_update_cached_phctime+0x4ad/0x4d0 
[idpf]
  Read of size 8 at addr ff11002129215050 by task ptp3/10120
  ...
  idpf_ptp_update_cached_phctime+0x4ad/0x4d0 [idpf]
  idpf_ptp_do_aux_work+0x37/0x50 [idpf]
  ptp_aux_kworker+0x64/0xd0
  kthread_worker_fn+0x289/0xa20
  ...
  Allocated by task 8820 on cpu 32 at 2113.761375s:
  idpf_init_task+0x321/0x21c0 [idpf]a
  process_one_work+0x917/0x1940
  worker_thread+0x5a5/0xfe0
  ...
  Freed by task 8820 on cpu 32 at 2113.809014s:
  idpf_vport_dealloc+0x8cf/0x16b0 [idpf]
  idpf_init_task+0x245/0x21c0 [idpf]
  process_one_work+0x917/0x1940
  worker_thread+0x5a5/0xfe0

The aux worker is armed in idpf_vc_core_init() before idpf_init_task() is
queued, so it is live throughout a failing init, leading to the scenario
above.

Fixes: 1a49cf814fe1 ("idpf: add Tx timestamp flows")
Reviewed-by: Madhu Chittim <[email protected]>
Signed-off-by: Emil Tantilov <[email protected]>
Reported-by: Konstantin Ilichev <[email protected]>
---
 drivers/net/ethernet/intel/idpf/idpf_lib.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/intel/idpf/idpf_lib.c 
b/drivers/net/ethernet/intel/idpf/idpf_lib.c
index a1c739cdd540..9c541dd6ed4d 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_lib.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_lib.c
@@ -1747,6 +1747,8 @@ void idpf_init_task(struct work_struct *work)
        return;
 
 unwind_vports:
+       idpf_ptp_release(adapter);
+
        if (default_vport) {
                for (index = 0; index < adapter->max_vports; index++) {
                        if (adapter->vports[index])
@@ -1760,7 +1762,6 @@ void idpf_init_task(struct work_struct *work)
                cancel_delayed_work_sync(&adapter->serv_task);
                cancel_delayed_work_sync(&adapter->mbx_task);
        }
-       idpf_ptp_release(adapter);
 
        clear_bit(IDPF_HR_RESET_IN_PROG, adapter->flags);
 }
-- 
2.37.3

Reply via email to