• Steffen Maier's avatar
    scsi: zfcp: Fix use-after-free in request timeout handlers · d25a2b92
    Steffen Maier authored
    commit 2d9a2c5f upstream.
    
    Before v4.15 commit 75492a51 ("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/20200813152856.50088-1-maier@linux.ibm.com
    Fixes: 75492a51 ("s390/scsi: Convert timers to use timer_setup()")
    Cc: <stable@vger.kernel.org> #4.15+
    Suggested-by: default avatarJulian Wiedmann <jwi@linux.ibm.com>
    Reviewed-by: default avatarJulian Wiedmann <jwi@linux.ibm.com>
    Signed-off-by: default avatarSteffen Maier <maier@linux.ibm.com>
    Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    d25a2b92
zfcp_fsf.c 67 KB