Patch "scsi: zfcp: fix use-after-"free" in FC ingress path after TMF" has been added to the 4.4-stable tree
Subsystems (3)
This is a note to let you know that I've just added the patch titled
scsi: zfcp: fix use-after-"free" in FC ingress path after TMF
to the 4.4-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
scsi-zfcp-fix-use-after-free-in-fc-ingress-path-after-tmf.patch
and it can be found in the queue-4.4 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
dac37e15b7d511e026a9313c8c46794c144103cdMon Sep 17 00:00:00 2001
From: Benjamin Block <[email protected]>
Date: Fri, 9 Dec 2016 17:16:31 +0100
Subject: scsi: zfcp: fix use-after-"free" in FC ingress path after TMF
From: Benjamin Block <[email protected]>
commit dac37e15b7d511e026a9313c8c46794c144103cd upstream.
When SCSI EH invokes zFCP's callbacks for eh_device_reset_handler() and eh_target_reset_handler(), it expects us to relent the ownership over the given scsi_cmnd and all other scsi_cmnds within the same scope - LUN or target - when returning with SUCCESS from the callback ('release' them). SCSI EH can then reuse those commands.
We did not follow this rule to release commands upon SUCCESS; and if later a reply arrived for one of those supposed to be released commands, we would still make use of the scsi_cmnd in our ingress tasklet. This will at least result in undefined behavior or a kernel panic because of a wrong kernel pointer dereference.
To fix this, we NULLify all pointers to scsi_cmnds (struct zfcp_fsf_req *)->data in the matching scope if a TMF was successful. This is done under the locks (struct zfcp_adapter *)->abort_lock and (struct zfcp_reqlist *)->lock to prevent the requests from being removed from the request-hashtable, and the ingress tasklet from making use of the scsi_cmnd-pointer in zfcp_fsf_fcp_cmnd_handler().
For cases where a reply arrives during SCSI EH, but before we get a chance to NULLify the pointer - but before we return from the callback -, we assume that the code is protected from races via the CAS operation in blk_complete_request() that is called in scsi_done().
The following stacktrace shows an example for a crash resulting from the previous behavior:
Unable to handle kernel pointer dereference at virtual kernel address fffffee17a672000
Oops: 0038 [#1] SMP
CPU: 2 PID: 0 Comm: swapper/2 Not tainted
task: 00000003f7ff5be0 ti: 00000003f3d38000 task.ti: 00000003f3d38000
Krnl PSW : 0404d00180000000 00000000001156b0 (smp_vcpu_scheduled+0x18/0x40)
R:0 T:1 IO:0 EX:0 Key:0 M:1 W:0 P:0 AS:3 CC:1 PM:0 EA:3
Krnl GPRS: 000000200000007e 0000000000000000 fffffee17a671fd8 0000000300000015
ffffffff80000000 00000000005dfde8 07000003f7f80e00 000000004fa4e800
000000036ce8d8f8 000000036ce8d9c0 00000003ece8fe00 ffffffff969c9e93
00000003fffffffd 000000036ce8da10 00000000003bf134 00000003f3b07918
Krnl Code: 00000000001156a2: a7190000 lghi %r1,0
00000000001156a6: a7380015 lhi %r3,21
#00000000001156aa: e32050000008 ag %r2,0(%r5)
>00000000001156b0: 482022b0 lh %r2,688(%r2)
00000000001156b4: ae123000 sigp %r1,%r2,0(%r3)
00000000001156b8: b2220020 ipm %r2
00000000001156bc: 8820001c srl %r2,28
00000000001156c0: c02700000001 xilf %r2,1
Call Trace:
([<0000000000000000>] 0x0)
[<000003ff807bdb8e>] zfcp_fsf_fcp_cmnd_handler+0x3de/0x490 [zfcp]
[<000003ff807be30a>] zfcp_fsf_req_complete+0x252/0x800 [zfcp]
[<000003ff807c0a48>] zfcp_fsf_reqid_check+0xe8/0x190 [zfcp]
[<000003ff807c194e>] zfcp_qdio_int_resp+0x66/0x188 [zfcp]
[<000003ff80440c64>] qdio_kick_handler+0xdc/0x310 [qdio]
[<000003ff804463d0>] __tiqdio_inbound_processing+0xf8/0xcd8 [qdio]
[<0000000000141fd4>] tasklet_action+0x9c/0x170
[<0000000000141550>] __do_softirq+0xe8/0x258
[<000000000010ce0a>] do_softirq+0xba/0xc0
[<000000000014187c>] irq_exit+0xc4/0xe8
[<000000000046b526>] do_IRQ+0x146/0x1d8
[<00000000005d6a3c>] io_return+0x0/0x8
[<00000000005d6422>] vtime_stop_cpu+0x4a/0xa0
([<0000000000000000>] 0x0)
[<0000000000103d8a>] arch_cpu_idle+0xa2/0xb0
[<0000000000197f94>] cpu_startup_entry+0x13c/0x1f8
[<0000000000114782>] smp_start_secondary+0xda/0xe8
[<00000000005d6efe>] restart_int_handler+0x56/0x6c
[<0000000000000000>] 0x0Last Breaking-Event-Address:
[<00000000003bf12e>] arch_spin_lock_wait+0x56/0xb0
--- drivers/s390/scsi/zfcp_dbf.h | 11 +++++++ drivers/s390/scsi/zfcp_reqlist.h | 30 +++++++++++++++++++- drivers/s390/scsi/zfcp_scsi.c | 57 +++++++++++++++++++++++++++++++++++++-- 3 files changed, 95 insertions(+), 3 deletions(-)
drivers/s390/scsi/zfcp_dbf.h +11 -0
@@ -388,4 +388,15 @@ void zfcp_dbf_scsi_devreset(char *tag, s _zfcp_dbf_scsi(tmp_tag, 1, scmnd, NULL); } +/** +* zfcp_dbf_scsi_nullcmnd() - trace NULLify of SCSI command in dev/tgt-reset. +* @scmnd: SCSI command that was NULLified. +* @fsf_req: request that owned @scmnd. +*/ +static inline void zfcp_dbf_scsi_nullcmnd (struct scsi_cmnd *scmnd, +struct zfcp_fsf_req *fsf_req) +{ +_zfcp_dbf_scsi ("scfc__1" ,3 , scmnd, fsf_req); +} +#endif /* ZFCP_DBF_H */
drivers/s390/scsi/zfcp_reqlist.h +29 -1
@@ -4,7 +4,7 @@* Data structure and helper functions for tracking pending FSF * requests. * -* Copyright IBM Corp. 2009 +* Copyright IBM Corp. 2009, 2016 */ #ifndef ZFCP_REQLIST_H
@@ -180,4 +180,32 @@ static inline void zfcp_reqlist_move(str spin_unlock_irqrestore(&rl->lock, flags); } +/** +* zfcp_reqlist_apply_for_all() - apply a function to every request. +* @rl: the requestlist that contains the target requests. +* @f: the function to apply to each request; the first parameter of the +* function will be the target-request; the second parameter is the same +* pointer as given with the argument @data. +* @data: freely chosen argument; passed through to @f as second parameter. +* +* Uses :c:macro:`list_for_each_entry` to iterate over the lists in the hash- +* table (not a 'safe' variant, so don't modify the list). +* +* Holds @rl->lock over the entire request-iteration. +*/ +static inline void +zfcp_reqlist_apply_for_all (struct zfcp_reqlist *rl, +void (*f)(struct zfcp_fsf_req *,void *),void *data) +{ +struct zfcp_fsf_req *req; +unsigned long flags; +unsigned int i; + +spin_lock_irqsave (&rl->lock, flags); +for (i =0 ; i <ZFCP_REQ_LIST_BUCKETS ; i++) +list_for_each_entry (req, &rl->buckets[i], list) +f (req, data); +spin_unlock_irqrestore (&rl->lock, flags); +} +#endif /* ZFCP_REQLIST_H */
drivers/s390/scsi/zfcp_scsi.c +55 -2
76 lines not on this page · raw message
Patches currently in stable-queue which might be from [email protected] are
queue-4.4/scsi-zfcp-do-not-trace-pure-benign-residual-hba-responses-at-default-level.patch queue-4.4/scsi-zfcp-fix-rport-unblock-race-with-lun-recovery.patch queue-4.4/scsi-zfcp-fix-use-after-free-in-fc-ingress-path-after-tmf.patch