CVE-2022-49789

Severity CVSS v4.0:
Pending analysis
Type:
Unavailable / Other
Publication date:
01/05/2025
Last modified:
02/05/2025

Description

In the Linux kernel, the following vulnerability has been resolved:<br /> <br /> scsi: zfcp: Fix double free of FSF request when qdio send fails<br /> <br /> We used to use the wrong type of integer in &amp;#39;zfcp_fsf_req_send()&amp;#39; to cache<br /> the FSF request ID when sending a new FSF request. This is used in case the<br /> sending fails and we need to remove the request from our internal hash<br /> table again (so we don&amp;#39;t keep an invalid reference and use it when we free<br /> the request again).<br /> <br /> In &amp;#39;zfcp_fsf_req_send()&amp;#39; we used to cache the ID as &amp;#39;int&amp;#39; (signed and 32<br /> bit wide), but the rest of the zfcp code (and the firmware specification)<br /> handles the ID as &amp;#39;unsigned long&amp;#39;/&amp;#39;u64&amp;#39; (unsigned and 64 bit wide [s390x<br /> ELF ABI]). For one this has the obvious problem that when the ID grows<br /> past 32 bit (this can happen reasonably fast) it is truncated to 32 bit<br /> when storing it in the cache variable and so doesn&amp;#39;t match the original ID<br /> anymore. The second less obvious problem is that even when the original ID<br /> has not yet grown past 32 bit, as soon as the 32nd bit is set in the<br /> original ID (0x80000000 = 2&amp;#39;147&amp;#39;483&amp;#39;648) we will have a mismatch when we<br /> cast it back to &amp;#39;unsigned long&amp;#39;. As the cached variable is of a signed<br /> type, the compiler will choose a sign-extending instruction to load the 32<br /> bit variable into a 64 bit register (e.g.: &amp;#39;lgf %r11,188(%r15)&amp;#39;). So once<br /> we pass the cached variable into &amp;#39;zfcp_reqlist_find_rm()&amp;#39; to remove the<br /> request again all the leading zeros will be flipped to ones to extend the<br /> sign and won&amp;#39;t match the original ID anymore (this has been observed in<br /> practice).<br /> <br /> If we can&amp;#39;t successfully remove the request from the hash table again after<br /> &amp;#39;zfcp_qdio_send()&amp;#39; fails (this happens regularly when zfcp cannot notify<br /> the adapter about new work because the adapter is already gone during<br /> e.g. a ChpID toggle) we will end up with a double free. We unconditionally<br /> free the request in the calling function when &amp;#39;zfcp_fsf_req_send()&amp;#39; fails,<br /> but because the request is still in the hash table we end up with a stale<br /> memory reference, and once the zfcp adapter is either reset during recovery<br /> or shutdown we end up freeing the same memory twice.<br /> <br /> The resulting stack traces vary depending on the kernel and have no direct<br /> correlation to the place where the bug occurs. Here are three examples that<br /> have been seen in practice:<br /> <br /> list_del corruption. next-&gt;prev should be 00000001b9d13800, but was 00000000dead4ead. (next=00000001bd131a00)<br /> ------------[ cut here ]------------<br /> kernel BUG at lib/list_debug.c:62!<br /> monitor event: 0040 ilc:2 [#1] PREEMPT SMP<br /> Modules linked in: ...<br /> CPU: 9 PID: 1617 Comm: zfcperp0.0.1740 Kdump: loaded<br /> Hardware name: ...<br /> Krnl PSW : 0704d00180000000 00000003cbeea1f8 (__list_del_entry_valid+0x98/0x140)<br /> R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:0 AS:3 CC:1 PM:0 RI:0 EA:3<br /> Krnl GPRS: 00000000916d12f1 0000000080000000 000000000000006d 00000003cb665cd6<br /> 0000000000000001 0000000000000000 0000000000000000 00000000d28d21e8<br /> 00000000d3844000 00000380099efd28 00000001bd131a00 00000001b9d13800<br /> 00000000d3290100 0000000000000000 00000003cbeea1f4 00000380099efc70<br /> Krnl Code: 00000003cbeea1e8: c020004f68a7 larl %r2,00000003cc8d7336<br /> 00000003cbeea1ee: c0e50027fd65 brasl %r14,00000003cc3e9cb8<br /> #00000003cbeea1f4: af000000 mc 0,0<br /> &gt;00000003cbeea1f8: c02000920440 larl %r2,00000003cd12aa78<br /> 00000003cbeea1fe: c0e500289c25 brasl %r14,00000003cc3fda48<br /> 00000003cbeea204: b9040043 lgr %r4,%r3<br /> 00000003cbeea208: b9040051 lgr %r5,%r1<br /> 00000003cbeea20c: b9040032 lgr %r3,%r2<br /> Call Trace:<br /> [] __list_del_entry_valid+0x98/0x140<br /> ([] __list_del_entry_valid+0x94/0x140)<br /> [] zfcp_fsf_req_dismiss_all+0xde/0x150 [zfcp]<br /> [] zfcp_erp_strategy_do_action+0x160/0x280 [zfcp]<br /> ---truncated---

Impact