In the Linux kernel, the following vulnerability has been resolved:
dibs: fix use-after-free of dmb_node in loopback attach/detach/unregister
dibs_lo_attach_dmb(), dibs_lo_detach_dmb() and dibs_lo_unregister_dmb() look up the dmb_node under dmb_ht_lock, drop the lock and only then operate on the node's refcount. Nothing keeps the node alive across that window: __dibs_lo_unregister_dmb() removes the node from the hash table under the write lock and immediately frees it.
A concurrent final put can therefore free the node between the lookup and the refcount operation:
CPU0 (attach) CPU1 (owner unregisters)
read_lock_bh(&dmb_ht_lock) find dmb_node (refcnt == 1) read_unlock_bh(&dmb_ht_lock) refcount_dec_and_test() 1 -> 0 write_lock_bh(&dmb_ht_lock) hash_del(&dmb_node->list) write_unlock_bh(&dmb_ht_lock) kfree(dmb_node) refcount_inc_not_zero(&dmb_node->refcnt) <-- use-after-free
The same window exists for the refcount_dec_and_test() calls in the detach and unregister paths.
Close the race structurally by making hash table membership and the refcount transitions atomic with respect to each other:
- Perform the final refcount_dec_and_test() and hash_del() in a single
- This establishes the invariant that any node found in the hash table
__dibs_lo_unregister_dmb() no longer touches the hash table and is renamed to dibs_lo_free_dmb() accordingly.
Note: commit cc21191b584c ("dibs: Move data path to dibs layer") moved the code to its current location; the race was introduced earlier by commit c3a910f2380f ("net/smc: implement DMB-merged operations of loopback-ism").
Tested SMC-D via ISM and dibs loopback.