Re: [PATCH net] dibs: fix double free of dmb_clientid_arr

Alexandra Winter <[email protected]> Fri, 31 Jul 2026 16:04:51 +0200
Newsgroups dev.linux.lists.sashiko-reviews,org.kernel.vger.linux-s390
Message-ID <[email protected]>

On 31.07.26 09:56, [email protected] wrote:
> Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
> 
> Pre-existing issues:
> - [High] The hardware interrupt handler `ism_handle_irq()` can execute out-of-order with respect to initialization and teardown of critical resources, leading to crashes (UAF, NULL deref, and uninitialized spinlock accesses).
> - [High] `dibs_unregister_client()` leaves the subsystem in an inconsistent partial state if it aborts midway through its device iteration.
> - [High] `dibs_lo_attach_dmb` drops the hash table read lock before incrementing the object's reference count, leading to a Use-After-Free.
> --
> 
> --- Patch [1]: [PATCH net] dibs: fix double free of dmb_clientid_arr ---
> commit 45565b8a1cec1239be540b3b54fad60822ae8b57
> Author: Hidayath Khan <[email protected]>
> 
> dibs: fix double free of dmb_clientid_arr
> 
> dibs_dev_add() frees dibs->dmb_clientid_arr on both of its failure
> paths, but does not clear the pointer. dibs_lo_dev_probe() then frees
> the same pointer again in its err_reg path, so a failing device_add()
> or sysfs_create_group() results in a double free.
> 
> Drop the kfree() from dibs_lo_dev_probe().
> 
> Cc: [email protected]
> 
>> diff --git a/drivers/dibs/dibs_loopback.c b/drivers/dibs/dibs_loopback.c
>> index 0f2e093111526..aeb8787ea9816 100644
>> --- a/drivers/dibs/dibs_loopback.c
>> +++ b/drivers/dibs/dibs_loopback.c
>> @@ -334,7 +334,6 @@ static int dibs_lo_dev_probe(void)
>>  	return 0;
>>  
>>  err_reg:
>> -	kfree(dibs->dmb_clientid_arr);
> 
> [Severity: High]
> This isn't a bug introduced by this patch, but does dibs_lo_attach_dmb() have
> a use-after-free if the reference count is incremented after dropping the hash
> table lock?
> 
> drivers/dibs/dibs_loopback.c:dibs_lo_attach_dmb() {
> ...
> 	read_unlock_bh(&ldev->dmb_ht_lock);
> 
> 	if (!refcount_inc_not_zero(&dmb_node->refcnt))
> ...
> }

Fixed by
a10ea943356b ("dibs: fix use-after-free of dmb_node in loopback attach/detach/unregister")
that got accepted to net yesterday.


> 
> If a concurrent thread executing dibs_lo_unregister_dmb() acquires the lock
> and drops the refcount to zero, could it free the node before the first thread
> resumes, causing refcount_inc_not_zero() to operate on freed memory?
> 
> [Severity: High]
> This is a pre-existing issue, but is there an initialization race with the
> hardware interrupt handler in ism_drv.c?
> 
> drivers/s390/net/ism_drv.c:ism_probe() {
> ...
> 	ret = dibs_dev_add(dibs);
> ...
> }
> 
> If the hardware interrupt is registered before dibs_dev_add() initializes
> resources, and a spurious interrupt fires, could ism_handle_irq() access an
> uninitialized spinlock or dereference a NULL pointer?
> 

Hidayath has already sent a fix for the lock initialization:
https://lore.kernel.org/netdev/[email protected]/



> drivers/s390/net/ism_drv.c:ism_handle_irq() {
> ...
> 		client_id = dibs->dmb_clientid_arr[bit];
> ...
> }


No client can have registered a dmb at that point, so
no dmb interrupt can occur, so this NULL pointer dereference cannot happen irl.
I plan to restructure with a future cleanup patch.


> 
> Similarly, during teardown:
> 
> drivers/s390/net/ism_drv.c:ism_remove() {
> ...
> 	dibs_dev_del(dibs);
> 	ism_dev_exit(ism);
> ...
> }
> 
> Could freeing resources like dibs->dmb_clientid_arr via dibs_dev_del() before
> the active IRQ is unregistered create a use-after-free window?
> 


Yes, we will send a fix.


> [Severity: High]
> This is also a pre-existing issue, but does dibs_unregister_client() leave the
> subsystem in an inconsistent state if it aborts early?
> 
> drivers/dibs/dibs_main.c:dibs_unregister_client() {
> ...
> 				rc = -EBUSY;
> 				goto err_reg_dmb;
> ...
> }
> 
> If the loop successfully processes some devices but then encounters a device
> with active DMBs, it returns -EBUSY without rolling back the teardown on the
> previously processed devices. If the caller ignores this return value and
> proceeds to unload the module, could the detached devices later trigger an
> event and dereference freed ops function pointers?
> 
>>  	/* pairs with dibs_dev_alloc() */
>>  	put_device(&dibs->dev);
>>  	kfree(ldev);
> 


Does not happen with smc today.
But the guard is not clean, it should do a better and safer cleanup,
should such a situation arise with a future client.
I will work on an improvement.