CVE-2022-49159
Severity CVSS v4.0:
Pending analysis
Type:
Unavailable / Other
Publication date:
26/02/2025
Last modified:
26/02/2025
Description
In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
scsi: qla2xxx: Implement ref count for SRB<br />
<br />
The timeout handler and the done function are racing. When<br />
qla2x00_async_iocb_timeout() starts to run it can be preempted by the<br />
normal response path (via the firmware?). qla24xx_async_gpsc_sp_done()<br />
releases the SRB unconditionally. When scheduling back to<br />
qla2x00_async_iocb_timeout() qla24xx_async_abort_cmd() will access an freed<br />
sp->qpair pointer:<br />
<br />
qla2xxx [0000:83:00.0]-2871:0: Async-gpsc timeout - hdl=63d portid=234500 50:06:0e:80:08:77:b6:21.<br />
qla2xxx [0000:83:00.0]-2853:0: Async done-gpsc res 0, WWPN 50:06:0e:80:08:77:b6:21<br />
qla2xxx [0000:83:00.0]-2854:0: Async-gpsc OUT WWPN 20:45:00:27:f8:75:33:00 speeds=2c00 speed=0400.<br />
qla2xxx [0000:83:00.0]-28d8:0: qla24xx_handle_gpsc_event 50:06:0e:80:08:77:b6:21 DS 7 LS 6 rc 0 login 1|1 rscn 1|0 lid 5<br />
BUG: unable to handle kernel NULL pointer dereference at 0000000000000004<br />
IP: qla24xx_async_abort_cmd+0x1b/0x1c0 [qla2xxx]<br />
<br />
Obvious solution to this is to introduce a reference counter. One reference<br />
is taken for the normal code path (the &#39;good&#39; case) and one for the timeout<br />
path. As we always race between the normal good case and the timeout/abort<br />
handler we need to serialize it. Also we cannot assume any order between<br />
the handlers. Since this is slow path we can use proper synchronization via<br />
locks.<br />
<br />
When we are able to cancel a timer (del_timer returns 1) we know there<br />
can&#39;t be any error handling in progress because the timeout handler hasn&#39;t<br />
expired yet, thus we can safely decrement the refcounter by one.<br />
<br />
If we are not able to cancel the timer, we know an abort handler is<br />
running. We have to make sure we call sp->done() in the abort handlers<br />
before calling kref_put().