* [PATCH 1/3] coda: is_bad_inode() is always false there
2026-04-05 2:15 [PATCH 0/3] coda dcache-related cleanups and fixes Al Viro
@ 2026-04-05 2:15 ` Al Viro
2026-04-05 2:15 ` [PATCH 2/3] sanitize coda_dentry_delete() Al Viro
` (2 subsequent siblings)
3 siblings, 0 replies; 7+ messages in thread
From: Al Viro @ 2026-04-05 2:15 UTC (permalink / raw)
To: linux-fsdevel; +Cc: Christian Brauner, Jan Kara, Jan Harkes
... since dbd822046445 ("[PATCH] Coda FS update") back in 2002
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/coda/dir.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index c64b8cd81568..799c3d3ea12c 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -449,8 +449,6 @@ static int coda_dentry_revalidate(struct inode *dir, const struct qstr *name,
inode = d_inode(de);
if (!inode || is_root_inode(inode))
goto out;
- if (is_bad_inode(inode))
- goto bad;
cii = ITOC(d_inode(de));
if (!(cii->c_flags & (C_PURGE | C_FLUSH)))
@@ -470,7 +468,6 @@ static int coda_dentry_revalidate(struct inode *dir, const struct qstr *name,
spin_lock(&cii->c_lock);
cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
spin_unlock(&cii->c_lock);
-bad:
return 0;
out:
return 1;
@@ -489,7 +486,7 @@ static int coda_dentry_delete(const struct dentry * dentry)
return 0;
inode = d_inode(dentry);
- if (!inode || is_bad_inode(inode))
+ if (!inode)
return 1;
cii = ITOC(inode);
--
2.47.3
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 2/3] sanitize coda_dentry_delete()
2026-04-05 2:15 [PATCH 0/3] coda dcache-related cleanups and fixes Al Viro
2026-04-05 2:15 ` [PATCH 1/3] coda: is_bad_inode() is always false there Al Viro
@ 2026-04-05 2:15 ` Al Viro
2026-04-05 2:15 ` [PATCH 3/3] coda_flag_children(): fix a UAF Al Viro
2026-04-07 22:05 ` [PATCH 0/3] coda dcache-related cleanups and fixes Jan Harkes
3 siblings, 0 replies; 7+ messages in thread
From: Al Viro @ 2026-04-05 2:15 UTC (permalink / raw)
To: linux-fsdevel; +Cc: Christian Brauner, Jan Kara, Jan Harkes
d_really_is_negative(dentry) is a check for d_inode(dentry) being NULL;
rechecking that is pointless (and no, it can't race - the caller is holding
->d_lock, so ->d_inode is stable)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/coda/dir.c | 12 +++---------
1 file changed, 3 insertions(+), 9 deletions(-)
diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index 799c3d3ea12c..2a5048bab635 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -479,18 +479,12 @@ static int coda_dentry_revalidate(struct inode *dir, const struct qstr *name,
*/
static int coda_dentry_delete(const struct dentry * dentry)
{
- struct inode *inode;
- struct coda_inode_info *cii;
-
- if (d_really_is_negative(dentry))
- return 0;
+ struct inode *inode = d_inode(dentry);
- inode = d_inode(dentry);
if (!inode)
- return 1;
+ return 0;
- cii = ITOC(inode);
- if (cii->c_flags & C_PURGE)
+ if (ITOC(inode)->c_flags & C_PURGE)
return 1;
return 0;
--
2.47.3
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH 3/3] coda_flag_children(): fix a UAF
2026-04-05 2:15 [PATCH 0/3] coda dcache-related cleanups and fixes Al Viro
2026-04-05 2:15 ` [PATCH 1/3] coda: is_bad_inode() is always false there Al Viro
2026-04-05 2:15 ` [PATCH 2/3] sanitize coda_dentry_delete() Al Viro
@ 2026-04-05 2:15 ` Al Viro
2026-04-07 22:05 ` [PATCH 0/3] coda dcache-related cleanups and fixes Jan Harkes
3 siblings, 0 replies; 7+ messages in thread
From: Al Viro @ 2026-04-05 2:15 UTC (permalink / raw)
To: linux-fsdevel; +Cc: Christian Brauner, Jan Kara, Jan Harkes
if de goes negative right under us, there's nothing to prevent inode
getting freed just as we call coda_flag_inode(). We are not holding
->d_lock, so it's not impossible. Not going to be reproducible on
bare hardware unless it's a realtime config, but it could happen on KVM.
Trivial to fix - just hold rcu_read_lock() over that loop.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
fs/coda/cache.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/fs/coda/cache.c b/fs/coda/cache.c
index 970f0022ec52..245131296300 100644
--- a/fs/coda/cache.c
+++ b/fs/coda/cache.c
@@ -93,12 +93,14 @@ static void coda_flag_children(struct dentry *parent, int flag)
struct dentry *de;
spin_lock(&parent->d_lock);
+ rcu_read_lock();
hlist_for_each_entry(de, &parent->d_children, d_sib) {
struct inode *inode = d_inode_rcu(de);
/* don't know what to do with negative dentries */
if (inode)
coda_flag_inode(inode, flag);
}
+ rcu_read_unlock();
spin_unlock(&parent->d_lock);
}
--
2.47.3
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH 0/3] coda dcache-related cleanups and fixes
2026-04-05 2:15 [PATCH 0/3] coda dcache-related cleanups and fixes Al Viro
` (2 preceding siblings ...)
2026-04-05 2:15 ` [PATCH 3/3] coda_flag_children(): fix a UAF Al Viro
@ 2026-04-07 22:05 ` Jan Harkes
2026-04-21 20:06 ` [git pull] " Al Viro
3 siblings, 1 reply; 7+ messages in thread
From: Jan Harkes @ 2026-04-07 22:05 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel, Christian Brauner, Jan Kara
Thank you so much for looking at this.
On Sun, Apr 05, 2026 at 03:15:12AM +0100, Al Viro wrote:
> 1) prior to 2002 coda_revalidate_inode() used make_bad_inode() on
> failures; is_bad_inode() checks used to make sense back then. For
> the last 23.5 years they had been dead code; let's take them out...
Ah, yeah, didn't realize that, "if it works don't fix it" is not much
use when the code we call has been dead for that long.
> 2) coda ->d_delete() appears to have been hit by somebody overhardened
> back in 2021. Useful tip: if we've just checked d_really_is_negative()
> and it had returned false, dentry->d_inode is *NOT* going to be NULL.
>
> 3) coda_flag_children() is holding ->d_lock on parent while iterating
> through the list of its children; that's fine, but that does not protect
> ->d_inode of individual children. Hold rcu_read_lock() over the entire
> loop to prevent UAF there...
>
> No preferences regarding the tree these would go through; at the moment
> it's in
> git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs.git #work.coda
> but if coda folks prefer to route those through another tree, just say
> so.
Your vfs tree is perfectly fine by me. Again, thanks for doing this.
All the changes look good to me. I'll give them a spin and I will let
you know if anything goes bad, but if you don't hear from me assume
things worked.
Jan
^ permalink raw reply [flat|nested] 7+ messages in thread* [git pull] coda dcache-related cleanups and fixes
2026-04-07 22:05 ` [PATCH 0/3] coda dcache-related cleanups and fixes Jan Harkes
@ 2026-04-21 20:06 ` Al Viro
2026-04-21 21:56 ` pr-tracker-bot
0 siblings, 1 reply; 7+ messages in thread
From: Al Viro @ 2026-04-21 20:06 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linux-fsdevel, Christian Brauner, Jan Kara, Jan Harkes
The following changes since commit 7aaa8047eafd0bd628065b15757d9b48c5f9c07d:
Linux 7.0-rc6 (2026-03-29 15:40:00 -0700)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs.git tags/pull-coda
for you to fetch changes up to e252ed8988578f01da5a4f5aa4c2269f96f03951:
coda_flag_children(): fix a UAF (2026-04-04 21:03:13 -0400)
----------------------------------------------------------------
coda cleanups and fixes
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
----------------------------------------------------------------
Al Viro (3):
coda: is_bad_inode() is always false there
sanitize coda_dentry_delete()
coda_flag_children(): fix a UAF
fs/coda/cache.c | 2 ++
fs/coda/dir.c | 15 +++------------
2 files changed, 5 insertions(+), 12 deletions(-)
^ permalink raw reply [flat|nested] 7+ messages in thread