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

* Re: [REPORT] binfmt_misc: leaked write-access denial on F-flag interpreter inode
  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
  0 siblings, 0 replies; 2+ messages in thread
From: Jori Koolstra @ 2026-07-19 11:47 UTC (permalink / raw)
  To: Vivek Parikh; +Cc: viro, brauner, kees, linux-fsdevel

On Sat, Jul 18, 2026 at 10:13:46AM +0530, Vivek Parikh wrote:
> 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>

Thanks!

This is already addressed by a recent patchset of Brauner.[1]

Best,
Jori.

[1]: https://lore.kernel.org/linux-fsdevel/20260710-work-binfmt_misc-locking-v3-1-a162f7cb58d6@kernel.org/

^ 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