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