This repository was archived by the owner on Sep 8, 2026. It is now read-only.
[pull] master from libfuse:master - #81
Merged
Merged
Conversation
struct fuse_file_info reserves padding bits so new flags can be added without an ABI break, but abidiff reports the resulting member insertion and padding offset shift as a change and fails the check. Bound the suppression to size-preserving changes so a real size change still fails. Signed-off-by: Bernd Schubert <bernd@bsbernd.com>
With FUSE_CAP_HANDLE_KILLPRIV_V2 the kernel stops clearing suid/sgid itself and leaves that to the filesystem. Clearing them depends on CAP_FSETID, held by the application that issued the syscall - the filesystem's own privileges do not matter, and it cannot see the application's, so the kernel signals the decision per request. Of the three flags carrying it only FATTR_KILL_SUIDGID made it through, because FUSE_SET_ATTR_KILL_SUID happens to be the same bit. FUSE_OPEN_KILL_SUIDGID and FUSE_WRITE_KILL_SUIDGID were dropped, so a server that negotiated KILLPRIV_V2 never saw the request on O_TRUNC open and on write, and suid/sgid survived. Decode both into a new fuse_file_info::kill_suidgid, taken from the padding bits, in open, create, write and write_buf. Gate it on the negotiated capability and not on proto_minor: a filesystem that did not ask for KILLPRIV_V2 must never see fi->kill_suidgid set, and negotiating KILLPRIV_V2 implies 7.31, so fuse_create_in::open_flags is there to read. Added by Bernd: - fix the comment style for checkpatch - drop the XXX markers for unhandled open_flags, this patch handles them - replace the proto_minor guard with the capability check - drop security.capability from the field's documentation Signed-off-by: Robert Doebbelin <robert@quobyte.com> Signed-off-by: Bernd Schubert <bernd@bsbernd.com>
Nothing covered fi->kill_suidgid arriving in open, create, write and write_buf. test_setattr already asks whether the lowlevel layer passes the right fuse_file_info to an operation, so the check goes there rather than into a second binary. Its own case file though, to keep the FUSE_CAP_HANDLE_KILLPRIV_V2 requirement off the setattr check. Three runs: - default: fi->kill_suidgid has to arrive set - --write-buf: same, through the write_buf handler - --no-killpriv: it has to arrive clear The kernel sets FUSE_OPEN_KILL_SUIDGID and FUSE_WRITE_KILL_SUIDGID only for a caller without CAP_FSETID, which a root test process gives up for itself rather than skipping the case. The --no-killpriv run is not idle. fuse_direct_io() sets FUSE_WRITE_KILL_SUIDGID for any caller without CAP_FSETID and never consults handle_killpriv_v2, so it reaches a filesystem that did not ask for KILLPRIV_V2 unless libfuse gates on the negotiated capability. Signed-off-by: Bernd Schubert <bernd@bsbernd.com>
A write by a caller without CAP_FSETID has to clear setuid and setgid, and nothing covered that for passthrough_hp. It is worth checking there because the daemon writes to the backing file under its own credentials, which normally hold CAP_FSETID, so the backing filesystem never clears setuid/setgid - and in passthrough mode the daemon does not even see the write. Only the FUSE kernel clears them. Two cases, because opening a backing file needs CAP_SYS_ADMIN and so passthrough mode is only reachable as root: - passthrough-hp-suid, root only, covers the backing-file write path - passthrough-hp-suid-nopassthrough, unprivileged, covers the write path the daemon serves checks.py drops CAP_FSETID for the write, so one check serves both. Signed-off-by: Bernd Schubert <bernd@bsbernd.com>
Without KILLPRIV_V2 the kernel never marks a FUSE inode S_NOSEC, so every write syscall probes security.capability first - 20 writes to one file cost 20 GETXATTR round trips and produced a single WRITE. Under KILLPRIV_V2 the probe stops after the first write and the kernel hands the CAP_FSETID decision to the filesystem instead, which costs one local fstat per WRITE. Not in passthrough mode: the kernel drops the suid/sgid clearing once KILLPRIV_V2 is negotiated, and there the filesystem never sees the write to clear them instead, so suid/sgid would survive. fallocate needs the same care for a different reason. The kernel stops clearing suid/sgid there too, but sends no flag for it - the protocol has one for open, create, write and setattr only. sfs_fallocate() clears them unconditionally, since nothing says whether the caller held CAP_FSETID. Signed-off-by: Bernd Schubert <bernd@bsbernd.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )