summaryrefslogtreecommitdiff
path: root/fs
AgeCommit message (Collapse)Author
2026-08-03binfmt_misc: add the 'L' loader substitution flagChristian Brauner
Add the first activation of the PT_INTERP substitution machinery. A static entry registered with the new 'L' flag no longer runs the registered interpreter with the binary as payload. It stashes the interpreter as bprm->loader and declines the match with -ENOEXEC. The format search continues in the same round. binfmt_elf claims the binary as a fully native exec and substitutes the stashed file for the binary's PT_INTERP. 'L' rejects every classic-dispatch flag at registration. 'T', 'P' and 'O' have nothing to act on (no argv splice, no execfd) and 'C' is subsumed (credentials derive from the binary natively). 'F' composes and is valuable: with it the substitute is pre-opened at registration time and immune to mount namespace changes. Without it the substitute is opened at exec time in the exec'ing task's context, so 'L' joins 'C' in the requirement that the interpreter be named by an absolute path. As with 'C', only trusted interpreters should be registered. The substituted loader runs with credentials derived from the binary. Like the other flag characters 'L' cannot be used as the field delimiter. The flag scan would run off the registration buffer. The interpreter open is shared with the classic path via the entry_open_interpreter() helper. An open error fails the exec. Map -ENOEXEC to -EACCES to avoid letting the binary run with its own PT_INTERP. Link: https://patch.msgid.link/20260721-work-bpf-binfmt_misc-ptinterp-v2-18-e57866e4ae0f@kernel.org Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_elf_fdpic: consume a stashed PT_INTERP substituteChristian Brauner
Do what binfmt_elf does. When a binfmt_misc loader entry stashed bprm->loader use it in place of the path named in PT_INTERP, and drop the override when the binary names no interpreter at all. Without this 'L' is unusable on nommu, where fdpic is the only ELF loader. On ARM with an MMU both loaders are registered but split the ELF space between them along elf_check_fdpic(), so an fdpic binary is never picked up by binfmt_elf either. Declining is what fdpic did so far, but it declined late. The pending override was only caught in begin_new_exec(), by which point the segment scan had opened the interpreter the binary itself names and overwritten bprm->buf with its header, leaving the next format in the round to inspect a buffer that no longer describes the file it is offered. The scan consumes the override now, so of the in-tree formats only binfmt_flat still relies on the refusal, and it reads bprm->buf without writing it. Transparent dispatch needs nothing on top of the AT_FLAGS translation both loaders already share. The binary travels in AT_EXECFD, which create_elf_fdpic_tables() emits, and the exe and comm labelling is done in exec.c for every format. Link: https://patch.msgid.link/20260721-work-bpf-binfmt_misc-ptinterp-v2-17-e57866e4ae0f@kernel.org Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_elf: consume a stashed PT_INTERP substituteChristian Brauner
When a binfmt_misc loader entry stashed bprm->loader use it instead of opening the path named in PT_INTERP. The substitution deliberately changes as little as possible. Ownership transfers into the local interpreter reference which the existing success and error paths already release. A binary without PT_INTERP has nothing to substitute for. Drop the override at the end of the segment scan and load the binary natively. Nothing sets bprm->loader yet. Link: https://patch.msgid.link/20260721-work-bpf-binfmt_misc-ptinterp-v2-16-e57866e4ae0f@kernel.org Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03exec: carry a PT_INTERP substitute in struct linux_binprmChristian Brauner
binfmt_misc currently supports an execution model where the registered interpreter becomes the executed program and the matched binary is handed to it as payload. The upcoming binfmt_misc loader mode inverts this. The matched binary remains the executed program and the registered interpreter is substituted into the role the binary's PT_INTERP would have played. Add the channel for that hand-over. bprm->loader carries an open_exec-style struct file reference from the binfmt_misc match to the binary format that consumes it. Unlike bprm->interpreter it does not request a restart of the format search. The stashing handler declines the exec with -ENOEXEC and the search continues to the real format in the same round. Both ELF loaders consume it, so give them the two helpers to do it with rather than a copy each. bprm_open_interpreter() hands out the substitute in place of what PT_INTERP names and bprm_drop_loader() releases one that turned out not to apply. Establish the complete lifecycle up front so a stashed loader can neither leak nor be silently ignored. - Chain restart: if another format wins the round by staging bprm->interpreter (binfmt_script) the stashed loader belonged to the file being replaced. Drop it at the top of the swap block in exec_binprm(). - Unclaimed or error: free_bprm() releases a still-stashed loader next to the other bprm file references. - Silent non-substitution: a final format that reaches begin_new_exec() with a pending loader would run the binary while ignoring the override. Refuse with -ENOEXEC before the point of no return. Formats that do not know about the override (binfmt_flat, out-of-tree) need no changes. Link: https://patch.msgid.link/20260721-work-bpf-binfmt_misc-ptinterp-v2-15-e57866e4ae0f@kernel.org Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_misc: let a bpf handler run the interpreter transparentlyChristian Brauner
Expose transparent mode 'T' to the bpf handler via a new BPF_BINPRM_TRANSPARENT flag. A bpf handler can decide per binary whether the dispatch is transparent. This way users may choose a native-looking loader for one binary and a visible wrapper invocation for the next. Link: https://patch.msgid.link/20260721-work-bpf-binfmt_misc-ptinterp-v2-12-e57866e4ae0f@kernel.org Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_misc: add a static transparent flag 'T'Christian Brauner
Let a registration opt into transparent dispatch. The 'T' flag lets a matched binary keep its argument vector and is sent to the interpreter through AT_EXECFD. The process's identity is the binary's. 'T' implies 'O' exactly like 'C' does. 'P' is rejected in combination with it. Transparency preserves the whole argument vector so there is nothing left for 'P' to say. 'C' remains an independent choice and 'F' keeps working. A pre-opened interpreter is orthogonal to how the binary is handed over. Like the other flag characters 'T' cannot be used as the field delimiter. The flag scan would run off the registration buffer. Link: https://patch.msgid.link/20260721-work-bpf-binfmt_misc-ptinterp-v2-11-e57866e4ae0f@kernel.org Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_misc: add transparent interpreter dispatchChristian Brauner
A binfmt_misc interpreter is visible to the binary it runs. argv[0] becomes the interpreter path and the binary's path is appended as an argument and /proc/pid/cmdline shows both. For wine or qemu-user that is the point. For a per-binary loader the interpreter is an implementation detail of running the binary that has no business in the argument vector. And a binary handed to execveat() as an O_CLOEXEC fd without a usable path cannot be run through binfmt_misc at all. The interpreter would have no path to open the binary by. Add the dispatch machinery for a transparent mode. The binary is handed to the interpreter through AT_EXECFD. The argument vector is left exactly as the caller set it. argv[0] and /proc/pid/cmdline look like a direct execution of the binary. bprm->interp still names the interpreter: it drives the next format lookup and the sched_prepare_exec tracepoint, not what the process sees. The interpreter loads the binary from AT_EXECFD for this. A relocatable loader can and glibc's ld.so is gaining AT_EXECFD support [1]. A staged interpreter argument is rejected: no argv slot is built for it to land in. The transparent branch raises BINPRM_FLAGS_TRANSPARENT_INTERP. A dispatch through it labels mm->exe_file with the binary and raises AT_FLAGS_TRANSPARENT_INTERP next to AT_EXECFD. The aux vector bit is the loader's hint to retarget saved_auxv and the statistics markers to the binary, which is only correct while the exe link names the binary too. The inaccessible-path bail moves after handler selection and into the path-building branch. A transparent interpreter takes the binary from AT_EXECFD instead of a path, so the restriction does not apply to it and the O_CLOEXEC execveat() case above can work. Nothing can take the transparent branch yet. Link: https://inbox.sourceware.org/libc-alpha/20260717-work-glibc-binfmt_misc-v3-0-45129bfb13fe@kernel.org [1] Link: https://patch.msgid.link/20260721-work-bpf-binfmt_misc-ptinterp-v2-10-e57866e4ae0f@kernel.org Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03exec: label mm->exe_file with the binary for a transparent dispatchChristian Brauner
When binfmt_misc dispatches a binary to an interpreter, the interpreter becomes bprm->file and begin_new_exec() labels mm->exe_file with it. For wine or qemu-user that is the point. For the transparent mode it defeats the point. The interpreter is an implementation detail and the process's identity is the binary. Relocatable programs that locate themselves via /proc/self/exe find the dynamic linker instead [1]. Userspace cannot get this right on its own. PR_SET_MM_MAP's exe_fd is gated on checkpoint_restore_ns_capable() in the caller's own user namespace - that is how CRIU restores an exe link - so the ability to retarget mm->exe_file is not what this adds. What userspace cannot do is have the link be right from the first instruction. Credentials are unaffected either way: they still derive from the interpreter unless 'C' says otherwise. bprm->executable is the file execve() access-checked and kept open for AT_EXECFD. It is already the file would_dump() bases the dumpability decision on and the file bprm->execfd_creds derives credentials from. Label mm->exe_file with it when the dispatch is transparent and the identity is correct from the start. The label names precisely the file the caller passed to execve(). Write-denial moves along with the label. Rather than tracking per mode who still owes a release, the denial do_open_execat() took stays on bprm->executable until the file is handed over. begin_new_exec() drops it right before installing the descriptor - set_mm_exe_file() has taken its own denial on the identity file by then - and free_bprm() releases an unconsumed executable with do_close_execat() like the other exec files. For a transparent dispatch the result is exact parity with a direct execution: a concurrently written binary fails execve() with -ETXTBSY at open and a running one cannot be opened for writing. The interpreter consequently is not exe-pinned and matches the role it has in a native PT_INTERP exec. A classic execfd dispatch now keeps the binary write-denied until the exec completes rather than only until the interpreter swap; the difference is confined to the exec itself. Nothing sets BINPRM_FLAGS_TRANSPARENT_INTERP yet; the transparent dispatch machinery in binfmt_misc follows and raises it from birth, so the label and the aux vector bit that announces it appear together. Link: https://inbox.sourceware.org/libc-alpha/87ik6fymha.fsf@oldenburg.str.redhat.com [1] Link: https://patch.msgid.link/20260721-work-bpf-binfmt_misc-ptinterp-v2-9-e57866e4ae0f@kernel.org Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03exec: add AT_FLAGS_TRANSPARENT_INTERPChristian Brauner
A transparent binfmt_misc dispatch hands the binary to the interpreter through AT_EXECFD and leaves the argument vector exactly as the caller built it. The loader on the receiving end has to know which contract it got. On the classic 'O'/'C' entries the binary's path is spliced into the argument vector and the loader consumes arguments. In transparent mode nothing was spliced and argv belongs entirely to the program. This cannot be inferred from AT_EXECFD alone. Raise a new AT_FLAGS bit following the AT_FLAGS_PRESERVE_ARGV0 precedent added for qemu-user in commit 2347961b11d4 ("binfmt_misc: pass binfmt_misc flags to the interpreter"). The bit also announces that mm->exe_file names the binary rather than the interpreter (added in the next commit). A loader that sees the bit may finish the identity polish by fixing up AT_PHDR/AT_ENTRY/AT_BASE in saved_auxv and fix the code/data markers via one uncapped PR_SET_MM_MAP once it has mapped the binary. I've got glibc patches for this as well but it's useful for any loader. BINPRM_FLAGS_TRANSPARENT_INTERP carries the mode from binfmt_misc to the ELF loaders. Both had their own copy of the AT_FLAGS translation, so give them one bprm_at_flags() to share instead of a second copy that can drift. Nothing sets the bprm flag yet. Link: https://patch.msgid.link/20260721-work-bpf-binfmt_misc-ptinterp-v2-8-e57866e4ae0f@kernel.org Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03exec: release the replaced file with do_close_execat()Christian Brauner
When the format search stages an interpreter exec_binprm() swaps it in and releases the file it replaces. Dropping the write denial the open took is done manually ahead of both release paths. The one path that keeps the file silently relies on it not being called. Let's just use do_close_execat() on the two paths that release the file and drop the denial explicitly on the one that does not. No functional change. Link: https://patch.msgid.link/20260721-work-bpf-binfmt_misc-ptinterp-v2-6-e57866e4ae0f@kernel.org Reviewed-by: Farid Zakaria <farid.m.zakaria@gmail.com> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_misc: split out entry_open_interpreter() and build_interp_argv()Christian Brauner
Opening the interpreter is a property of the matched entry: an 'F' entry hands out a clone of the file it pre-opened at registration time, any other entry opens the selected path. Give that its own helper instead of an if/else in the middle of load_misc_binary(), and let it fail early rather than carrying an ERR_PTR through the successful branch. Building the interpreter's argument vector is the bulk of what remains and the one part of load_misc_binary() that is specific to the classic dispatch. Move it into its own helper too, so the dispatch reads as what it is: pick a handler, pick an interpreter, build the invocation, open it. No functional change. Link: https://patch.msgid.link/20260721-work-bpf-binfmt_misc-ptinterp-v2-5-e57866e4ae0f@kernel.org Reviewed-by: Farid Zakaria <farid.m.zakaria@gmail.com> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_misc: normalize the per-exec invocation flagsChristian Brauner
A static entry fixes its invocation flags at registration. A 'B' entry's load program picks them per exec. Since load_misc_binary() branches on which kind of entry matched and then applies the two flag sets side by side every flag is handled twice and each new one has to be added to both arms. Translate the 'B' flags into the entry flags they mirror and let the dispatch act on a single set of flags. The boolean the two arms communicated 'P' can be removed. No functional change. Link: https://patch.msgid.link/20260721-work-bpf-binfmt_misc-ptinterp-v2-4-e57866e4ae0f@kernel.org Reviewed-by: Farid Zakaria <farid.m.zakaria@gmail.com> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_misc: table-drive the register string flagsChristian Brauner
Every flag character of the register string is spelled out three times: in the parser, in the entry's /proc output and in the delimiter blacklist that keeps a flag character from sending the flag scan off the end of the buffer. The three lists have to agree, and each new flag has to be added to all of them. Describe a flag once - character, entry flag, implied flags and a description for the registration debug output - and drive all three from the table. While at it, express the "a 'B' entry carries no flags" check as what it is, an empty flags field, rather than as a fourth list of every flag character. Equivalent: the check runs right after check_special_flags(), which advances past exactly the flag characters it consumed and sets exactly their flags. No functional change. Link: https://patch.msgid.link/20260721-work-bpf-binfmt_misc-ptinterp-v2-3-e57866e4ae0f@kernel.org Reviewed-by: Farid Zakaria <farid.m.zakaria@gmail.com> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_misc: require an absolute interpreter path with 'C'Christian Brauner
A 'C' entry computes the credentials from the matched binary instead of from the interpreter. So a set*id binary hands its credentials to whatever the entry names as its interpreter. Without 'F' that interpreter is not opened until the exec happens and open_exec() resolves the path relative to the current working directory. The working directory at that point belongs to whoever runs the binary not to whoever registered the entry. So :x:M::\x7fELF::interp:C lets every user who execs a matching set*id binary from a directory they control run their own interp with that binary's credentials. A relative interpreter has no sensible use here to begin with. The registering task cannot know what the working directory will be. Make the register string reject the combination at registration time. This does refuse register strings that used to be accepted. The 'F' flag covers the case where the interpreter really is meant to be resolved in the registrant's context, and it resolves it once, at registration. Link: https://patch.msgid.link/20260721-work-bpf-binfmt_misc-ptinterp-v2-1-e57866e4ae0f@kernel.org Reviewed-by: Farid Zakaria <farid.m.zakaria@gmail.com> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_misc: let a bpf handler choose the invocation flags per execChristian Brauner
The 'P', 'C' and 'O' flags of a binfmt_misc entry - preserve argv[0], compute credentials from the binary, and pass the binary as an open file descriptor - are fixed at registration and apply to every binary the entry matches. A bpf handler matches, selects the interpreter and reads the binary per exec, so the flags should be its per-exec decision too: one handler may match both setuid and non-setuid binaries, argv[0]-sensitive ones and not. Honor the flags the load program stages in bprm->bpf_flags through the bpf_binprm_set_flags() kfunc: BPF_BINPRM_PRESERVE_ARGV0, BPF_BINPRM_CREDENTIALS and BPF_BINPRM_EXECFD map to 'P', 'C' and 'O' and keep the semantics of their static counterparts, credentials implying the open file descriptor included. Flags staged by a load program that then fails are dropped on the way out so they cannot leak into a later handler's exec, and the argv[0] decision acts on the entry's own choice instead of testing the accumulated bprm->interp_flags bit, which an earlier chain level may have left set and binfmt_misc never clears. Since a 'B' entry's flags come from the program, it carries none in the register string: 'P', 'C' and 'O' are rejected there alongside 'F', which was already meaningless for it. load_misc_binary() takes the flags from the entry for a static handler and from bprm->bpf_flags for a bpf one. Link: https://patch.msgid.link/20260714-work-bpf-binfmt_misc-v2-7-57b7529c002c@kernel.org Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_misc: let bpf handlers pass an argument to the interpreterChristian Brauner
A bpf binfmt_misc handler selects an interpreter but, unlike binfmt_script, load_misc_binary() builds the argument vector as just [interpreter, binary, ...] with no slot for an argument to the interpreter. A handler that wants to reproduce a #! line therefore cannot express its single optional argument, e.g. a handler that resolves $ORIGIN in a script's #! path loses the argument that followed the interpreter. Have load_misc_binary() consume the argument staged through the bpf_binprm_set_interp_arg() kfunc and insert it between the interpreter and the binary - the same position and single-argument semantics binfmt_script gives the argument of a #! line. The argument is cleared once spliced into the argument vector, and a load program that fails after staging one has it dropped on the way out: whether the exec fails or -ENOEXEC hands the binary back to the remaining formats, a stale argument cannot leak into a nested interpreter's argv. This also lets static-style handlers pass a fixed interpreter argument, which plain binfmt_misc has never been able to express. Link: https://patch.msgid.link/20260714-work-bpf-binfmt_misc-v2-6-57b7529c002c@kernel.org Reviewed-by: Farid Zakaria <farid.m.zakaria@gmail.com> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03bpf: allow fs kfuncs for binfmt_misc_ops programsChristian Brauner
The fs kfuncs are currently exclusive to LSM programs. A binfmt_misc handler needs a subset of them to do anything interesting: computing an interpreter relative to the binary's location wants bpf_path_d_path() on bprm->file->f_path from the load program, and matching on per-binary metadata wants bpf_get_file_xattr() and friends right from the match program. Register the fs kfunc set for struct_ops programs as well and extend the filter to admit binfmt_misc_ops programs. The xattr setters stay exclusive to LSM programs: a binary type handler decides how to run a binary, it has no business modifying filesystem state. This only takes effect in builds that have the fs kfunc set at all, i.e. CONFIG_BPF_LSM. Without it a binfmt_misc handler is limited to bprm fields and the file-backed dynptr, which are provided by the common kfunc set. Link: https://lore.kernel.org/20260704211409.1978485-1-farid.m.zakaria@gmail.com Link: https://patch.msgid.link/20260714-work-bpf-binfmt_misc-v2-5-57b7529c002c@kernel.org Reviewed-by: Farid Zakaria <farid.m.zakaria@gmail.com> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_misc: wire up bpf-backed 'B' entriesChristian Brauner
Activate a registered binfmt_misc_ops handler through the existing text interface with the new 'B' entry type: echo ':name:B::::<handler-name>:' > <binfmt_misc>/register The offset, magic, and mask fields must be empty since the program does the matching; the interpreter field carries the handler name since the program supplies the interpreter. Reusing the register file keeps the existing permission model intact: activating a handler requires the same write access to a binfmt_misc instance as any other registration, and the per user namespace instance semantics apply unchanged. A 'B' entry in a container's own instance shadows the host's handlers just like any other entry, and the privilege needed to shadow e.g. all ELF binaries is the same as for a static 'M' entry matching \x7fELF today; the only novelty is that matching becomes programmable. The entry takes its own reference on the ops for its whole lifetime. It is dropped from the SRCU callback that frees the entry rather than synchronously on the final put: a walker may be asleep inside the handler's match program while the entry's last reference goes away, so the ops must stay callable until every walker has left the read section - the same deferral the entry's own memory already gets. The registration failure path, where the users refcount is not live yet, drops it explicitly. The match program runs from the lookup walk like magic and extension matching and under the same rules: strict registration order, first match wins. The walk became an SRCU read-side section in the previous patch, so the program can sleep: it decides on the actual file content - program headers beyond the prefetched bprm->buf, say - not just on whatever happens to be resident in the page cache. A match commits the exec to the handler. The sleepable load program then selects the interpreter from load_misc_binary() by calling bpf_binprm_set_interp() and returning zero; a failure fails the exec instead of falling through to later entries. The walk is never left and re-entered, so 'B' entries need no special semantics against concurrent registration and removal whatsoever. -ENOEXEC keeps its usual meaning and moves on to the remaining binary formats - a handler whose load program discovers that it cannot serve the binary after all hands it back to them - and so does returning zero without having selected an interpreter; other program-supplied errors are clamped to the errno range. The 'F' flag is rejected for 'B' entries: it exists to pre-open a fixed interpreter at registration time in the registrar's context, and a 'B' entry has no fixed interpreter to pre-open. 'C' is accepted and behaves exactly as it does for a static entry. It honors the suid bits of the matched binary while executing the interpreter, which makes 'B' handlers usable for the setuid case, e.g. a per-binary loader. This does not let the program's registrant widen access: bprm_fill_uid() gates the credential transition on vfsuid_has_mapping() in the caller's user namespace, so the interpreter can only ever run as a uid that is mapped there, identical to a static 'C' entry. The computed path is opened with open_exec() under the caller's credentials with the usual LSM and noexec checks, and the programs run before the transition with the caller's credentials, never elevated. Link: https://lore.kernel.org/20260704211409.1978485-1-farid.m.zakaria@gmail.com Link: https://patch.msgid.link/20260714-work-bpf-binfmt_misc-v2-4-57b7529c002c@kernel.org Reviewed-by: Farid Zakaria <farid.m.zakaria@gmail.com> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_misc: let the entry lookup walk sleepChristian Brauner
The upcoming bpf-backed binary type handlers run a match program from the entry lookup walk in load_misc_binary(). Deciding whether a handler applies means reading the binary - parsing ELF program headers sitting at arbitrary file offsets, say - and reliable file reads at exec time fault in the file's pages, so the walk must tolerate an entry's evaluation sleeping. Switch the walk from RCU to SRCU in its fast flavor: srcu-fast read sections may block while the read side stays practically as cheap as the RCU read lock it replaces, so the common static-entry lookup does not pay for the new capability. Entry freeing moves from kfree_rcu() to call_srcu(). Removal still unlinks the entry immediately and never blocks: a walker sleeping inside an entry's evaluation just keeps the entry alive until it leaves the read section. The module exit path flushes pending callbacks with srcu_barrier(). Take the reference on a matched entry at the match point inside the walk instead of retrying the whole search when the refcount raise fails. A restarted search was harmless when an entry's evaluation was a memcmp() on bprm->buf, but re-running match programs that may sleep on entries that were already consulted is not. An entry whose refcount hit zero is unlinked and dying, so treating it as absent and walking on is exactly what the bounded retry loop converged to, without ever evaluating an entry twice. Link: https://patch.msgid.link/20260714-work-bpf-binfmt_misc-v2-3-57b7529c002c@kernel.org Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_misc: add binfmt_misc_ops bpf struct_opsChristian Brauner
Add the bpf plumbing for binary type handlers whose matching and interpreter selection are implemented by bpf programs instead of a fixed magic/extension and a fixed interpreter string recorded at registration time. This serves relocatable binary formats where the interpreter must be computed per binary, e.g. relative to the location of the binary itself, as discussed for hermetic Nix-style executables. A handler is an instance of the new binfmt_misc_ops struct_ops with a name that binfmt_misc entries reference it by and two ops: bool (*match)(struct linux_binprm *bprm); int (*load)(struct linux_binprm *bprm); struct_ops is the sanctioned mechanism for this kind of user-supplied policy callback: program types, attach types, and the uapi helper list are frozen, and every recently added subsystem hook (bpf qdisc, SMC handshake control, io_uring loop ops, sched_ext) is a struct_ops user. The ops receive the bprm as a trusted BTF pointer, so a program can match on the header in bprm->buf, read arbitrary file content via bpf_dynptr_from_file() to parse e.g. ELF program headers, and inspect the binary's location. No dedicated program type, ctx blob, or uapi helper is needed. The two ops split along what they decide, not what they may do: the match program decides whether the handler applies to a binary, the load program decides how a matched binary is run. Both are required to be sleepable. Matching cannot be limited to the prefetched 256 bytes in bprm->buf: deciding whether a handler applies takes e.g. parsing the ELF program headers to find an interpreter segment, which sits at an arbitrary file offset, and non-sleepable file reads are limited to whatever happens to be resident in the page cache. A match program that cannot read the file reliably would have to match broadly and leave the rejection to its load program, which breaks first-match-wins entry semantics the moment more than one handler is registered. Reliable file reads at exec time fault in the file's pages, so both ops must be able to sleep. This also constrains the caller: binfmt_misc must invoke both from sleepable context, which a later patch takes care of. Both ops are required; a handler that wants to decide everything from the load program supplies a match program that just returns true. The load program communicates its decisions through three new kfuncs: int bpf_binprm_set_interp(struct linux_binprm *bprm, const char *path, size_t path__sz); selects the interpreter and enforces an absolute path shorter than PATH_MAX. int bpf_binprm_set_interp_arg(struct linux_binprm *bprm, const char *arg, size_t arg__sz); passes a single optional argument to the interpreter, mirroring the optional argument of a #! interpreter line - something a static entry cannot express at all. int bpf_binprm_set_flags(struct linux_binprm *bprm, enum bpf_binprm_flags flags); chooses the invocation flags for this exec, with BPF_BINPRM_PRESERVE_ARGV0, BPF_BINPRM_CREDENTIALS and BPF_BINPRM_EXECFD mapping to 'P', 'C' and 'O'. Unknown bits are rejected so a program built against a newer kernel fails loudly on an older one rather than silently losing a flag. Repeated calls replace the staged flags and a zero argument clears them again - the set-or-clear semantics of bpf_bprm_opts_set() on the same struct. A flags word carries this better than a kfunc per flag: it is one call, it is set atomically, and new behaviour is a new bit rather than new surface - the same shape the register string's flags field already has. All three stage their result in the bprm; consuming it from load_misc_binary() is wired up by the following patches. The bprm is exclusively owned by the task doing the exec, so no shared or per-CPU state is involved and nothing here can race. The kfuncs are registered for struct_ops programs with a filter that limits them to the load program of a binfmt_misc_ops instance, keyed off the struct_ops member offset the program attaches to: match decides whether a handler applies, load decides how the binary is run, and the verifier enforces that split at program load time. Registering an ops instance (updating the struct_ops map or attaching its link) publishes the handler under its name in a registry keyed by the registering task's user namespace. Lookups do not walk that hierarchy: a handler is only visible in the user namespace it was registered in, so an entry can only reference a handler registered in the same user namespace as its binfmt_misc instance. Consumers take a reference on the ops via bpf_struct_ops_get() which pins the underlying map and programs, so an activated handler keeps working even if the map is deleted or the registering container goes away; deregistration only prevents new activations, exactly like unregistering a tcp congestion ops with live users. Link: https://lore.kernel.org/20260704211409.1978485-1-farid.m.zakaria@gmail.com Link: https://patch.msgid.link/20260714-work-bpf-binfmt_misc-v2-2-57b7529c002c@kernel.org Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03exec: stash bpf-selected interpreter state in struct linux_binprmChristian Brauner
The upcoming bpf-backed binfmt_misc handlers decide how a binary is run programmatically at exec time: the interpreter itself, an optional single argument to pass to it, and the invocation flags that a static binfmt_misc entry fixes at registration time. The selection runs before load_misc_binary() has copied the binary path from bprm->interp into the argument vector, so the selecting program cannot go through bprm_change_interp() directly without clobbering argv[1]. Stage the selected state in the bprm instead, grouped in struct binfmt_misc_bpf and embedded anonymously in struct linux_binprm so the bprm->bpf_* accesses stay direct. The bprm is exclusively owned by the task doing the exec so no synchronization is needed. The consumers free and clear the fields once the exec attempt that set them is finished; free_bprm() covers all error paths. Link: https://patch.msgid.link/20260714-work-bpf-binfmt_misc-v2-1-57b7529c002c@kernel.org Reviewed-by: Farid Zakaria <farid.m.zakaria@gmail.com> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_misc: allow removing entries via unlink(2)Christian Brauner
Removing a binary type handler requires echoing -1 into its entry file which works but is an odd interface to discover for something that already looks like a plain file in a filesystem. The comment on remove_binfmt_handler() has been suggesting a proper ->unlink() method for years, so add one: unlinking an entry file unhashes the entry from the handler list and removes the file, exactly like writing -1 to it does. The status and register control files refuse removal with EPERM the same way binderfs protects binder-control. Writing -1 keeps working. Permission-wise nothing new is exposed: unlink(2) requires write access to the root directory which is owned by the (user namespace) root with mode 0755, matching the privilege needed to write to the 0644 entry files. The VFS calls ->unlink() with the root inode lock held so the existing writer serialization scheme applies unchanged, and eviction of the unlinked inode drops the entry reference exactly as for the write based removal. Document the new way in admin-guide/binfmt-misc.rst. Link: https://patch.msgid.link/20260710-work-binfmt_misc-locking-v3-24-a162f7cb58d6@kernel.org Reviewed-by: Jori Koolstra <jkoolstra@xs4all.nl> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_misc: include what is usedChristian Brauner
The include list still reflects code that left this file years ago: nothing here uses sched/mm.h, pagemap.h, namei.h, syscalls.h or anything from fs/internal.h anymore, mount.h and the bm_fs_type forward declaration lost their last user when the pinned bm_mnt machinery was removed. Drop all of that and instead spell out the headers the file actually relies on but so far pulled in transitively: bitops, bits, bug, cleanup, cred, kstrtox, printk, refcount, string and user_namespace. With that nothing needs the kernel.h grab bag anymore, so it goes too, and the list is sorted alphabetically. Link: https://patch.msgid.link/20260710-work-binfmt_misc-locking-v3-23-a162f7cb58d6@kernel.org Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_misc: assorted small cleanupsChristian Brauner
Use umode_t for the mode argument of bm_get_inode(), constify the fixed status strings in bm_status_read(), give the super_operations the bm_ prefix everything else in this file uses, replace the stale scanarg() comment which still described parameters and an err variable it lost decades ago and fix the delimiter typo plus a missing space nearby. No functional change. Link: https://patch.msgid.link/20260710-work-binfmt_misc-locking-v3-22-a162f7cb58d6@kernel.org Reviewed-by: Jori Koolstra <jkoolstra@xs4all.nl> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_misc: use __free(kfree) in bm_register_write()Christian Brauner
bm_register_write() has to free the entry it got from create_entry() on every failure until add_entry() has linked it into the filesystem and made the inode its owner. Arm the entry with __free(kfree) so the error branches can simply return and disarm it via retain_and_null_ptr() once ownership has been handed to the inode. The interpreter file keeps its manual error cleanup as freeing the entry would not close it. No functional change. Link: https://patch.msgid.link/20260710-work-binfmt_misc-locking-v3-21-a162f7cb58d6@kernel.org Reviewed-by: Jori Koolstra <jkoolstra@xs4all.nl> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_misc: split the field parsing out of create_entry()Christian Brauner
create_entry() is a two hundred line parser with the M and E field handling inlined as the two arms of its largest branch. Move them into parse_magic_fields() and parse_extension_fields() which return the new parse position or NULL so create_entry() itself reads like the register string grammar again. The offset parsing loses a provably dead check on the way: after *s = '\0' and p = s the subsequent if (*p++) always reads the just written NUL byte and can never fail, it only obscured that the code simply advances past the delimiter. With the field parsing gone every remaining failure unwinds the same way, so hand the entry to __free(kfree), return errors directly and pass ownership out via no_free_ptr() on success instead of routing every exit through goto tails. Link: https://patch.msgid.link/20260710-work-binfmt_misc-locking-v3-20-a162f7cb58d6@kernel.org Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_misc: use a flexible array member for the register stringChristian Brauner
create_entry() allocates the entry and the register string it parses into in one chunk and finds the string part again through manual pointer arithmetic behind a cast. Make the layout explicit with a flexible array member and struct_size(), and give the magic pad of trailing delimiters a name while at it. No functional change. Link: https://patch.msgid.link/20260710-work-binfmt_misc-locking-v3-19-a162f7cb58d6@kernel.org Reviewed-by: Jori Koolstra <jkoolstra@xs4all.nl> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_misc: simplify check_special_flags()Christian Brauner
Replace the cont flag and the pointer increment repeated in every case with a for loop that returns from the default case, and shrink the multi-line 'C implies O' remark to one line. No functional change. Link: https://patch.msgid.link/20260710-work-binfmt_misc-locking-v3-18-a162f7cb58d6@kernel.org Reviewed-by: Jori Koolstra <jkoolstra@xs4all.nl> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_misc: factor out the entry removalChristian Brauner
Both write handlers open-code the same removal dance - grab the root inode lock, unlink, unlock - each carrying a verbatim copy of the same eleven-line locking comment, and bm_entry_write() reuses its inode variable for the root inode halfway through to pull it off. Move the dance into bm_remove_entry() and bm_remove_all_entries() and the locking rules into the kernel-doc of remove_binfmt_handler() which both helpers wrap. No functional change. Link: https://patch.msgid.link/20260710-work-binfmt_misc-locking-v3-17-a162f7cb58d6@kernel.org Reviewed-by: Jori Koolstra <jkoolstra@xs4all.nl> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_misc: give the parse_command() results namesChristian Brauner
parse_command() maps "0" to 1, "1" to 2 and "-1" to 3 and the write handlers switch on those bare numbers, leaving every reader to redo the mapping in their head. Name the commands and drop the per-case comments that only existed to translate the numbers back. No functional change. Link: https://patch.msgid.link/20260710-work-binfmt_misc-locking-v3-16-a162f7cb58d6@kernel.org Reviewed-by: Jori Koolstra <jkoolstra@xs4all.nl> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_misc: return errors directly in load_misc_binary()Christian Brauner
load_misc_binary() seeds retval with the error for checks that happen further down, reassigns it along the way and funnels every exit through a ret label whose only job is dropping the entry reference, so figuring out what an early return actually returns means replaying the assignment history. Give put_binfmt_handler() a cleanup class and take the reference with __free() so every failure can return its error right where the condition is checked. The comment at the label restated what the put_binfmt_handler() kernel-doc already explains, it goes with the label. Drop the dead NULL initialization of interp_file which is assigned on all paths before use. No functional change. Link: https://patch.msgid.link/20260710-work-binfmt_misc-locking-v3-15-a162f7cb58d6@kernel.org Reviewed-by: Jori Koolstra <jkoolstra@xs4all.nl> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_misc: rename load_binfmt_misc() to current_binfmt_misc()Christian Brauner
load_binfmt_misc() is one word swap away from load_misc_binary(), the binfmt loader it serves. It doesn't load anything, it looks up the binfmt_misc instance of the caller's user namespace, so name it after what it returns in the style of current_user_ns() and friends. Tighten the parent walk into a for loop and fix the stale wording and typos in the kernel-doc while at it. Link: https://patch.msgid.link/20260710-work-binfmt_misc-locking-v3-14-a162f7cb58d6@kernel.org Reviewed-by: Jori Koolstra <jkoolstra@xs4all.nl> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_misc: factor out the entry matchingChristian Brauner
search_binfmt_handler() open-codes both match types in one loop body with the maskless magic comparison spelled as a manual xor loop that is just memcmp() in disguise. Move the extension and magic checks into helpers so the walk reads as policy - skip disabled entries, match by entry type - and the maskless case actually uses memcmp(). No functional change. Link: https://patch.msgid.link/20260710-work-binfmt_misc-locking-v3-13-a162f7cb58d6@kernel.org Reviewed-by: Jori Koolstra <jkoolstra@xs4all.nl> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_misc: convert the entry file to seq_fileChristian Brauner
Reading an entry file allocates a whole page and formats the status into it with a chain of manually advanced sprintf() calls, silently relying on MAX_REGISTER_LENGTH plus the hex-expanded magic and mask always staying below PAGE_SIZE. Convert the read side to seq_file which sizes its buffer as needed and gets rid of the open-coded pointer arithmetic including the last bin2hex() user in the file. The output is byte for byte identical. seq_open() clears FMODE_PWRITE for historical reasons and would silently turn pwrite() on entry files into -ESPIPE even though bm_entry_write() accepts writes at any offset. Restore the flag in bm_entry_open() the same way kernfs does for its seq_file backed files so pwrite() keeps working. The only user-visible difference is that seeking is now bound by seq_lseek() instead of default_llseek(), i.e. SEEK_END stops working on entry files, which nothing can sensibly use anyway. The status file keeps its simple_read_from_buffer() as it only ever returns one of two fixed strings. Link: https://patch.msgid.link/20260710-work-binfmt_misc-locking-v3-12-a162f7cb58d6@kernel.org Reviewed-by: Jori Koolstra <jkoolstra@xs4all.nl> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_misc: use print_hex_dump_debug() for the register debug outputChristian Brauner
The hex dumps in create_entry() are compiled out unless someone edits the file to define DEBUG while the pr_debug() calls right next to them are dynamic-debug aware. Switch the dumps to print_hex_dump_debug() which follows the same rules as pr_debug() so the register parsing debug output is uniformly controlled through dynamic debug, and remove the USE_DEBUG machinery. Drop the magic[masked] dump instead of converting it: it printed the bitwise AND of two buffers dumped right above it and required a temporary allocation on every registration just to recompute what the reader can derive from the magic and mask dumps directly. Link: https://patch.msgid.link/20260710-work-binfmt_misc-locking-v3-11-a162f7cb58d6@kernel.org Reviewed-by: Jori Koolstra <jkoolstra@xs4all.nl> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_misc: remove the VERBOSE_STATUS toggleChristian Brauner
VERBOSE_STATUS is a compile-time constant that has been fixed to 1 for as long as git history reaches. Turning it off requires editing the source and yields entry files that only ever report "enabled"/"disabled", a format nothing has ever seen in the wild. Remove the pretend knob and the dead branch it guards. Link: https://patch.msgid.link/20260710-work-binfmt_misc-locking-v3-10-a162f7cb58d6@kernel.org Reviewed-by: Jori Koolstra <jkoolstra@xs4all.nl> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_misc: rename Node to struct binfmt_misc_entryChristian Brauner
The CamelCase Node typedef is a 1997 leftover and hides that this is a plain struct. Call it what it is: struct binfmt_misc_entry, matching struct binfmt_misc that it hangs off of and the entry bit and flag enums. Drop the typedef, switch the size computations in create_entry() to sizeof(*e) and adjust the comments that still referred to the old name. No functional change. Link: https://patch.msgid.link/20260710-work-binfmt_misc-locking-v3-9-a162f7cb58d6@kernel.org Reviewed-by: Jori Koolstra <jkoolstra@xs4all.nl> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_misc: turn the entry behavior flags into an enumChristian Brauner
The MISC_FMT_* behavior flags are macros using unsigned long literals while the entry bit numbers right above them are now a proper enum. Move the flags into an enum as well so every flags word constant is declared in one form and shows up in debuginfo. (1U << N) keeps the enumerators within unsigned int range which is well-defined for enum constants and the values are unchanged when promoted to the unsigned long flags word. No functional change. Link: https://patch.msgid.link/20260710-work-binfmt_misc-locking-v3-8-a162f7cb58d6@kernel.org Reviewed-by: Jori Koolstra <jkoolstra@xs4all.nl> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_misc: turn the entry bit numbers into a proper enumChristian Brauner
Enabled and Magic are bit numbers in the flags word of an entry but are declared as bare, unprefixed enumerators with implicit values in a style that predates the git history. Give the enum a name, explicit bit numbers and namespaced names and use BIT() instead of open-coding the shifts when building the initial flags word in create_entry(). No functional change. Link: https://patch.msgid.link/20260710-work-binfmt_misc-locking-v3-7-a162f7cb58d6@kernel.org Reviewed-by: Jori Koolstra <jkoolstra@xs4all.nl> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_misc: annotate racy accesses to ->enabledChristian Brauner
->enabled has always been read and written locklessly: every exec reads it in load_misc_binary() while bm_status_write() or a concurrent remount via bm_fill_super() may flip it. That is fine as it is an independent boolean toggle but the accesses should be marked accordingly for KCSAN. Annotate them with READ_ONCE()/WRITE_ONCE(). Link: https://patch.msgid.link/20260710-work-binfmt_misc-locking-v3-6-a162f7cb58d6@kernel.org Reviewed-by: Jori Koolstra <jkoolstra@xs4all.nl> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_misc: use RCU for the handler lookupChristian Brauner
Once binfmt_misc is loaded load_misc_binary() runs for every execve() on the system since binfmt_misc registers at the head of the formats list. Every exec therefore performs read_lock() and read_unlock() on the entries_lock of the relevant binfmt_misc instance, i.e., two atomic read-modify-writes on a shared cacheline. User namespaces without their own binfmt_misc mount fall back to an ancestor's instance so on container-heavy systems every exec on the machine typically ends up hammering the cacheline of init_binfmt_misc. On PREEMPT_RT the rwlock additionally turns the handler lookup into a sleeping lock on the exec fast path. The lock protects very little. Entries are immutable after publication except for the Enabled bit which is already toggled locklessly via set_bit()/clear_bit() and entry lifetime is already handled by the users refcount via get_binfmt_handler()/put_binfmt_handler(). The read lock's only remaining job is to make "the entry is still linked" and "take a reference" atomic with respect to the unlink sites. Switch the lookup to an RCU walk: * Lookup walks the entry list under rcu_read_lock() and acquires a reference via refcount_inc_not_zero(). The refcount can only drop to zero after an entry has been unlinked so a failed increment means the walk raced with an unlink. Restarting the search is bounded because an unlinked entry cannot be found again. * The unlink sites use hlist_del_init_rcu() which keeps the forward pointer intact for concurrent walkers and preserves hlist_unhashed() as the protection against double removal. * The final put frees the entry via kfree_rcu() as a concurrent walker may still dereference its flags, magic, mask, and inline strings. They all live in the entry allocation itself and thus stay valid until a grace period has elapsed. Closing the interpreter file stays synchronous. It is only used with a reference already held and all final puts run in process context. * Writers remain serialized by the inode lock of the root dentry with one exception. bm_evict_inode() called from generic_shutdown_super() during umount unlinks entries without holding it. Keep a spinlock around the unlink sites instead of relying on superblock lifetime rules to make that exclusion implicit. Handler removal semantics are unchanged. An exec that acquired a reference just before its handler was unregistered already completes with the removed handler today. The read lock never protected against that, it only made the window smaller. With this an exec that matches no binfmt_misc entry, the common case, no longer writes to any shared cacheline at all. Link: https://patch.msgid.link/20260710-work-binfmt_misc-locking-v3-5-a162f7cb58d6@kernel.org Reviewed-by: Jori Koolstra <jkoolstra@xs4all.nl> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-03binfmt_misc: convert entry list to an hlistChristian Brauner
The upcoming conversion of the handler lookup to RCU walks cannot use list_del_init(): reinitializing the forward pointer of a removed entry would make a concurrent lockless walker standing on that entry loop back onto it indefinitely. The removal paths do rely on reinitialization though because bm_{entry,status}_write() and bm_evict_inode() need to detect whether an entry has already been unlinked. hlists support exactly this pattern: hlist_del_init_rcu() keeps the forward pointer of the removed entry intact for concurrent walkers and only zeroes ->pprev with hlist_unhashed() serving as the linked test. Convert the entry list to an hlist now while keeping the rwlock so the subsequent RCU conversion is a pure locking change. hlist_add_head() inserts at the head just as list_add() did so lookup precedence between registered handlers is unchanged. Link: https://patch.msgid.link/20260710-work-binfmt_misc-locking-v3-4-a162f7cb58d6@kernel.org Reviewed-by: Jori Koolstra <jkoolstra@xs4all.nl> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-08-02smb: client: Fix use-after-free in cifs_try_adding_channels()Shuangpeng Bai
cifs_try_adding_channels() takes a temporary reference to an interface before dropping iface_lock. If cifs_ses_add_channel() fails, it drops that reference and then increments iface->weight_fulfilled. A concurrent interface list refresh can remove the list reference while channel creation is in progress. In that case, the failure-path kref_put() releases the last reference and frees iface. Updating weight_fulfilled afterward then accesses freed memory. Increment weight_fulfilled before dropping the temporary reference, keeping iface alive for the final access. Fixes: 6aac002bcfd5 ("cifs: failure to add channel on iface should bump up weight") Cc: stable@vger.kernel.org Signed-off-by: Shuangpeng Bai <shuangpeng.kernel@gmail.com> Signed-off-by: Steve French <stfrench@microsoft.com>
2026-08-02smb/client: show compress mount optionChenXiaoSong
Example: 1. mount -t cifs -o compress //localhost/test /mnt 2. mount | grep cifs //localhost/test on /mnt type cifs (..., compress, ...) Signed-off-by: ChenXiaoSong <chenxiaosong@kylinos.cn> Signed-off-by: Steve French <stfrench@microsoft.com>
2026-08-02Merge tag 'vfs-7.2-rc6.fixes' of ↵Linus Torvalds
git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs Pull vfs fixes from Christian Brauner: "binfmt_misc: - Don't let an 'F' entry pin its own instance. An entry registered with 'F' opens its interpreter at registration time and holds that file until the entry is freed, so an entry nobody removes by hand is only closed once the binfmt_misc superblock is shut down. If the interpreter lives on a mount that keeps that superblock alive the two pin each other and the file is never closed. That's reachable by pointing the interpreter at the instance itself or by using the instance as an overlayfs lower layer, and once the mount namespace is gone there's nothing left to unregister through either. - Restore write access when removing an entry. Registering with the MISC_FMT_OPEN_FILE flag opens the interpreter via open_exec() which denies write access for as long as the entry exists, but removal only did filp_close() and never restored it. The inode's i_writecount stayed permanently negative and opening the interpreter for writing kept failing with ETXTBSY long after the entry was gone. - Use exe_file_deny_write_access() for the interpreter clone so both sides base their decision on the same mode. - Reject a flag character as the field delimiter. create_entry() pads the buffer with the delimiter so the field parsers terminate even on a truncated string, but check_special_flags() consumes flag characters instead of scanning for the delimiter. If the delimiter is itself a flag character the padding stops acting as a terminator and the scan keeps reading past the end of the allocation. Such a registration was always rejected, just only after the out of bounds read has already happened. - Don't leak the user namespace when the mount fails. bm_get_tree() hands its reference to get_tree_keyed() and sget_fc() moves it into sb->s_fs_info, but generic_shutdown_super() only calls ->put_super() from inside the if (sb->s_root) branch and bm_fill_super() can fail before either s_root or s_op is in place. Drop the reference in ->kill_sb() instead, which runs unconditionally. netfs: - Clear PG_private_2 on a copy-to-cache append failure. - Handle a rolling buffer allocation failure in single-object writeback and drop the extra folio reference netfs_write_folio_single() took before the append. - Release the previously batched readahead folios when rolling_buffer_load_from_ra() fails in netfs_prepare_read_iterator() - Fix the folio_queue ENOMEM in writeback by adding a mempool and passing gfp flags into the rolling buffer helpers. iomap: - Add a separate bio_set for iomap_split_ioend(). It can split bios that already come from iomap_ioend_bioset and deadlock once that bioset is exhausted. afs: - Set call->async for an asynchronous afs_fs_fetch_data() the way afs_fs_fetch_data64() already does. - Subtract subreq->transferred from subreq->len in afs_fs_fetch_data() rather than adding it. - Fix a UAF when sending a message" * tag 'vfs-7.2-rc6.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: iomap: add a separate bio_set for iomap_split_ioend binfmt_misc: don't leak the user namespace when the mount fails binfmt_misc: reject a flag character as the field delimiter binfmt_misc: use exe_file_deny_write_access() for the interpreter clone binfmt_misc: restore write access when removing an entry binfmt_misc: don't let an 'F' entry pin its own instance netfs: Fix folio_queue ENOMEM in writeback by adding a mempool netfs: release readahead folios on iterator preparation failure netfs: handle single writeback rolling buffer allocation failure netfs: clear PG_private_2 on copy-to-cache append failure afs: Fix UAF when sending a message afs: Fix afs_fs_fetch_data() to subtract transferred from len afs: Fix afs_fs_fetch_data() to set call->async
2026-07-31Merge tag 'ntfs-for-7.2-rc6' of ↵Linus Torvalds
git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/ntfs Pull ntfs fixes from Namjae Jeon: - Keep RECALL_ON_OPEN in inode flags when reloading them from $FILE_NAME - Check runlist reallocation sizes for negative values and overflow - Drop stale page cache after shrinking non-resident attributes to prevent writeback failures and data loss * tag 'ntfs-for-7.2-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/ntfs: ntfs: drop stale page-cache when shrinking a non-resident attr ntfs: harden runlist realloc size calculations ntfs: preserve RECALL_ON_OPEN on WSL special-file reparse points
2026-07-31Merge tag 'v7.2-rc5-smb3-server-fixes' of git://git.samba.org/ksmbdLinus Torvalds
Pull smb server fixes from Steve French: - Use memcmp() when comparing fixed-size binary ClientGUIDs, so embedded NUL bytes are handled correctly - Reject repeated SMB2 NEGOTIATE requests after dialect selection This prevents preauth_info leaks, enforces the SMB2 protocol requirements, and serializes negotiation state updates. - Fix a use-after-free in __close_file_table_ids() by removing the volatile file ID from the owning IDR before dropping the IDR reference * tag 'v7.2-rc5-smb3-server-fixes' of git://git.samba.org/ksmbd: ksmbd: use memcmp() to compare ClientGUIDs ksmbd: reject repeated SMB2 NEGOTIATE requests ksmbd: fix use-after-free in __close_file_table_ids()
2026-07-31unicode: Properly reject invalid encoding version stringsGabriel Krisman Bertazi
Casefolding filesystems can request a specific version of UTF-8 at mount-time. utf8_parse_version then assembles the "major.minor.rev" string into an unsigned int. There were two issues with the parser logic: first, individual fields are read as signed int, allowing negative numbers, second, an overflowed field will result in unexpected results. Something like the below actually succeeds to mount using utf8-12.1.0. mount -t tmpfs -o casefold=utf8-12.0.256 none /mnt [ 10.867859] tmpfs: Using encoding : utf8-12.1.0 Signed-off-by: Gabriel Krisman Bertazi <krisman@suse.de>
2026-07-31utf8: Remove unused utf8_normalizeDr. David Alan Gilbert
utf8_normalize() was added in 2019 as part of commit 9d53690f0d4e ("unicode: implement higher level API for string handling") but has remained unused. (I think because the other higher level routines added by that patch normalise as part of their operations) Remove it. Signed-off-by: Dr. David Alan Gilbert <linux@treblig.org> Signed-off-by: Gabriel Krisman Bertazi <krisman@suse.de>
2026-07-31NFSv4.2: fix nfs4_listxattr size accountingAchilles Gaikwad
A call to listxattr() with a buffer size of 0 returns the actual size of the buffer needed for a subsequent call. On an NFSv4.2 mount this triggers the following oops: [ 399.768687] BUG: kernel NULL pointer dereference, address: 0000000000000000 [ 399.768705] RIP: 0010:_copy_from_pages+0x44/0xe0 [ 399.768722] Call Trace: [ 399.768723] nfs4_xattr_alloc_entry+0x1bf/0x1e0 [ 399.768730] nfs4_xattr_cache_set_list+0x43/0x1f0 [ 399.768731] nfs4_listxattr+0x21f/0x250 [ 399.768733] vfs_listxattr+0x55/0xa0 [ 399.768736] listxattr+0x23/0x160 [ 399.768737] path_listxattrat+0xba/0x1e0 [ 399.768739] do_syscall_64+0xe2/0x680 security_inode_listsecurity() (via the xattr_list_one() helper) now decrements the remaining size even when the buffer pointer is NULL, so in the size-query case, 'left' underflows to a huge size_t value. As a result, nfs4_listxattr_nfs4_user() treats the NULL buffer as a real one, leading to a NULL pointer dereference in _copy_from_pages(). security_inode_listsecurity() does not return the number of bytes it added to the list, so the code derived it as 'size - error - left'. That is also wrong in the size-query case: the generic_listxattr() contribution is only subtracted from 'left' when a buffer is present. Thus, the query result comes up short by exactly that contribution (e.g., "system.nfs4_acl" on a mount with ACL support), and a caller that allocates the returned size gets -ERANGE on the subsequent call. Declare 'left' as ssize_t, use a scratch copy to measure security hook consumption, and only decrement 'left' if a buffer is present. Fixes: f71ece9712b7 ("security,fs,nfs,net: update security_inode_listsecurity() interface") Suggested-by: Paul Moore <paul@paul-moore.com> Signed-off-by: Achilles Gaikwad <achillesgaikwad@gmail.com> Reviewed-by: Paul Moore <paul@paul-moore.com> Signed-off-by: Anna Schumaker <anna.schumaker@hammerspace.com>