Repository navigation
Conversation
macFUSE 5 can run file systems in user space through FSKit, which needs
neither its kernel extension nor Reduced Security. Use it on macOS 26
and later when the kernel extension is not loaded.
- Choose the backend once per mount, before the FUSE process forks:
FSKit when running on macOS 26 or later, the kernel extension is not
loaded (no vfs.generic.macfuse.version.number sysctl) and the
installed macFUSE is 5.2 or later, which ships MFMount.framework.
Otherwise the kernel backend is used, so a kernel extension that is
already loaded, or a macFUSE too old for FSKit, works as before. An
approved but not yet loaded kernel extension cannot be told apart
from an unapproved one without a privileged load attempt, so FSKit
is used in that case; a kernel extension loaded later is picked up
by the next mount.
- Pass -o backend=fskit to the auxiliary mount.
- The FSKit backend loads no kernel extension, so the sysctl does not
exist after the mount. A kernel-backend mount loads the extension,
which cannot unload while the mount exists, so a missing sysctl
after a successful mount means FSKit; skip the version check then.
- The FSKit backend ignores direct_io and fails any read that ends
before the advertised file size with EIO. The control and
aux-device-info files advertise at least VC_FUSE_METADATA_SIZE, so
pad their reads with zeros up to the advertised size.
- FSKit file system extensions are enabled per user, and macFUSE
refuses mounts from root ("File system extension not found"). When
an elevated service mounts a volume for a user through FSKit, drop
the FUSE process to that user after the volume is open and before
fuse_main, and give the user the mount point. Dropping from root
marks the process set-id, which keeps the user's other processes
from attaching to it.
- Mark the volume's host file close-on-exec on macOS for both FUSE
backends, so that helpers such as hdiutil do not retain it after the
service exits.
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
macFUSE 5 can run file systems in user space through FSKit, which needs neither its kernel extension nor Reduced Security. This PR uses that backend on macOS 26 and later when the kernel extension is not loaded, so the macFUSE build can mount volumes on a Mac with default security settings. Related to #1900, which asks for FSKit through FUSE-T; this covers the macFUSE build only.
The backend is chosen once per mount, before the FUSE process forks. FSKit is used when macOS is 26 or later, the kernel extension is not loaded (no
vfs.generic.macfuse.version.numbersysctl) and the installed macFUSE is 5.2 or later. Otherwise the mount goes through the kernel extension as before. An extension that is approved but not yet loaded cannot be told apart from an unapproved one without a privileged load attempt, so such a system now mounts through FSKit. An extension loaded later is picked up by the next mount.What FSKit needed:
-o backend=fskitis passed to the auxiliary mount.HigherFuseVersionRequired.direct_ioand fails a read that ends before the advertised file size withEIO.controlandaux-device-infoalready advertise 64 KiB, so their reads are now padded with zeros up to that size. This part is shared code, so Linux and FreeBSD serve the same padded files.setgroups,setgid,setuid) beforefuse_main. Dropping from root marks the process set-id, so the user's other processes cannot attach to it or get its task port. The signal-handler process forked earlier stays root, as before. Mounts through the kernel extension are unchanged.hdiutildo not keep it open after the service exits.Testing
macOS 27.0.1 on Apple Silicon, macFUSE 5.5.0, kernel extension not loaded:
--text), withoutsudo: create a 64 MB exFAT container, mount, write 20 MiB, unmount, mount again and compare SHA-256. The auxiliary mount showsfskit, the kernel extension stays unloaded, and no process or mount is left after the unmount;sudo: the mount belongs to my user and the FUSE process runs with my uid, while the signal-handler process stays root;Linux, because of the padded reads (Debian 13 container, kernel 6.8, aarch64), console build with libfuse 2.9.9 and with libfuse 3.17.2: FAT and exFAT containers, with kernel crypto and with
nokernelcrypto, create, mount,--list, write 20 MB, unmount, mount again and compare.controlandaux-device-inforead back as 65536 bytes. With the libfuse 2 build,test_volume_read.py,test_linux_process.py,test_linux_mount_read_only.pyandtest_linux_mount_points.pypass, and the threeTests/test.*.hcmounts from the Linux workflow work.Not tested:
Two things I noticed with FSKit: on the first mount macOS asks once whether VeraCrypt may access files on a network volume, and in text mode macFUSE prints
fuse: forking a threaded process is unsafe, the child may crash or deadlock. I do not know whether the kernel backend prints the second one too.