* [PATCH 0/3] ubifs: fix an auth node leak and two error-handling bugs
@ 2026-11-02 11:50 shao.mingyin
2026-11-02 12:12 ` [PATCH 1/3] ubifs: gc: fix authentication node leak shao.mingyin
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: shao.mingyin @ 2026-11-02 11:50 UTC (permalink / raw)
To: richard; +Cc: linux-mtd, chengzhihao1, linux-kernel, stable
This series fixes three independent problems in ubifs, all found while
auditing the error paths around the GC write-buffer, xattr creation and
authenticated node hashing.
Patch 1 fixes a leak. move_nodes() allocates the authentication node for
the GC journal head and writes it into the GC write-buffer; the buffer is
freed only when one of the steps fails. On an authenticated file system
every GC pass that moves nodes therefore leaks ubifs_auth_node_sz()
bytes, so the loss is unbounded on a long-running system.
Patch 2 fixes state that survives a failed operation. create_xattr()
sets UBIFS_CRYPT_FL for inodes that carry an encryption context, but its
error path clears the flag whether this call set it or not. A setxattr()
that fails before anything reaches the journal, for example because its
journal buffer cannot be allocated, therefore leaves the in-memory inode
marked as unencrypted; the next inode write persists that, and after the
next mount the inode is no longer treated as encrypted although its names
and data still are.
Patch 3 stops five call sites from ignoring ubifs_node_calc_hash(). With
authentication enabled a failing crypto operation leaves those callers
using an uninitialised stack buffer as the node hash; it is then stored in
the TNC or in the master node, and the affected nodes fail verification
later.
The three patches are independent and can be applied in any order or as a
subset. They are listed by severity, not by dependency: the leak first,
then the persistent state loss, then the error propagation.
All three carry Fixes: and Cc: stable.
Testing: the patches apply to next-20261030, pass checkpatch.pl --strict
with 0 errors/0 warnings/0 checks, and fs/ubifs/ builds with
CONFIG_UBIFS_FS_AUTHENTICATION, CONFIG_UBIFS_FS_XATTR and
CONFIG_UBIFS_FS_SECURITY enabled and W=1 without new warnings. They were
not exercised at runtime: this machine has no UBI/MTD tooling or
emulation, so there is no mount test. Patch 1 is the easiest to verify by
inspection; patch 2 needs an allocation or I/O failure in
ubifs_jnl_update(); patch 3 needs a crypto failure inside
ubifs_node_calc_hash().
Signed-off-by: Shao Mingyin <shao.mingyin@zte.com.cn>
---
base-commit: 7649ba73f9e7e1e04d0b46213e39c79ae09dd55c
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH 1/3] ubifs: gc: fix authentication node leak 2026-11-02 11:50 [PATCH 0/3] ubifs: fix an auth node leak and two error-handling bugs shao.mingyin @ 2026-11-02 12:12 ` shao.mingyin 2026-11-02 12:13 ` [PATCH 2/3] ubifs: xattr: preserve the encryption flag when creation fails shao.mingyin 2026-11-02 12:14 ` [PATCH 3/3] ubifs: check node hash calculation errors shao.mingyin 2 siblings, 0 replies; 5+ messages in thread From: shao.mingyin @ 2026-11-02 12:12 UTC (permalink / raw) To: richard, linux-mtd; +Cc: chengzhihao1, linux-kernel, stable move_nodes() allocates the authentication node, writes it to the GC write-buffer and only frees it on the error paths. Every GC pass that moves nodes on an authenticated file system therefore leaks ubifs_auth_node_sz() bytes. Free the buffer after it has been written to the write-buffer. Fixes: 6f06d96fdf62 ("ubifs: Add auth nodes to garbage collector journal head") Cc: stable@vger.kernel.org Signed-off-by: Shao Mingyin <shao.mingyin@zte.com.cn> --- diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c index 933c79b5cd6b..2b0f29423f48 100644 --- a/fs/ubifs/gc.c +++ b/fs/ubifs/gc.c @@ -427,6 +427,7 @@ static int move_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb) kfree(auth); goto out; } + kfree(auth); ubifs_add_dirt(c, wbuf->lnum, ubifs_auth_node_sz(c)); } ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 2/3] ubifs: xattr: preserve the encryption flag when creation fails 2026-11-02 11:50 [PATCH 0/3] ubifs: fix an auth node leak and two error-handling bugs shao.mingyin 2026-11-02 12:12 ` [PATCH 1/3] ubifs: gc: fix authentication node leak shao.mingyin @ 2026-11-02 12:13 ` shao.mingyin 2026-11-02 12:14 ` [PATCH 3/3] ubifs: check node hash calculation errors shao.mingyin 2 siblings, 0 replies; 5+ messages in thread From: shao.mingyin @ 2026-11-02 12:13 UTC (permalink / raw) To: richard, linux-mtd; +Cc: chengzhihao1, linux-kernel, stable create_xattr() clears UBIFS_CRYPT_FL in its error path regardless of whether this call set the flag. The flag is also set for every inode that already carries an encryption context, so a failed setxattr() on such an inode clears it from the in-memory inode. The next inode write then packs ui->flags without UBIFS_CRYPT_FL, and after the next mount the inode is no longer treated as encrypted although its names and data still are. ubifs_jnl_update() can fail before anything is written, for example when its journal buffer cannot be allocated. Remember whether this call actually set the flag and only clear it in that case. Fixes: d475a507457b ("ubifs: Add skeleton for fscrypto") Cc: stable@vger.kernel.org Signed-off-by: Shao Mingyin <shao.mingyin@zte.com.cn> --- diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c index 3b0e8a270f59..7f82ddb9e3f2 100644 --- a/fs/ubifs/xattr.c +++ b/fs/ubifs/xattr.c @@ -69,6 +69,7 @@ static int create_xattr(struct ubifs_info *c, struct inode *host, const struct fscrypt_name *nm, const void *value, int size) { int err, names_len; + bool set_crypt = false; struct inode *inode; struct ubifs_inode *ui, *host_ui = ubifs_inode(host); struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1, @@ -133,8 +134,10 @@ static int create_xattr(struct ubifs_info *c, struct inode *host, * To avoid multiple updates of the same inode in the same operation, * let's do it here. */ - if (strcmp(fname_name(nm), UBIFS_XATTR_NAME_ENCRYPTION_CONTEXT) == 0) + if (strcmp(fname_name(nm), UBIFS_XATTR_NAME_ENCRYPTION_CONTEXT) == 0) { + set_crypt = !(host_ui->flags & UBIFS_CRYPT_FL); host_ui->flags |= UBIFS_CRYPT_FL; + } err = ubifs_jnl_update(c, host, nm, inode, 0, 1, 0); if (err) @@ -152,7 +155,8 @@ static int create_xattr(struct ubifs_info *c, struct inode *host, host_ui->xattr_size -= CALC_DENT_SIZE(fname_len(nm)); host_ui->xattr_size -= CALC_XATTR_BYTES(size); host_ui->xattr_names -= fname_len(nm); - host_ui->flags &= ~UBIFS_CRYPT_FL; + if (set_crypt) + host_ui->flags &= ~UBIFS_CRYPT_FL; mutex_unlock(&host_ui->ui_mutex); out_free: make_bad_inode(inode); ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 3/3] ubifs: check node hash calculation errors 2026-11-02 11:50 [PATCH 0/3] ubifs: fix an auth node leak and two error-handling bugs shao.mingyin 2026-11-02 12:12 ` [PATCH 1/3] ubifs: gc: fix authentication node leak shao.mingyin 2026-11-02 12:13 ` [PATCH 2/3] ubifs: xattr: preserve the encryption flag when creation fails shao.mingyin @ 2026-11-02 12:14 ` shao.mingyin 2026-11-02 13:41 ` Zhihao Cheng 2 siblings, 1 reply; 5+ messages in thread From: shao.mingyin @ 2026-11-02 12:14 UTC (permalink / raw) To: richard, linux-mtd; +Cc: chengzhihao1, linux-kernel, stable ubifs_node_calc_hash() can fail when authentication is enabled and the crypto operation fails. Five calls ignore the return value and use the uninitialized stack buffer as the node hash: replay_bud() stores it in the replay entry, make_idx_node() and write_index() copy it into the parent branch or the index root, and create_default_filesystem() copies it into an index branch and into the master node. Verifying those nodes later then fails with a hash mismatch. Propagate the error from all five call sites. Fixes: 16a26b20d2af ("ubifs: authentication: Add hashes to index nodes") Fixes: 104115a3eb54 ("ubifs: Add hashes and HMACs to default filesystem") Cc: stable@vger.kernel.org Signed-off-by: Shao Mingyin <shao.mingyin@zte.com.cn> --- diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c index 263045e05cf1..442493dc18c6 100644 --- a/fs/ubifs/replay.c +++ b/fs/ubifs/replay.c @@ -730,7 +730,9 @@ static int replay_bud(struct ubifs_info *c, struct bud_entry *b) goto out_dump; } - ubifs_node_calc_hash(c, snod->node, hash); + err = ubifs_node_calc_hash(c, snod->node, hash); + if (err) + goto out; if (snod->sqnum > c->max_sqnum) c->max_sqnum = snod->sqnum; diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c index e7693b94e5b5..1c176be261e0 100644 --- a/fs/ubifs/sb.c +++ b/fs/ubifs/sb.c @@ -329,14 +329,18 @@ static int create_default_filesystem(struct ubifs_info *c) if (err) goto out; - ubifs_node_calc_hash(c, ino, hash); + err = ubifs_node_calc_hash(c, ino, hash); + if (err) + goto out; ubifs_copy_hash(c, hash, ubifs_branch_hash(c, br)); err = ubifs_write_node(c, idx, idx_node_size, main_first + DEFAULT_IDX_LEB, 0); if (err) goto out; - ubifs_node_calc_hash(c, idx, hash); + err = ubifs_node_calc_hash(c, idx, hash); + if (err) + goto out; ubifs_copy_hash(c, hash, mst->hash_root_idx); err = ubifs_write_node_hmac(c, mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM, 0, diff --git a/fs/ubifs/tnc_commit.c b/fs/ubifs/tnc_commit.c index 7bf2672062a2..1a62739c3731 100644 --- a/fs/ubifs/tnc_commit.c +++ b/fs/ubifs/tnc_commit.c @@ -52,7 +52,9 @@ static int make_idx_node(struct ubifs_info *c, struct ubifs_idx_node *idx, } } ubifs_prepare_node(c, idx, len, 0); - ubifs_node_calc_hash(c, idx, hash); + err = ubifs_node_calc_hash(c, idx, hash); + if (err) + return err; znode->lnum = lnum; znode->offs = offs; @@ -887,7 +889,9 @@ static int write_index(struct ubifs_info *c) } len = ubifs_idx_node_sz(c, znode->child_cnt); ubifs_prepare_node(c, idx, len, 0); - ubifs_node_calc_hash(c, idx, hash); + err = ubifs_node_calc_hash(c, idx, hash); + if (err) + return err; mutex_lock(&c->tnc_mutex); ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 3/3] ubifs: check node hash calculation errors 2026-11-02 12:14 ` [PATCH 3/3] ubifs: check node hash calculation errors shao.mingyin @ 2026-11-02 13:41 ` Zhihao Cheng 0 siblings, 0 replies; 5+ messages in thread From: Zhihao Cheng @ 2026-11-02 13:41 UTC (permalink / raw) To: shao.mingyin, richard, linux-mtd; +Cc: linux-kernel, stable 在 2026/11/2 20:14, shao.mingyin@zte.com.cn 写道: > ubifs_node_calc_hash() can fail when authentication is enabled and the > crypto operation fails. Five calls ignore the return value and use the > uninitialized stack buffer as the node hash: replay_bud() stores it in > the replay entry, make_idx_node() and write_index() copy it into the > parent branch or the index root, and create_default_filesystem() copies > it into an index branch and into the master node. Verifying those nodes > later then fails with a hash mismatch. > > Propagate the error from all five call sites. > > Fixes: 16a26b20d2af ("ubifs: authentication: Add hashes to index nodes") > Fixes: 104115a3eb54 ("ubifs: Add hashes and HMACs to default filesystem") > Cc: stable@vger.kernel.org > Signed-off-by: Shao Mingyin <shao.mingyin@zte.com.cn> Reviewed-by: Zhihao Cheng <chengzhihao1@huawei.com> > --- > diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c > index 263045e05cf1..442493dc18c6 100644 > --- a/fs/ubifs/replay.c > +++ b/fs/ubifs/replay.c > @@ -730,7 +730,9 @@ static int replay_bud(struct ubifs_info *c, struct bud_entry *b) > goto out_dump; > } > > - ubifs_node_calc_hash(c, snod->node, hash); > + err = ubifs_node_calc_hash(c, snod->node, hash); > + if (err) > + goto out; > > if (snod->sqnum > c->max_sqnum) > c->max_sqnum = snod->sqnum; > diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c > index e7693b94e5b5..1c176be261e0 100644 > --- a/fs/ubifs/sb.c > +++ b/fs/ubifs/sb.c > @@ -329,14 +329,18 @@ static int create_default_filesystem(struct ubifs_info *c) > if (err) > goto out; > > - ubifs_node_calc_hash(c, ino, hash); > + err = ubifs_node_calc_hash(c, ino, hash); > + if (err) > + goto out; > ubifs_copy_hash(c, hash, ubifs_branch_hash(c, br)); > > err = ubifs_write_node(c, idx, idx_node_size, main_first + DEFAULT_IDX_LEB, 0); > if (err) > goto out; > > - ubifs_node_calc_hash(c, idx, hash); > + err = ubifs_node_calc_hash(c, idx, hash); > + if (err) > + goto out; > ubifs_copy_hash(c, hash, mst->hash_root_idx); > > err = ubifs_write_node_hmac(c, mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM, 0, > diff --git a/fs/ubifs/tnc_commit.c b/fs/ubifs/tnc_commit.c > index 7bf2672062a2..1a62739c3731 100644 > --- a/fs/ubifs/tnc_commit.c > +++ b/fs/ubifs/tnc_commit.c > @@ -52,7 +52,9 @@ static int make_idx_node(struct ubifs_info *c, struct ubifs_idx_node *idx, > } > } > ubifs_prepare_node(c, idx, len, 0); > - ubifs_node_calc_hash(c, idx, hash); > + err = ubifs_node_calc_hash(c, idx, hash); > + if (err) > + return err; > > znode->lnum = lnum; > znode->offs = offs; > @@ -887,7 +889,9 @@ static int write_index(struct ubifs_info *c) > } > len = ubifs_idx_node_sz(c, znode->child_cnt); > ubifs_prepare_node(c, idx, len, 0); > - ubifs_node_calc_hash(c, idx, hash); > + err = ubifs_node_calc_hash(c, idx, hash); > + if (err) > + return err; > > mutex_lock(&c->tnc_mutex); > . > ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-11-02 13:41 UTC | newest] Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-11-02 11:50 [PATCH 0/3] ubifs: fix an auth node leak and two error-handling bugs shao.mingyin 2026-11-02 12:12 ` [PATCH 1/3] ubifs: gc: fix authentication node leak shao.mingyin 2026-11-02 12:13 ` [PATCH 2/3] ubifs: xattr: preserve the encryption flag when creation fails shao.mingyin 2026-11-02 12:14 ` [PATCH 3/3] ubifs: check node hash calculation errors shao.mingyin 2026-11-02 13:41 ` Zhihao Cheng
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®