In the Linux kernel, the following vulnerability has been resolved: RDMA/cma: Ensure rdmaaddrcancel() happens before issuing more requests The FSM can run in a circle allowing rdmaresolveip() to be called twice on the same idpriv. While this cannot happen without going through the work, it violates the invariant that the same address resolution background request cannot be active twice. CPU 1 CPU 2 rdmaresolveaddr(): RDMACMIDLE -> RDMACMADDRQUERY rdmaresolveip(addrhandler) #1 processonereq(): for #1 addrhandler(): RDMACMADDRQUERY -> RDMACMADDRBOUND mutexunlock(&idpriv->handlermutex); [.. handler still running ..] rdmaresolveaddr(): RDMACMADDRBOUND -> RDMACMADDRQUERY rdmaresolveip(addrhandler) !! two requests are now on the reqlist rdmadestroyid(): destroyidhandlerunlock(): destroyid(): cmacanceloperation(): rdmaaddrcancel() // processonereq() self removes it spinlockbh(&lock); canceldelayedwork(&req->work); if (!listempty(&req->list)) == true ! rdmaaddrcancel() returns after processonreq #1 is done kfree(idpriv) processonereq(): for #2 addrhandler(): mutexlock(&idpriv->handlermutex); !! Use after free on idpriv rdmaaddrcancel() expects there to be one req on the list and only cancels the first one. The self-removal behavior of the work only happens after the handler has returned. This yields a situations where the reqlist can have two reqs for the same "handle" but rdmaaddrcancel() only cancels the first one. The second req remains active beyond rdmadestroyid() and will use-after-free idpriv once it inevitably triggers. Fix this by remembering if the idpriv has called rdmaresolveip() and always cancel before calling it again. This ensures the req_list never gets more than one item in it and doesn't cost anything in the normal flow that never uses this strange error path.