Are read-only filesystems currently supported by FSKit?

I'm writing a read-only filesystem extension.

I see that the documentation for loadResource(resource:options:replyHandler:) claims that the --rdonly option is supported, which suggests that this should be possible. However, I have never seen this option provided to my filesystem extension, even if I return usableButLimited as a probe result (where it doesn't mount at all - FB19241327) or pass the -r or -o rdonly options to the mount(8) command. Instead I see those options on the volume's activate call.

But other than saving that "readonly" state (which, in my case, is always the case) and then throwing on all write-related calls I'm not sure how to actually mark the filesystem as "read-only." Without such an indicator, the user is still offered the option to do things like trash items in Finder (although of course those operations do not succeed since I throw an EROFS error in the relevant calls).

It also seems like the FSKit extensions that come with the system handle read-only strangely as well. For example, for a FAT32 filesystem, if I mount it like

mount -r -F -t msdos /dev/disk15s1 /tmp/mnt

Then it acts... weirdly. For example, Finder doesn't know that the volume is read-only, and lets me do some operations like making new folders, although they never actually get written to disk. Writing may or may not lead to errors and/or the change just disappearing immediately (or later), which is pretty much what I'm seeing in my own filesystem extension. If I remove the -F option (thus using the kernel extension version of msdos), this doesn't happen.

Are read-only filesystems currently supported by FSKit? The fact that extensions like Apple's own msdos also seem to act weirdly makes me think this is just a current FSKit limitation, although maybe I'm missing something. It's not necessarily a hard blocker given that I can prevent writes from happening in my FSKit module code (or, in my case, just not implement such features at all), but it does make for a strange experience.

(I reported this as FB21068845, although I'm mostly asking here because I'm not 100% sure this is not just me missing something.)

Answered by DTS Engineer in 866824022

Are read-only filesystems currently supported by FSKit?

I think the tricky part here is what "support" here actually means. Let me start by what this actually "does":

pass the -r or -o rdonly options to the mount(8) command.

Passing that to mount should mean that the VFS layer itself is prevented from writing to the device. In FSKit terms, that means "FSBlockDeviceResource.writable" should be false and that all write methods should fail. If either of those behave differently, then that's a HUGE bug that we'd need to fix ASAP.

However, the confusing point here is that mounting a volume "readonly" doesn't necessarily define/change how the file system "presents" itself to the higher level system. That is, strictly speaking, nothing prevents a volume being mounted "readonly"... but that file system itself allowing itself to be fully modifiable.

That might sound a bit strange, but as a concrete example, you could implement a "resettable" file system by using the on-disk file system as the starting structure, routing all writes to secondary storage, and then discarding that storage on unmount. That's just one example, but the broader point is that the data "source" and lower-level VFS system aren't designed to control/constrain the file system that's actually presented to the system.

That leads to here:

Then it acts... weirdly. For example, Finder doesn't know that the volume is read-only, and lets me do some operations like making new folders, although they never actually get written to disk.

So, FYI, this is what happens when the high-level system presents operations as "possible" when it can't actually perform those operations. You can actually get exactly the same thing to happen to any of our kernel drivers, though it takes a KEXT*.

*More specifically, having written a KEXT that did this earlier in my career, if the IOMedia driver (the top level of the IOKit storage stack) "flips" itself to read-only AFTER the volume has mounted, you basically get exactly the behavior you're describing.

In terms of what your extension should do (and why msdosfs is failing), I think the best approach here is to support permissions (FSItemAttributeMode), and then ALWAYS return a configuration for all objects that prevents writing and fail any attempt to modify mode. You could also implement FSVolumeAccessCheckOperations; however, I'm not sure that will actually behave the way you want, and the mode operation is the more important check. The mode configuration means that the system (particularly the Finder) "knows" that the object is read-only before it attempts any operation, which means it never bothers trying.

That leads to here:

It also seems like the FSKit extensions that come with the system handle read-only strangely as well. For example, for a FAT32 filesystem,

It also seems like the FSKit extensions that come with the system handle read-only strangely as well.

Please file a bug on this (specifically, msdosfs's behavior) and post the bug number once it's filed.

What's going on here is that we're returning FSVolumeSupportedCapabilities.doesNotSupportSettingFilePermissions because, in fact, FAT does not support file permissions. However, that also means that it can't "tell" the higher-level system that it's read-only because it's disabled file permissions. In any case, I think it could solve all this by removing "doesNotSupportSettingFilePermissions" on read-only volumes and using exactly the same approach I'm suggesting above... and if it can’t, then this is an edge case we should probably solve. Either way, it's worth a bug.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Are read-only filesystems currently supported by FSKit?

I think the tricky part here is what "support" here actually means. Let me start by what this actually "does":

pass the -r or -o rdonly options to the mount(8) command.

Passing that to mount should mean that the VFS layer itself is prevented from writing to the device. In FSKit terms, that means "FSBlockDeviceResource.writable" should be false and that all write methods should fail. If either of those behave differently, then that's a HUGE bug that we'd need to fix ASAP.

However, the confusing point here is that mounting a volume "readonly" doesn't necessarily define/change how the file system "presents" itself to the higher level system. That is, strictly speaking, nothing prevents a volume being mounted "readonly"... but that file system itself allowing itself to be fully modifiable.

That might sound a bit strange, but as a concrete example, you could implement a "resettable" file system by using the on-disk file system as the starting structure, routing all writes to secondary storage, and then discarding that storage on unmount. That's just one example, but the broader point is that the data "source" and lower-level VFS system aren't designed to control/constrain the file system that's actually presented to the system.

That leads to here:

Then it acts... weirdly. For example, Finder doesn't know that the volume is read-only, and lets me do some operations like making new folders, although they never actually get written to disk.

So, FYI, this is what happens when the high-level system presents operations as "possible" when it can't actually perform those operations. You can actually get exactly the same thing to happen to any of our kernel drivers, though it takes a KEXT*.

*More specifically, having written a KEXT that did this earlier in my career, if the IOMedia driver (the top level of the IOKit storage stack) "flips" itself to read-only AFTER the volume has mounted, you basically get exactly the behavior you're describing.

In terms of what your extension should do (and why msdosfs is failing), I think the best approach here is to support permissions (FSItemAttributeMode), and then ALWAYS return a configuration for all objects that prevents writing and fail any attempt to modify mode. You could also implement FSVolumeAccessCheckOperations; however, I'm not sure that will actually behave the way you want, and the mode operation is the more important check. The mode configuration means that the system (particularly the Finder) "knows" that the object is read-only before it attempts any operation, which means it never bothers trying.

That leads to here:

It also seems like the FSKit extensions that come with the system handle read-only strangely as well. For example, for a FAT32 filesystem,

It also seems like the FSKit extensions that come with the system handle read-only strangely as well.

Please file a bug on this (specifically, msdosfs's behavior) and post the bug number once it's filed.

What's going on here is that we're returning FSVolumeSupportedCapabilities.doesNotSupportSettingFilePermissions because, in fact, FAT does not support file permissions. However, that also means that it can't "tell" the higher-level system that it's read-only because it's disabled file permissions. In any case, I think it could solve all this by removing "doesNotSupportSettingFilePermissions" on read-only volumes and using exactly the same approach I'm suggesting above... and if it can’t, then this is an edge case we should probably solve. Either way, it's worth a bug.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

I think the tricky part here is what "support" here actually means.

Yeah, I was actually having a bit of trouble trying to think of a title for this post (and for the aforementioned FB21068845).

If either of those behave differently, then that's a HUGE bug that we'd need to fix ASAP.

I didn't actually check those two (write isn't implemented at all in my filesystem). While it would take a little longer to check actual writes I just checked and FSBlockDeviceResource.isWritable is returning the correct value (false) when mounted as read-only, so I think that part is okay, at least!

I think the best approach here is to support permissions (FSItemAttributeMode), and then ALWAYS return a configuration for all objects that prevents writing and fail any attempt to modify mode

I actually have tried this. There's this code in my real project:

if request.isAttributeWanted(.mode) {
    // FIXME: not correct way to enforce read-only file system but does FSKit currently have a better way?
    let useMode = readOnlySystem ? mode.subtracting([.ownerWrite, .groupWrite, .otherWrite]) : mode
    attributes.mode = UInt32(useMode.rawValue)
}

I suppose I can remove that FIXME if that's the case! However, that doesn't remove the relevant options from Finder, and users can still attempt to do these actions. It'll ask me to first authenticate with my admin password, then fail if I do.

Edit: actually, I think the admin prompt is because of the access check. When I modify the sample project I sent into FB21068845 to just return a mode of 0o555 then it still just presents me the option to use those options and doesn't ask for admin, but still returns errors.

The other annoyance I see with this solution is that if I use Finder (or something else like cp) to copy files out of this read-only disk onto some other disk that is read-write (like the internal SSD), then the destination file also has the read-only mode.

Please file a bug on this (specifically, msdosfs's behavior)

Here you go: FB21094219

First of all, on the msdosfs issues:

Here you go: FB21094219

I discussed this with the team and, yes, none of this is intentional and it will be fixed in the future.

Moving over to the more general issue, yes, there is a bug here (r.150720858). The way this works in the VFS layer is that the vfs driver is told that the mount request is read-only and the VFS driver can then mark the mount point as read-only (which is what most do). That then propagates back to user space as the "MNT_RDONLY" flag returned through statfs (among other points). Much of the infrastructure for that is already in place; however, there should be an API to allow your driver to directly set it and there appears to be a breakdown in the logic which means that flag isn't getting set automatically. I can't comment on our release schedule, but the issue is well understood and fixing it is a high priority.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Are read-only filesystems currently supported by FSKit?
 
 
Q