[PATCH 1/1] ubifs: fix slab-out-of-bounds in pack_inode via xattr
Zhihao Cheng
chengzhihao1 at huawei.com
Wed Jun 3 21:57:05 PDT 2026
在 2026/6/4 0:37, Ren Wei 写道:
> From: Luxiao Xu <rakukuip at gmail.com>
>
> An issue in fs/ubifs/journal.c was found where a malicious or corrupted
> ubifs image could trigger a slab-out-of-bounds write in pack_inode().
>
> When an inode with extended attributes (xattrs) is being evicted or
> deleted (i.e., 'last_reference' and 'kill_xattrs' are true),
> ubifs_jnl_write_inode() calculates the allocation size 'write_len'
> based on 'ui->xattr_cnt' from the disk.
>
> However, if 'ui->xattr_cnt' is maliciously tampered with or corrupted
> to be smaller than the actual number of xattr entries stored in the
> TNC (Tree Node Cache), kmalloc() will allocate an undersized buffer.
> The subsequent 'while (1)' loop continues to iterate through all actual
> xattr entries via ubifs_tnc_next_ent(), advancing the 'ino' pointer
> and invoking pack_inode() for each entry. This mismatch leads to an
> out-of-bounds memory write, corrupting the slab redzone and triggering
> a KASAN panic.
>
> Fix this by introducing a strict counter 'xattrs_deleted' within the
> deletion loop. The loop is aborted with -EUCLEAN if the number of
> processed xattrs exceeds 'ui->xattr_cnt', preventing 'ino' from
> overflowing the allocated kmalloc buffer.
>
> The bug is reachable by a non-root user via user and net namespace.
>
> Fixes: 7959cf3a7506 ("ubifs: journal: Handle xattrs like files")
> Cc: stable at kernel.org
> Reported-by: Yuan Tan <yuantan098 at gmail.com>
> Reported-by: Yifan Wu <yifanwucs at gmail.com>
> Reported-by: Juefei Pu <tomapufckgml at gmail.com>
> Reported-by: Xin Liu <bird at lzu.edu.cn>
> Signed-off-by: Luxiao Xu <rakukuip at gmail.com>
> Signed-off-by: Ren Wei <n05ec at lzu.edu.cn>
> ---
> fs/ubifs/journal.c | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
Hi Luxiao,
Each metadata(inode/dentry) entry will checked with crc while loading
from flash(see ubifs_read_node->ubifs_check_node), I don't think
corrupted image will trigger the problem, because
ubifs_lookup->ubifs_iget will fail after detecting crc error. Unless
someone manually inject wong number into 'ui->xattr_cnt' fieled and
update the whole ino node crc, and I don't think it is a real problem
need to be fixed. In that injection method, no one filesystem is okay.
The bitflips happen both in node field(eg. xattr_cnt) and crc field is
an almost impossible thing.
> diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c
> index d02509920baf..78fe9d2a3178 100644
> --- a/fs/ubifs/journal.c
> +++ b/fs/ubifs/journal.c
> @@ -880,6 +880,7 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode)
> struct fscrypt_name nm = {0};
> struct inode *xino;
> struct ubifs_dent_node *xent, *pxent = NULL;
> + int xattrs_deleted = 0;
>
> if (ui->xattr_cnt > ubifs_xattr_max_cnt(c)) {
> err = -EPERM;
> @@ -899,6 +900,14 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode)
> goto out_release;
> }
>
> + if (xattrs_deleted >= ui->xattr_cnt) {
> + kfree(pxent);
> + kfree(xent);
> + err = -EUCLEAN;
> + ubifs_err(c, "xattr count mismatch for ino %lu", inode->i_ino);
> + goto out_release;
> + }
> +
> fname_name(&nm) = xent->name;
> fname_len(&nm) = le16_to_cpu(xent->nlen);
>
> @@ -917,6 +926,7 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode)
> clear_nlink(xino);
> pack_inode(c, ino, xino, 0);
> ino = (void *)ino + UBIFS_INO_NODE_SZ;
> + xattrs_deleted++;
> iput(xino);
>
> kfree(pxent);
>
More information about the linux-mtd
mailing list