[PATCH 0/3] binfmt_misc: bound the interpreters an entry can pre-open
Christian Brauner <[email protected]> Mon, 03 Aug 2026 14:14:59 +0200
| Newsgroups | org.kernel.vger.linux-fsdevel,org.kernel.vger.bpf,org.kvack.linux-mm |
|---|---|
| Message-ID | <20260803-work-binfmt_misc-interplimit-v1-0-4a2435500bd9@kernel.org> |
An 'F' entry opens its interpreter at registration and every exec runs a clone of it. A 'B' entry does the same for each interpreter it binds. That file stays open for as long as the entry lives. So it pins the file, its inode, the mount it came from and that mount's superblock. An entry binds at most 100 interpreters, but nothing caps the entries. binfmt_misc is container mountable so all of this is reachable by unprivileged users. While the pins go away when the instance is unmounted, it's still weird for an unprivileged namespace to be allowed to do this. And the fix is simple. Charge each binding to the user namespace and uid that makes it against a new UCOUNT_BINFMT_MISC_INTERPRETERS and refuse with -ENOSPC when the limit is hit. A per-instance cap won't do. Instances are keyed on the user namespace, so whatever constant I pick gets multiplied by however many namespaces the caller cares to create. inc_ucount() charges the namespace and every one of its ancestors, and a namespace can only ever raise its own limit, so nesting buys nothing. The knob is /proc/sys/user/max_binfmt_misc_interpreters, per namespace like every other ucount. I left it at the max_threads/2 default that fork_init() hands a new ucount type. Nothing anyone runs today comes anywhere near that. Selftests for all of it, including that a nested namespace can't buy itself budget. Signed-off-by: Christian Brauner (Amutable) <[email protected]> --- Christian Brauner (3): binfmt_misc: correctly account pre-opened interpreters selftests/exec: test the pre-opened interpreter limit binfmt_misc: document the pre-opened interpreter limit Documentation/admin-guide/binfmt-misc.rst | 12 +- fs/binfmt_misc.c | 16 +- include/linux/binfmt_misc.h | 3 + include/linux/user_namespace.h | 3 + kernel/ucount.c | 6 + tools/testing/selftests/exec/.gitignore | 1 + tools/testing/selftests/exec/Makefile | 6 + tools/testing/selftests/exec/binfmt_misc_bpf.c | 70 +++++++ .../selftests/exec/binfmt_misc_interplimit.c | 232 +++++++++++++++++++++ 9 files changed, 343 insertions(+), 6 deletions(-) --- base-commit: 7693ae84747b6e72a1a3d14b836f7bec11606e08 change-id: 20260803-work-binfmt_misc-interplimit-392eca4de742