[PATCH 1/2] ubifs: tnc_delete: Don't free zero-branch znodes if memory allocation fails

Zhihao Cheng chengzhihao1 at huawei.com
Tue Oct 13 23:48:44 PDT 2026


在 2026/10/14 14:28, sashiko-bot at kernel.org 写道:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [High] ubifs: assertion failure on lookups due to zero-child znode after tnc_delete() error
> --
> 
> commit 5c1854483c2d06b6fd3fc46791b422fcd958956f
> Author: Zhihao Cheng <chengzhihao1 at huawei.com>
> 
> ubifs: tnc_delete: Don't free zero-branch znodes if memory allocation fails
> 
> This commit delays the freeing of zero-branch znodes in tnc_delete()
> until after all insert_old_idx_znode() calls succeed. It introduces a
> local stack list to track znodes to be freed, aiming to prevent a
> use-after-free race condition when traversing the TNC tree.
> 
>> diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c
>> --- a/fs/ubifs/tnc.c
>> +++ b/fs/ubifs/tnc.c
> [ ... ]
>> @@ -2542,15 +2543,20 @@ static int tnc_delete(struct ubifs_info *c, struct ubifs_znode *znode, int n)
>>   		atomic_long_dec(&c->dirty_zn_cnt);
>>   
>>   		err = insert_old_idx_znode(c, znode);
>> -		if (err)
>> +		if (err) {
>> +			zn = free_head.fnext;
>> +			while (zn) {
>> +				struct ubifs_znode *next = zn->fnext;
>> +
>> +				zn->fnext = NULL;
>> +				zn = next;
>> +			}
>>   			return err;
> 
> [Severity: High]
> If insert_old_idx_znode() returns an error like -ENOMEM, does this early
> return leave the zero-child znode linked in the TNC tree?
> 
> Because we return before removing the znode from its parent's zbranch array,
> the tree retains a node with child_cnt == 0. If a subsequent read operation
> (which is permitted even after the filesystem is forced to read-only mode)
> traverses this znode, it will call ubifs_search_zbranch():
> 
> fs/ubifs/tnc_misc.c:ubifs_search_zbranch() {
>          int beg = 0, end = znode->child_cnt, mid;
>          int cmp;
>          const struct ubifs_zbranch *zbr = &znode->zbranch[0];
> 
>          ubifs_assert(c, end > beg);
> ...
> }
> 
> With end == 0 and beg == 0, this will trigger the assertion failure, which
> can panic the kernel if mounted with assert=panic. Does this error path need
> to remove the znode from its parent's zbranch, or otherwise mark it to
> prevent lookups from tripping the assertion?
> 

Hi, the insert_old_idx_znode() makes tnc_delete return immediately even 
level0_znode->child_cnt becomes zero, which could trigger following 
assertion failure in ubifs_search_zbranch(), this is an already existed 
process.
This issue is not severe because after the insert_old_idx_znode error 
occurs, UBIFS has already switched to read-only mode and issued an 
alarm. Subsequent ubifs_assert is merely printing more alarms, unless 
the mount option uses assert=panic.



More information about the linux-mtd mailing list