Skip to content

Commit 2d9a2c5

Browse files
steffen-maiermartinkpetersen
authored andcommitted
scsi: zfcp: Fix use-after-free in request timeout handlers
Before v4.15 commit 75492a5 ("s390/scsi: Convert timers to use timer_setup()"), we intentionally only passed zfcp_adapter as context argument to zfcp_fsf_request_timeout_handler(). Since we only trigger adapter recovery, it was unnecessary to sync against races between timeout and (late) completion. Likewise, we only passed zfcp_erp_action as context argument to zfcp_erp_timeout_handler(). Since we only wakeup an ERP action, it was unnecessary to sync against races between timeout and (late) completion. Meanwhile the timeout handlers get timer_list as context argument and do a timer-specific container-of to zfcp_fsf_req which can have been freed. Fix it by making sure that any request timeout handlers, that might just have started before del_timer(), are completed by using del_timer_sync() instead. This ensures the request free happens afterwards. Space time diagram of potential use-after-free: Basic idea is to have 2 or more pending requests whose timeouts run out at almost the same time. req 1 timeout ERP thread req 2 timeout ---------------- ---------------- --------------------------------------- zfcp_fsf_request_timeout_handler fsf_req = from_timer(fsf_req, t, timer) adapter = fsf_req->adapter zfcp_qdio_siosl(adapter) zfcp_erp_adapter_reopen(adapter,...) zfcp_erp_strategy ... zfcp_fsf_req_dismiss_all list_for_each_entry_safe zfcp_fsf_req_complete 1 del_timer 1 zfcp_fsf_req_free 1 zfcp_fsf_req_complete 2 zfcp_fsf_request_timeout_handler del_timer 2 fsf_req = from_timer(fsf_req, t, timer) zfcp_fsf_req_free 2 adapter = fsf_req->adapter ^^^^^^^ already freed Link: https://lore.kernel.org/r/[email protected] Fixes: 75492a5 ("s390/scsi: Convert timers to use timer_setup()") Cc: <[email protected]> #4.15+ Suggested-by: Julian Wiedmann <[email protected]> Reviewed-by: Julian Wiedmann <[email protected]> Signed-off-by: Steffen Maier <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent d87a1f6 commit 2d9a2c5

File tree

1 file changed

+2
-2
lines changed

1 file changed

+2
-2
lines changed

drivers/s390/scsi/zfcp_fsf.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ static void zfcp_fsf_req_complete(struct zfcp_fsf_req *req)
434434
return;
435435
}
436436

437-
del_timer(&req->timer);
437+
del_timer_sync(&req->timer);
438438
zfcp_fsf_protstatus_eval(req);
439439
zfcp_fsf_fsfstatus_eval(req);
440440
req->handler(req);
@@ -867,7 +867,7 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *req)
867867
req->qdio_req.qdio_outb_usage = atomic_read(&qdio->req_q_free);
868868
req->issued = get_tod_clock();
869869
if (zfcp_qdio_send(qdio, &req->qdio_req)) {
870-
del_timer(&req->timer);
870+
del_timer_sync(&req->timer);
871871
/* lookup request again, list might have changed */
872872
zfcp_reqlist_find_rm(adapter->req_list, req_id);
873873
zfcp_erp_adapter_reopen(adapter, 0, "fsrs__1");

0 commit comments

Comments
 (0)