FSKit module mount fails with permission error on physical disks

I'm trying to make an FSKit module for NTFS read-write filesystem and at the stage where everything is more or less working fine as long as I mount the volume via mount -F and that volume is a RAM disk. However, since the default NTFS read-only driver is already present in macOS, this introduces an additional challenge.

Judging by the DiskArbitration sources, it looks like all FSKit modules are allowed to probe anything only after all kext modules. So, in this situation, any third-party NTFS FSKit module is effectively blocked from using DiskArbitration mechanisms at all because it's always masked during the probing by the system's read-only kext.

This leaves mount -F as the only means to mount the NTFS volume via FSKit. However, even that doesn't work for volumes on real (non-RAM) disks due to permission issues. The logs in Console.app hint that the FSKit extension is running; however, it looks like the fskitd itself doesn't have permissions to access real disks if it's initiated from the mount utility?

default	16:42:41.939498+0200	fskitd	New module list <private>
default	16:42:41.939531+0200	fskitd	Old modules (null)
default	16:42:41.939578+0200	fskitd	Added 2 identifiers: <private>
default	16:42:41.939651+0200	fskitd	[0x7fc58020bf00] activating connection: mach=true listener=true peer=false name=com.apple.filesystems.fskitd
debug	16:42:41.939768+0200	fskitd	main:RunLoopRun
debug	16:42:41.939811+0200	fskitd	-[liveFilesMountServiceDelegate listener:shouldAcceptNewConnection:]: start
default	16:42:41.939870+0200	fskitd	Incomming connection, entitled 0
debug	16:42:41.940021+0200	fskitd	-[liveFilesMountServiceDelegate listener:shouldAcceptNewConnection:]: accepting connection
default	16:42:41.940048+0200	fskitd	[0x7fc580006120] activating connection: mach=false listener=false peer=true name=com.apple.filesystems.fskitd.peer[1816].0x7fc580006120
default	16:42:41.940325+0200	fskitd	Hello FSClient! entitlement no
default	16:42:41.940977+0200	fskitd	About to get current agent for 503
default	16:42:41.941104+0200	fskitd	[0x7fc580015480] activating connection: mach=true listener=false peer=false name=com.apple.fskit.fskit_agent
info	16:42:41.941227+0200	fskitd	About to call to fskit_agent
debug	16:42:42.004630+0200	fskitd	-[fskitdAgentManager currentExtensionForShortName:auditToken:replyHandler:]_block_invoke: Found extension for fsShortName (<private>)
info	16:42:42.005409+0200	fskitd	Probe starting on <private>
debug	16:42:42.005480+0200	fskitd	-[FSResourceManager getResourceState:]:not_found:<private>
debug	16:42:42.005528+0200	fskitd	-[FSResourceManager addTaskUUID:resource:]:<private>: Adding task (<private>)
debug	16:42:42.005583+0200	fskitd	applyResource starting with resource <private> kind 1
default	16:42:42.005609+0200	fskitd	About to get current agent for 503
info	16:42:42.005629+0200	fskitd	About to call to fskit_agent
debug	16:42:42.006700+0200	fskitd	-[fskitdXPCServer getExtensionModuleFromID:forToken:]_block_invoke: Found extension <private>, attrs <private>
default	16:42:42.006829+0200	fskitd	About to get current agent for 503
info	16:42:42.006858+0200	fskitd	About to call to fskit_agent, bundle ID <private>, instanceUUID <private>
default	16:42:42.070923+0200	fskitd	About to grab assertion on pid 1820
default	16:42:42.071058+0200	fskitd	Initializing connection
default	16:42:42.071141+0200	fskitd	Removing all cached process handles
default	16:42:42.071185+0200	fskitd	Sending handshake request attempt #1 to server
default	16:42:42.071223+0200	fskitd	Creating connection to com.apple.runningboard
info	16:42:42.071224+0200	fskitd	Acquiring assertion: <RBSAssertionDescriptor| "com.apple.extension.session" ID:(null) target:1820>
default	16:42:42.071258+0200	fskitd	[0x7fc58001cdc0] activating connection: mach=true listener=false peer=false name=com.apple.runningboard
default	16:42:42.075617+0200	fskitd	Handshake succeeded
default	16:42:42.075660+0200	fskitd	Identity resolved as osservice<com.apple.filesystems.fskitd>
debug	16:42:42.076337+0200	fskitd	Adding assertion 183-1817-1669 to dictionary
debug	16:42:42.076385+0200	fskitd	+[FSBlockDeviceResource(Project) openWithBSDName:writable:auditToken:replyHandler:]:bsdName:<private>
default	16:42:42.076457+0200	fskitd	[0x7fc5801092e0] activating connection: mach=true listener=false peer=false name=com.apple.fskit.fskit_helper
default	16:42:42.077706+0200	fskitd	+[FSBlockDeviceResource(Project) openWithBSDName:writable:auditToken:replyHandler:]_block_invoke: Open device returned error Error Domain=NSPOSIXErrorDomain Code=13
info	16:42:42.077760+0200	fskitd	+[FSBlockDeviceResource(Project) openWithBSDName:writable:auditToken:replyHandler:]: failed to open device <private>, Error Domain=NSPOSIXErrorDomain Code=13
default	16:42:42.077805+0200	fskitd	[0x7fc5801092e0] invalidated because the current process cancelled the connection by calling xpc_connection_cancel()
debug	16:42:42.077830+0200	fskitd	+[FSBlockDeviceResource(Project) openWithBSDName:writable:auditToken:replyHandler:]:end
info	16:42:42.078459+0200	fskitd	openWith returned err Error Domain=NSPOSIXErrorDomain Code=13 dev (null)
error	16:42:42.078501+0200	fskitd	-[fskitdXPCServer getRealResource:auditToken:reply:]: Unable to convert proxy FSBlockDeviceResource into open resource
error	16:42:42.078538+0200	fskitd	-[fskitdXPCServer applyResource:targetBundle:instanceID:initiatorAuditToken:authorizingAuditToken:isProbe:usingBlock:]: Can't get the real resource of <private>
default	16:42:42.105443+0200	fskitd	[0x7fc580006120] invalidated because the client process (pid 1816) either cancelled the connection or exited

The mount utility call I use is the same for RAM and real disks with the only difference being the device argument and this permission error is only relevant for real disks case.

So, the proper solution (using DiskArbitration) seems to be blocked architecturally in this use case due to FSKit modules being relegated to the fallback role. Is this subject to change in the future?

The remaining workaround with using the mount directly doesn't work for unclear reasons. Is that permission error a bug? Or am I missing something?

However, since the default NTFS read-only driver is already present in macOS, this introduces an additional challenge.

Please file a bug about this specific case (system r/o NTFS driver blocks r/w FSKit driver) and then post that bug number back here. While the basic behavior (prioritizing KEXTs over FSKit) is reasonably justifiable and difficult to address, I think the specific issue around r/o NTFS is important (and narrow) enough that we might want to consider a special cased solution.

So, the proper solution (using DiskArbitration) seems to be blocked architecturally

Note that there is also a bug in DiskArb that is preventing FSKit volumes from working correctly. See this thread for more details.

This leaves mount -F as the only means to mount the NTFS volume via FSKit.

You might also try including "-t nontfs". I haven't tried it, but I believe that would exclude the kernel NTFS driver while leaving yours as an option.

However, even that doesn't work for volumes on real (non-RAM) disks due to permission issues.

A few things here:

  1. You ran "mount" as root, correct?

  2. Is the slice you're trying to target on the boot device or is it an external volume?

  3. Are you able to mount disk images?

The remaining workaround with using the mount directly doesn't work for unclear reasons. Is that permission error a bug? Or am I missing something?

I'm not sure. It's possible that the boot volume is special cased, but other devices should work. Similarly, disk images bypass most of the permission dynamics that effect physical devices. Finally, I'm not sure how the NTFS collision changes things.

The big thing to look at here is what the large system log shows, particularly between these log messages:

debug	16:42:42.076385+0200	fskitd	+[FSBlockDeviceResource(Project) openWithBSDName:writable:auditToken:replyHandler:]:bsdName:<private>
default	16:42:42.076457+0200	fskitd	[0x7fc5801092e0] activating connection: mach=true listener=false peer=false name=com.apple.fskit.fskit_helper
default	16:42:42.077706+0200	fskitd	+[FSBlockDeviceResource(Project) openWithBSDName:writable:auditToken:replyHandler:]_block_invoke: Open device returned error Error Domain=NSPOSIXErrorDomain Code=13

That sequence called out to "fskit_helper" and I'd expect there to be logging from it or secondary components that might provide more detail on the underling issue.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Please file a bug about this specific case (system r/o NTFS driver blocks r/w FSKit driver) and then post that bug number back here.

I have filed a bug: FB18230524

You might also try including "-t nontfs". I haven't tried it, but I believe that would exclude the kernel NTFS driver while leaving yours as an option.

It looks like mount (without -F) tries to use literal non-existent nontfs filesystem in this case:

$ mount -t nontfs disk2s2 ./mnt
mount: exec /Library/Filesystems/nontfs.fs/Contents/Resources/mount_nontfs for /Users/user/temp/fstest/mnt: No such file or directory
mount: /Users/user/temp/fstest/mnt failed with 72

You ran "mount" as root, correct?

I currently run mount as a normal administrator user (otherwise this workaround would need a helper with elevated privileges to be used in the app). However, I also attempted to run it as root. In that case the mount -F command fails without providing a specific error message.

$ sudo mount -F -t abcd_ntfs disk11 ./mnt
mount: Unable to invoke task

# mount -F -t abcd_ntfs disk11 ./mnt
mount: Unable to invoke task

Judging by the logs, it stops somewhere early:

default	16:54:13.664228+0200	fskitd	Hello FSClient! entitlement no
default	16:54:13.664465+0200	mount	Setting remote protocol to all XPC
default	16:54:13.665000+0200	fskitd	Getting own modules
default	16:54:13.665045+0200	fskitd	Returning module array <private>
default	16:54:13.665236+0200	mount	[0x7fe9e1a04140] invalidated because the current process cancelled the connection by calling xpc_connection_cancel()
default	16:54:13.665266+0200	fskitd	[0x7f9424a05570] invalidated because the client process (pid 1542) either cancelled the connection or exited

Furthermore, the mount -F command fails for all volumes when run with root privileges, including non-physical volumes.

Is the slice you're trying to target on the boot device or is it an external volume?

I have tested both a volume on the boot device and an external volume on a USB device. In both cases, the same error occurs and almost identical logs:

$ mount -F -t abcd_ntfs disk2s2 ./mnt
mount: Probing resource: The operation couldn’t be completed. Permission denied
mount: Unable to invoke task

Are you able to mount disk images?

Yes, disk images can be mounted without issues using the non-root mount -F command.

$ hdiutil attach -imagekey diskimage-class=CRawDiskImage -nomount ./ntfs-rw.dmg
/dev/disk11
$ mount -F -t abcd_ntfs disk11 ./mnt
$ diskutil info disk11
   Device Identifier:         disk11
   Device Node:               /dev/disk11
   Whole:                     Yes
   Part of Whole:             disk11
   Device / Media Name:       Disk Image

   Volume Name:               NTFS_IMAGE
   Mounted:                   Yes
   Mount Point:               /Users/user/temp/fstest/mnt

Finally, I'm not sure how the NTFS collision changes things.

Just in case, the filesystem short name in my FSKit module is not ntfs/NTFS to avoid the naming collision.

The big thing to look at here is what the large system log shows, particularly between these log messages:

I have attached fuller log of that area.

I also encountered this permission issue when working with FSKit on physical external volume (e.g. a USB device). The workaround I'm using is to change the owner of the dev node to be the current user:

sudo chown $(whoami) /dev/rdisk6s3

(where disk6s3 is your target disk)

This probably isn't a great long-term solution but it at least got me able to test my module with a physical device.


(Running mount as root didn't work for me either. It's as if it didn't know the FSKit module was there. My assumption was that enabling the module in Settings only enabled it for my user account, and root didn't have it enabled? I suppose based on @DTS Engineer 's suggestion to run mount as root, sudo mount not working is actually a bug though.)

I also encountered this permission issue when working with FSKit on physical external volume (e.g. a USB device). The workaround I'm using is to change the owner of the dev node to be the current user:

Unfortunately, more bugs have been found so you're going to need to wait for more fixes. Thanks for your patience and I'll try and let you know when you should test again.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

FSKit module mount fails with permission error on physical disks
 
 
Q