[PATCH v2 5/5] ubifs: xattr: guard against xattr accounting underflow

From: shao.mingyin

Date: Tue Nov 03 2026 - 01:30:31 EST


remove_xattr() decrements the host inode's xattr counters, which are
stored on flash. An image can contain an xattr entry for an inode
whose counters are already zero or smaller than the entry. The
unsigned counters then wrap, and ubifs_jnl_delete_xattr() writes the
bogus values back to flash. On the next mount validate_inode() rejects
the inode because xattr_names + xattr_cnt exceeds XATTR_LIST_MAX, so a
single removexattr() turns a mountable image into one that cannot be
mounted.

Refuse the operation when the accounting cannot be decremented.

Fixes: 1e51764a3c2a ("UBIFS: add new flash file system")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Shao Mingyin <shao.mingyin@xxxxxxxxxx>
---
v2: no change since v1.

diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c
index 3b0e8a270f59..8f0447de94f0 100644
--- a/fs/ubifs/xattr.c
+++ b/fs/ubifs/xattr.c
@@ -456,6 +456,21 @@ static int remove_xattr(struct ubifs_info *c, struct inode *host,

ubifs_assert(c, ui->data_len == inode->i_size);

+ /*
+ * The per-inode xattr accounting is stored on flash and can disagree
+ * with the entries found in the TNC. Do not let a corrupted image
+ * underflow the counters, because the bogus values would then be
+ * written back to flash by ubifs_jnl_delete_xattr().
+ */
+ if (!host_ui->xattr_cnt ||
+ host_ui->xattr_names < fname_len(nm) ||
+ host_ui->xattr_size < CALC_DENT_SIZE(fname_len(nm)) +
+ CALC_XATTR_BYTES(ui->data_len)) {
+ ubifs_err(c, "xattr accounting mismatch for inode %llu",
+ host->i_ino);
+ return -EUCLEAN;
+ }
+
err = ubifs_budget_space(c, &req);
if (err)
return err;