CVE-2021-47391

Severity CVSS v4.0:
Pending analysis
Type:
CWE-416 Use After Free
Publication date:
21/05/2024
Last modified:
23/09/2025

Description

In the Linux kernel, the following vulnerability has been resolved:<br /> <br /> RDMA/cma: Ensure rdma_addr_cancel() happens before issuing more requests<br /> <br /> The FSM can run in a circle allowing rdma_resolve_ip() to be called twice<br /> on the same id_priv. While this cannot happen without going through the<br /> work, it violates the invariant that the same address resolution<br /> background request cannot be active twice.<br /> <br /> CPU 1 CPU 2<br /> <br /> rdma_resolve_addr():<br /> RDMA_CM_IDLE -&gt; RDMA_CM_ADDR_QUERY<br /> rdma_resolve_ip(addr_handler) #1<br /> <br /> process_one_req(): for #1<br /> addr_handler():<br /> RDMA_CM_ADDR_QUERY -&gt; RDMA_CM_ADDR_BOUND<br /> mutex_unlock(&amp;id_priv-&gt;handler_mutex);<br /> [.. handler still running ..]<br /> <br /> rdma_resolve_addr():<br /> RDMA_CM_ADDR_BOUND -&gt; RDMA_CM_ADDR_QUERY<br /> rdma_resolve_ip(addr_handler)<br /> !! two requests are now on the req_list<br /> <br /> rdma_destroy_id():<br /> destroy_id_handler_unlock():<br /> _destroy_id():<br /> cma_cancel_operation():<br /> rdma_addr_cancel()<br /> <br /> // process_one_req() self removes it<br /> spin_lock_bh(&amp;lock);<br /> cancel_delayed_work(&amp;req-&gt;work);<br /> if (!list_empty(&amp;req-&gt;list)) == true<br /> <br /> ! rdma_addr_cancel() returns after process_on_req #1 is done<br /> <br /> kfree(id_priv)<br /> <br /> process_one_req(): for #2<br /> addr_handler():<br /> mutex_lock(&amp;id_priv-&gt;handler_mutex);<br /> !! Use after free on id_priv<br /> <br /> rdma_addr_cancel() expects there to be one req on the list and only<br /> cancels the first one. The self-removal behavior of the work only happens<br /> after the handler has returned. This yields a situations where the<br /> req_list can have two reqs for the same "handle" but rdma_addr_cancel()<br /> only cancels the first one.<br /> <br /> The second req remains active beyond rdma_destroy_id() and will<br /> use-after-free id_priv once it inevitably triggers.<br /> <br /> Fix this by remembering if the id_priv has called rdma_resolve_ip() and<br /> always cancel before calling it again. This ensures the req_list never<br /> gets more than one item in it and doesn&amp;#39;t cost anything in the normal flow<br /> that never uses this strange error path.

Vulnerable products and versions

CPE From Up to
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 2.6.18 (including) 5.10.188 (excluding)
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 5.11 (including) 5.14.10 (excluding)
cpe:2.3:o:linux:linux_kernel:5.15:rc1:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:5.15:rc2:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:5.15:rc3:*:*:*:*:*:*