From 6fa6e4e21afd9360c7cdc24b8c1bdf6df274940c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 1 Feb 2026 12:10:54 -0500 Subject: coda: is_bad_inode() is always false there ... since dbd822046445 ("[PATCH] Coda FS update") back in 2002 Signed-off-by: Al Viro --- 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); -- cgit v1.2.3 From e6d683673167763ac364108b0b0eb10d0c605868 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 1 Feb 2026 12:18:30 -0500 Subject: sanitize coda_dentry_delete() 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 --- 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 @@ out: */ 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; -- cgit v1.2.3 From e252ed8988578f01da5a4f5aa4c2269f96f03951 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 1 Feb 2026 12:33:37 -0500 Subject: coda_flag_children(): fix a UAF 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 --- 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); } -- cgit v1.2.3