From: Al Viro <viro@zeniv.linux.org.uk>
To: Chris Mason <clm@meta.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
bot+bpf-ci@kernel.org, linux-fsdevel@vger.kernel.org,
torvalds@linux-foundation.org, brauner@kernel.org, jack@suse.cz,
raven@themaw.net, miklos@szeredi.hu, neil@brown.name,
a.hindborg@kernel.org, linux-mm@kvack.org,
linux-efi@vger.kernel.org, ocfs2-devel@lists.linux.dev,
kees@kernel.org, rostedt@goodmis.org, linux-usb@vger.kernel.org,
paul@paul-moore.com, casey@schaufler-ca.com,
linuxppc-dev@lists.ozlabs.org, john.johansen@canonical.com,
selinux@vger.kernel.org, borntraeger@linux.ibm.com,
bpf@vger.kernel.org, ast@kernel.org, andrii@kernel.org,
daniel@iogearbox.net, martin.lau@kernel.org, eddyz87@gmail.com,
yonghong.song@linux.dev, ihor.solodrai@linux.dev
Subject: Re: [functionfs] mainline UAF (was Re: [PATCH v3 36/50] functionfs: switch to simple_remove_by_name())
Date: Fri, 14 Nov 2025 07:58:54 +0000 [thread overview]
Message-ID: <20251114075854.GZ2441659@ZenIV> (raw)
In-Reply-To: <3984c9bd-2ac8-424e-9390-7170fdab3c03@meta.com>
On Thu, Nov 13, 2025 at 09:16:52PM -0500, Chris Mason wrote:
> ================================================================================
> BUG #2: Race condition in ffs_data_closed()
> ================================================================================
>
> In ffs_data_closed(), there's an unsynchronized state modification:
>
> static void ffs_data_closed(struct ffs_data *ffs)
> {
> ...
> if (atomic_dec_and_test(&ffs->opened)) {
> if (ffs->no_disconnect) {
> ffs->state = FFS_DEACTIVATED;
> ...
> } else {
> ffs->state = FFS_CLOSING;
> ffs_data_reset(ffs);
> }
> }
> if (atomic_read(&ffs->opened) < 0) {
> ffs->state = FFS_CLOSING;
> ffs_data_reset(ffs);
> }
> ...
> }
>
> Can this race with concurrent state changes? The atomic_read() check is not
> synchronized with the subsequent state assignment. Between the read and the
> assignment, another thread could modify the state, potentially causing state
> machine corruption or double cleanup via ffs_data_reset().
The atomic_read() check is utter bollocks. ->opened starts with 0, is bumped
on opens on that fs and decremented when files are closed. How could it end
up negative? Well might you ask - there's a call of ffs_data_closed() in
ffs_kill_sb(). _There_ we are guaranteed that there's no opened files (we'd
better, or there would be much worse problems), so ffs->opened is known to
be 0 and ffs_data_closed() decrements it to -1.
In other words, that couple of lines is executed on call from ffs_kill_sb()
and only on that call. Which is to say, that thing is just an obfuscated
if (s->s_fs_info) {
struct ffs_data *ffs = s->s_fs_info;
ffs->state = FFS_CLOSING;
ffs_data_reset(ffs);
ffs_data_put(ffs);
}
Not a race, just a highly unidiomatic code. While we are at it, after taking
that mess out of ffs_data_closed() we no longer need to bump/drop ffs->ref
in ffs_data_opened()/ffs_data_closed() - superblock owns a reference all along
and it's *not* going away under an opened file.
next prev parent reply other threads:[~2025-11-14 7:58 UTC|newest]
Thread overview: 77+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-11 6:54 [PATCH v3 00/50] tree-in-dcache stuff Al Viro
2025-11-11 6:54 ` [PATCH v3 01/50] fuse_ctl_add_conn(): fix nlink breakage in case of early failure Al Viro
2025-11-11 10:22 ` Miklos Szeredi
2025-11-11 6:54 ` [PATCH v3 02/50] tracefs: fix a leak in eventfs_create_events_dir() Al Viro
2025-11-11 6:54 ` [PATCH v3 03/50] new helper: simple_remove_by_name() Al Viro
2025-11-11 10:29 ` Miklos Szeredi
2025-11-11 6:54 ` [PATCH v3 04/50] new helper: simple_done_creating() Al Viro
2025-11-11 6:54 ` [PATCH v3 05/50] introduce a flag for explicitly marking persistently pinned dentries Al Viro
2025-11-11 6:54 ` [PATCH v3 06/50] primitives for maintaining persisitency Al Viro
2025-11-11 6:54 ` [PATCH v3 07/50] convert simple_{link,unlink,rmdir,rename,fill_super}() to new primitives Al Viro
2025-11-11 6:54 ` [PATCH v3 08/50] convert ramfs and tmpfs Al Viro
2025-11-11 6:54 ` [PATCH v3 09/50] procfs: make /self and /thread_self dentries persistent Al Viro
2025-11-11 6:54 ` [PATCH v3 10/50] configfs, securityfs: kill_litter_super() not needed Al Viro
2025-11-11 6:54 ` [PATCH v3 11/50] convert xenfs Al Viro
2025-11-11 6:54 ` [PATCH v3 12/50] convert smackfs Al Viro
2025-11-11 6:54 ` [PATCH v3 13/50] convert hugetlbfs Al Viro
2025-11-11 6:54 ` [PATCH v3 14/50] convert mqueue Al Viro
2025-11-11 6:54 ` [PATCH v3 15/50] convert bpf Al Viro
2025-11-11 6:54 ` [PATCH v3 16/50] convert dlmfs Al Viro
2025-11-11 6:54 ` [PATCH v3 17/50] convert fuse_ctl Al Viro
2025-11-11 10:28 ` Miklos Szeredi
2025-11-11 6:54 ` [PATCH v3 18/50] convert pstore Al Viro
2025-11-11 6:54 ` [PATCH v3 19/50] convert tracefs Al Viro
2025-11-11 6:54 ` [PATCH v3 20/50] convert debugfs Al Viro
2025-11-11 6:54 ` [PATCH v3 21/50] debugfs: remove duplicate checks in callers of start_creating() Al Viro
2025-11-11 6:54 ` [PATCH v3 22/50] convert efivarfs Al Viro
2025-11-11 6:54 ` [PATCH v3 23/50] convert spufs Al Viro
2025-11-11 6:54 ` [PATCH v3 24/50] convert ibmasmfs Al Viro
2025-11-11 6:54 ` [PATCH v3 25/50] ibmasmfs: get rid of ibmasmfs_dir_ops Al Viro
2025-11-11 6:54 ` [PATCH v3 26/50] convert devpts Al Viro
2025-11-11 6:54 ` [PATCH v3 27/50] binderfs: use simple_start_creating() Al Viro
2025-11-11 6:54 ` [PATCH v3 28/50] binderfs_binder_ctl_create(): kill a bogus check Al Viro
2025-11-11 6:54 ` [PATCH v3 29/50] convert binderfs Al Viro
2025-11-11 6:54 ` [PATCH v3 30/50] autofs_{rmdir,unlink}: dentry->d_fsdata->dentry == dentry there Al Viro
2025-11-11 6:55 ` [PATCH v3 31/50] convert autofs Al Viro
2025-11-11 6:55 ` [PATCH v3 32/50] convert binfmt_misc Al Viro
2025-11-11 6:55 ` [PATCH v3 33/50] selinuxfs: don't stash the dentry of /policy_capabilities Al Viro
2025-11-11 6:55 ` [PATCH v3 34/50] selinuxfs: new helper for attaching files to tree Al Viro
2025-11-11 7:53 ` bot+bpf-ci
2025-11-11 9:49 ` Al Viro
2025-11-12 3:55 ` Chris Mason
2025-11-11 6:55 ` [PATCH v3 35/50] convert selinuxfs Al Viro
2025-11-11 6:55 ` [PATCH v3 36/50] functionfs: switch to simple_remove_by_name() Al Viro
2025-11-11 7:53 ` bot+bpf-ci
2025-11-11 9:22 ` Al Viro
2025-11-11 9:30 ` Christian Brauner
2025-11-11 10:01 ` Al Viro
2025-11-11 14:25 ` Chris Mason
2025-11-12 3:44 ` Chris Mason
2025-11-13 9:26 ` [functionfs] mainline UAF (was Re: [PATCH v3 36/50] functionfs: switch to simple_remove_by_name()) Al Viro
2025-11-13 21:20 ` Greg Kroah-Hartman
2025-11-14 2:16 ` Chris Mason
2025-11-14 7:58 ` Al Viro [this message]
2025-11-14 7:46 ` Al Viro
2025-11-14 11:42 ` Christian Brauner
2025-11-15 13:21 ` Greg Kroah-Hartman
2025-11-16 6:30 ` Al Viro
2025-11-17 22:04 ` Al Viro
2025-11-17 22:04 ` [PATCH 1/4] functionfs: don't abuse ffs_data_closed() on fs shutdown Al Viro
2025-11-17 22:05 ` [PATCH 2/4] functionfs: don't bother with ffs->ref in ffs_data_{opened,closed}() Al Viro
2025-11-17 22:06 ` [PATCH 3/4] functionfs: need to cancel ->reset_work in ->kill_sb() Al Viro
2025-11-17 22:06 ` [PATCH 4/4] functionfs: fix the open/removal races Al Viro
2025-11-18 2:35 ` [functionfs] mainline UAF (was Re: [PATCH v3 36/50] functionfs: switch to simple_remove_by_name()) Greg Kroah-Hartman
2025-11-11 6:55 ` [PATCH v3 37/50] convert functionfs Al Viro
2025-11-11 6:55 ` [PATCH v3 38/50] gadgetfs: switch to simple_remove_by_name() Al Viro
2025-11-11 6:55 ` [PATCH v3 39/50] convert gadgetfs Al Viro
2025-11-11 6:55 ` [PATCH v3 40/50] hypfs: don't pin dentries twice Al Viro
2025-11-11 6:55 ` [PATCH v3 41/50] hypfs: switch hypfs_create_str() to returning int Al Viro
2025-11-11 6:55 ` [PATCH v3 42/50] hypfs: swich hypfs_create_u64() " Al Viro
2025-11-11 6:55 ` [PATCH v3 43/50] convert hypfs Al Viro
2025-11-11 6:55 ` [PATCH v3 44/50] convert rpc_pipefs Al Viro
2025-11-11 6:55 ` [PATCH v3 45/50] convert nfsctl Al Viro
2025-11-11 6:55 ` [PATCH v3 46/50] convert rust_binderfs Al Viro
2025-11-11 6:55 ` [PATCH v3 47/50] get rid of kill_litter_super() Al Viro
2025-11-11 6:55 ` [PATCH v3 48/50] convert securityfs Al Viro
2025-11-11 6:55 ` [PATCH v3 49/50] kill securityfs_recursive_remove() Al Viro
2025-11-11 6:55 ` [PATCH v3 50/50] d_make_discardable(): warn if given a non-persistent dentry Al Viro
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251114075854.GZ2441659@ZenIV \
--to=viro@zeniv.linux.org.uk \
--cc=a.hindborg@kernel.org \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=borntraeger@linux.ibm.com \
--cc=bot+bpf-ci@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=brauner@kernel.org \
--cc=casey@schaufler-ca.com \
--cc=clm@meta.com \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
--cc=gregkh@linuxfoundation.org \
--cc=ihor.solodrai@linux.dev \
--cc=jack@suse.cz \
--cc=john.johansen@canonical.com \
--cc=kees@kernel.org \
--cc=linux-efi@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-usb@vger.kernel.org \
--cc=linuxppc-dev@lists.ozlabs.org \
--cc=martin.lau@kernel.org \
--cc=miklos@szeredi.hu \
--cc=neil@brown.name \
--cc=ocfs2-devel@lists.linux.dev \
--cc=paul@paul-moore.com \
--cc=raven@themaw.net \
--cc=rostedt@goodmis.org \
--cc=selinux@vger.kernel.org \
--cc=torvalds@linux-foundation.org \
--cc=yonghong.song@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.