Re: [PATCH net] dibs: fix use-after-free of dmb_node in loopback attach/detach/unregister
Alexandra Winter <[email protected]> Wed, 29 Jul 2026 13:44:50 +0200
| Newsgroups | dev.linux.lists.sashiko-reviews,org.kernel.vger.linux-s390 |
|---|---|
| Message-ID | <[email protected]> |
On 28.07.26 11:35, [email protected] wrote: > Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider: > > Pre-existing issues: > - [High] dibs_lo_detach_dmb() fails to clear dibs->dmb_clientid_arr when dropping the final reference, leading to permanent client resource leaks. > - [High] Double free of dibs->dmb_clientid_arr in dibs_lo_dev_probe() error path. > - [High] Race condition in dibs_lo_move_data() routes spurious interrupts to wrong clients. > -- > > --- Patch [1]: [PATCH net] dibs: fix use-after-free of dmb_node in loopback attach/detach/unregister --- > commit 90d8ce044f1442abf2a546d5baabbf36276d4b45 > Author: Hidayath Khan <[email protected]> > > dibs: fix use-after-free of dmb_node in loopback attach/detach/unregister > > This commit fixes a use-after-free race condition in the DMB loopback > operations. It closes the race by making the hash table membership and refcount > transitions atomic with respect to each other under the write lock. Freeing the > node is now handled safely after the lock is dropped. > >> diff --git a/drivers/dibs/dibs_loopback.c b/drivers/dibs/dibs_loopback.c >> index 0f2e093111526..fd5caf1e19a8f 100644 >> --- a/drivers/dibs/dibs_loopback.c >> +++ b/drivers/dibs/dibs_loopback.c > [ ... ] >> @@ -209,11 +205,12 @@ static int dibs_lo_detach_dmb(struct dibs_dev *dibs, u64 token) >> { > [ ... ] >> + last = refcount_dec_and_test(&dmb_node->refcnt); >> + if (last) >> + hash_del(&dmb_node->list); >> + write_unlock_bh(&ldev->dmb_ht_lock); >> + >> + if (last) >> + dibs_lo_free_dmb(ldev, dmb_node); > > [Severity: High] > This isn't a bug introduced by this patch, but does this code fail to clear > the client ID array when dropping the final reference? > > When an owner unregisters a DMB that still has active attachers (refcount > 1), > dibs_lo_unregister_dmb() does not clear the array because last == false. > This is a true statement for future dibs clients (=dmb owners), but the current only dibs client smc does not do that. All dibs-loopback dmbs are detached before they are unregistered. -> not an issue today. I will follow up to make this more future-proof. > When the final attacher detaches, dibs_lo_detach_dmb() drops the refcount to 0, > frees the node and the sba_idx, but structurally fails to clear > dibs->dmb_clientid_arr[sba_idx]. > > Could this leave a stale client ID in dmb_clientid_arr indefinitely, causing > future unregistration to fail with -EBUSY and permanently leaking the client > resource? > >> >> - if (refcount_dec_and_test(&dmb_node->refcnt)) >> - __dibs_lo_unregister_dmb(ldev, dmb_node); >> return 0; >> } > > [Severity: High] > This is a pre-existing issue, but is there a double free of > dibs->dmb_clientid_arr in the dibs_lo_dev_probe() error path? Ack. Hidayath will send a fix soon. > > If dibs_dev_add() fails internally, it frees the array without nullifying it: > > drivers/dibs/dibs_main.c:dibs_dev_add() { > ... > free_client_arr: > kfree(dibs->dmb_clientid_arr); > return ret; > } > > The caller receives the error and unconditionally frees the already-freed array > again: > > drivers/dibs/dibs_loopback.c:dibs_lo_dev_probe() { > ... > err_reg: > kfree(dibs->dmb_clientid_arr); > ... > } > > Could this double-free cause slab allocator corruption? > > [Severity: High] > This is a pre-existing issue, but is there a race condition in > dibs_lo_move_data() that routes spurious interrupts to wrong clients? > > The target sba_idx is cached and the protection lock is dropped: > > drivers/dibs/dibs_loopback.c:dibs_lo_move_data() { > ... > sba_idx = rmb_node->sba_idx; > read_unlock_bh(&ldev->dmb_ht_lock); > ... > } > > Before it acquires the lock to trigger the IRQ, another CPU could drop the > final reference to the DMB, free the node, and clear its sba_idx. > > If a completely different client then immediately registers a new DMB and > reallocates the same sba_idx, will the IRQ be routed to the wrong client when > the code continues? > Not an issue today, because smc is the only dibs-client. But definitively needs improvement. I will follow up. > drivers/dibs/dibs_loopback.c:dibs_lo_move_data() { > ... > spin_lock(&dibs->lock); > client_id = dibs->dmb_clientid_arr[sba_idx]; > s_mask = ror16(0x1000, idx); > if (likely(client_id != NO_DIBS_CLIENT && dibs->subs[client_id])) > dibs->subs[client_id]->ops->handle_irq(dibs, sba_idx, s_mask); > ... > } >