Linux filesystem development
 help / color / mirror / Atom feed
* [REPORT] binfmt_misc: leaked write-access denial on F-flag interpreter inode
@ 2026-07-18  4:43 Vivek Parikh
  2026-07-19 11:47 ` Jori Koolstra
  0 siblings, 1 reply; 2+ messages in thread
From: Vivek Parikh @ 2026-07-18  4:43 UTC (permalink / raw)
  To: viro, brauner, kees; +Cc: linux-fsdevel

Note: this bug was found with AI assistance, so I am treating it as public
per Documentation/process/security-bugs. A reproducer (unprivileged C PoC)
is available on request; I am not posting it here.

Summary
-------
put_binfmt_handler() closes an F-flag (MISC_FMT_OPEN_FILE) entry's
interpreter file without restoring the write access that open_exec()
denied at registration. Every register/delete cycle of an F entry leaks
one i_writecount denial on the interpreter's inode, so that inode returns
-ETXTBSY to all writers until it is evicted from the inode cache or the
machine reboots.

Affected versions
-----------------
Introduced in v4.7 by commit 948b701a607f. Present through v7.2.0-rc3
(fs/binfmt_misc.c:162-168). Root-only from v4.7; reachable by an
unprivileged user from v6.7 onward, when binfmt_misc gained
FS_USERNS_MOUNT and can be mounted inside a user namespace with no
capability check on registration (on systems that permit unprivileged
user namespaces).

Details
-------
Registration of an F entry opens the interpreter via open_exec()
(fs/binfmt_misc.c:821), which calls exe_file_deny_write_access() in
do_open_execat() (fs/exec.c:800). do_open_execat() documents that the
caller must call exe_file_allow_write_access() before releasing the file.

The registration error path honors this (fs/binfmt_misc.c:834):

        exe_file_allow_write_access(f);
        filp_close(f, NULL);

The teardown path does not (fs/binfmt_misc.c:162-168):

        static void put_binfmt_handler(Node *e)
        {
                if (refcount_dec_and_test(&e->users)) {
                        if (e->flags & MISC_FMT_OPEN_FILE)
                                filp_close(e->interp_file, NULL);
                        kfree(e);
                }
        }

filp_close()/fput() do not reverse the deny count, so the denial is
leaked. This is the persistent file opened by open_exec() at
registration; it is distinct from the per-exec clone made in
load_misc_binary() (fs/binfmt_misc.c:251-254), which is released
elsewhere.

Reproduction (conditions)
-------------------------
- CONFIG_BINFMT_MISC enabled.
- For the unprivileged case: kernel/distro permitting unprivileged user
  namespaces (v6.7+ for the userns-mount path).
- Steps: mount binfmt_misc; register ":x:E::x::<victim>:F" for any
  world-readable regular file on a non-noexec mount; delete the entry
  ("echo -1"); open(victim, O_WRONLY) then fails with -ETXTBSY.
The victim needs no execute bit; open_exec only requires a regular file
on a non-noexec mount.

Verified: unprivileged (uid 1000) on a 7.0.0-27-generic host, and as
root on a 7.2.0-rc3 build.

Fix
---
Mirror the registration error-path fix on the teardown path.
exe_file_allow_write_access() is NULL-safe and skips the same
FMODE_FSNOTIFY_HSM files that exe_file_deny_write_access() skipped, so
no imbalance is possible.

diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -162,8 +162,10 @@ static void put_binfmt_handler(Node *e)
 static void put_binfmt_handler(Node *e)
 {
  if (refcount_dec_and_test(&e->users)) {
- if (e->flags & MISC_FMT_OPEN_FILE)
+ if (e->flags & MISC_FMT_OPEN_FILE) {
+ exe_file_allow_write_access(e->interp_file);
  filp_close(e->interp_file, NULL);
+ }
  kfree(e);
  }
 }

Fixes: 948b701a607f ("binfmt_misc: add persistent opened binary
handler for containers")
Signed-off-by: Vivek Parikh <viv0411.parikh@gmail.com>

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-07-19 11:46 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-18  4:43 [REPORT] binfmt_misc: leaked write-access denial on F-flag interpreter inode Vivek Parikh
2026-07-19 11:47 ` Jori Koolstra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox