Skip to content

Commit 20c399e

Browse files
fix: kext: sysfs_vfsops: stop advertising MNT_RDONLY
Mounting sysfs put coreservicesd into a crash loop, which is the real cause of the long-standing "system gradually stops responding" symptom: typing stalls, applications refusing to launch, an unresponsive Dock, and eventually nothing opening at all. CoreServices aborts while registering the mount in its volume universe: _CSAbortWithMessage <- FSNode_VolumeMounted <- FSNodeServer_SyncSystemUniverseInternal <- FileIDTreeServerGetVRefNumForDeviceInternal coreservicesd relaunches, re-syncs, hits the mount again and re-aborts, taking Launch Services down with it. loginwindow's black screen at login is the same abort reached earlier in boot, so mounting after login only moved the symptom. None of this was visible from the kernel side, which is why it resisted diagnosis for so long: the abort is in userspace, provoked by the mount merely existing. A full system spindump taken while /sys was mounted contained zero sysfs frames, and the vnop/vfs counters stayed flat across hangs. With /sys unmounted, no new coreservicesd crash reports appear. MNT_RDONLY is isolated as the offender by the two synthetic filesystems that never trigger the abort: procfs mounts MNT_LOCAL without it, devfs mounts MNT_LOCAL|MNT_DONTBROWSE without it. MNT_DONTBROWSE is kept - it is safe, and it is still needed to keep Spotlight from indexing the live IORegistry tree under /sys/devices. Read-only behaviour is unchanged. This filesystem registers no write, create, mkdir or setattr vnop, so every mutating operation already falls through to sysfs_vnop_default() and returns ENOTSUP; MNT_RDONLY only asked VFS to reject those same operations one layer earlier.
1 parent 8c5264e commit 20c399e

2 files changed

Lines changed: 35 additions & 7 deletions

File tree

kext/sysfs_vfsops.c

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -165,10 +165,35 @@ sysfs_mount(struct mount *mp, __unused vnode_t devvp, user_addr_t data, __unused
165165

166166
/*
167167
* Install sysfs-specific flags and augment the generic mount flags.
168-
* sysfs is a read-only synthetic view (as Linux /sys's root is) - it has
169-
* no writable nodes yet, so MNT_RDONLY is appropriate. It is revisited
170-
* when writable attributes arrive (the VFS layer rejects writes on a
171-
* read-only mount before they can reach vnop_write).
168+
*
169+
* NOT MNT_RDONLY, deliberately. Advertising a read-only *synthetic local*
170+
* volume makes CoreServices abort while registering the mount:
171+
*
172+
* _CSAbortWithMessage <- FSNode_VolumeMounted
173+
* <- FSNodeServer_SyncSystemUniverseInternal
174+
* <- FileIDTreeServerGetVRefNumForDeviceInternal
175+
*
176+
* coreservicesd then relaunches, re-syncs its volume universe, hits the
177+
* mount again and re-aborts - a crash loop that takes Launch Services
178+
* down with it. That is the true cause of the long-standing "system
179+
* gradually stops responding" symptom (typing stalls, apps refusing to
180+
* launch, an unresponsive Dock) and of loginwindow's black screen at
181+
* login, which is the same abort reached earlier in boot. None of it is
182+
* visible from the kernel side: the abort is in userspace, provoked by
183+
* the mount merely existing, so a full system spindump taken while /sys
184+
* was mounted contained zero sysfs frames.
185+
*
186+
* The flag bought nothing. This filesystem registers no write, create,
187+
* mkdir or setattr vnop, so every mutating operation already falls
188+
* through to sysfs_vnop_default() and returns ENOTSUP; MNT_RDONLY only
189+
* asked VFS to reject those same operations one layer earlier. Read-only
190+
* behaviour is unchanged by its removal.
191+
*
192+
* The two synthetic filesystems that do not trigger the abort bracket
193+
* the flag set and isolate MNT_RDONLY as the offender: procfs mounts
194+
* MNT_LOCAL without it, and devfs mounts MNT_LOCAL|MNT_DONTBROWSE
195+
* without it. MNT_DONTBROWSE is therefore kept - it is safe, and it is
196+
* needed for the reason below.
172197
*
173198
* MNT_DONTBROWSE is essential, not cosmetic: without it the volume is
174199
* presented as a browsable local disk, so Finder/DiskArbitration and -
@@ -181,7 +206,7 @@ sysfs_mount(struct mount *mp, __unused vnode_t devvp, user_addr_t data, __unused
181206
* /proc and /sys are never indexed. (The procfs sibling gets away without
182207
* it only because /proc is shallow and cheap to walk.)
183208
*/
184-
vfs_setflags(mp, MNT_RDONLY|MNT_NOSUID|MNT_NOEXEC|MNT_NODEV|MNT_NOATIME|MNT_LOCAL|MNT_DONTBROWSE);
209+
vfs_setflags(mp, MNT_NOSUID|MNT_NOEXEC|MNT_NODEV|MNT_NOATIME|MNT_LOCAL|MNT_DONTBROWSE);
185210

186211
/*
187212
* Increment the mounted instance count so that each mount of the file system

kext/sysfs_vnops.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,11 @@ int64_t sysfs_stat_vnops = 0;
176176
* registered as a file system and a pointer to that vector is stored in
177177
* sysfs_vnodeop_p.
178178
*
179-
* The file system is read-only (the mount is MNT_RDONLY), so there is no write /
180-
* setattr entry; those arrive with the first writable attribute.
179+
* The file system is read-only, so there is no write / setattr entry; those
180+
* arrive with the first writable attribute. Read-only-ness is enforced here
181+
* rather than by the mount: every mutating vnop is absent from this table and
182+
* so lands in sysfs_vnop_default(), which returns ENOTSUP. The mount is
183+
* deliberately not MNT_RDONLY - see the flag discussion in sysfs_vfsops.c.
181184
*/
182185
struct vnodeopv_entry_desc sysfs_vnodeop_entries[] = {
183186
{ .opve_op = &vnop_default_desc, .opve_impl = (VOPFUNC) sysfs_vnop_default }, /* default */

0 commit comments

Comments
 (0)