Apple File System is the default file system for iOS 10.3 and later, and for macOS High Sierra and later.

Posts under APFS tag

200 Posts

Post

Replies

Boosts

Views

Activity

How can a macOS application establish that an open APFS file has no extended ACL?
On macOS 26.5.2 (build 25F84), which documented API and return conditions, if any, establish that a regular file on APFS has no extended access control list (ACL), using an already-open file descriptor? We tested three disposable regular files on an APFS volume reporting ACL support. For each file, we opened a read-only file descriptor and called: acl_get_fd_np(fd, ACL_TYPE_EXTENDED) fgetattrlist() requesting ATTR_CMN_RETURNED_ATTRS | ATTR_CMN_EXTENDED_SECURITY Before and after inspection, fstat() confirmed stable device, inode, mode, and change timestamp. Observed results: 1. Newly created file, no ACL explicitly assigned acl_get_fd_np() returned NULL with errno == ENOENT. fgetattrlist() succeeded but omitted ATTR_CMN_EXTENDED_SECURITY from the returned attribute mask. FSOPT_PACK_INVAL_ATTRS also left that bit clear. 2. File with an explicitly assigned empty ACL acl_get_fd_np() returned NULL with errno == ENOENT. fgetattrlist() returned the extended-security attribute with an ACL entry count of zero. 3. File with one explicit ACL entry acl_get_fd_np() returned a non-null ACL. fgetattrlist() returned the extended-security attribute with an ACL entry count of one. Apple's published XNU attribute-packing implementation appears to use the same omission branch when ACL metadata is unsupported or when the ACL pointer is null. My question: Is there a supported descriptor-based API sequence that reliably distinguishes: Genuine absence of an extended ACL Unavailable or unsupported per-file ACL metadata An ACL retrieval failure If so, which API, capability checks, return values, attribute bits, or error conditions should a caller rely on? Are there relevant APFS or macOS version limitations? If the public API cannot establish ACL absence unambiguously in this situation, confirmation of that limitation would also be helpful. Thank you for your guidance.
0
0
15
1h
Requesting com.apple.developer.vfs.snapshot for a Developer ID backup app (Team LM3P28DNVQ)
Hello, I am Ahmed Hamade, founder of Pixel Ventures LLC, Apple Developer Program Team ID LM3P28DNVQ. I am asking Apple to grant the restricted entitlement com.apple.developer.vfs.snapshot to our team for a macOS backup application named PixelProtect. If this is not the right channel, please tell me where to send the request. PixelProtect backs up a whole Mac volume. It keeps one primary backup set on a local disk and a replica of that same set in cloud storage, protects both copies against deletion, and supports recovery. We built it for people whose AI coding agents can delete data. We need snapshots for three reasons. First, files change while a backup runs, so the backup must read from one point in time to copy a consistent state. Second, snapshots let us keep local restore points without copying the data again. Third, Time Machine takes local snapshots for the same purpose. The only alternative today is tmutil localsnapshot, whose snapshots the system manages and ages out, so we could not keep restore points of our own. We would use fs_snapshot_create, fs_snapshot_list, fs_snapshot_delete and fs_snapshot_mount. We do not use fs_snapshot_revert. Restores copy files out of a mounted snapshot. Only our privileged helper calls these functions. It runs as root, is registered with SMAppService, and is packaged as an app-like bundle (planned App ID ai.pixelventures.pixelprotect.daemon) so it can embed a provisioning profile. The main app (ai.pixelventures.pixelprotect) and our command line tool send requests to the helper and do not call these functions. We limit use as follows. Snapshots are created only on volumes the user chose to back up. The user controls how long snapshots are kept. The helper deletes only snapshots it created, which carry our own name prefix, and only under the user's retention rules or an action the user confirms. PixelProtect is signed with our Developer ID Application certificate, uses the hardened runtime, is notarized, and is distributed outside the Mac App Store to Pixel Ventures clients. It is not sandboxed, because a whole-volume backup reads the whole volume. It has no public marketing page yet, so a product description is attached. Please enable the entitlement for Team ID LM3P28DNVQ for development and for Developer ID distribution, or tell me what further information you need. I tried the code-level support request form and it requires a sample project, so I am asking here as the form suggested Thank you, Ahmed Hamade Founder, Pixel Ventures LLC Team ID LM3P28DNVQ I tried the code-level support request form and it requires a sample project, so I am asking here as the form suggested
3
0
54
13h
macOS APFS: NSFileCoordinator snapshot consistency and renameatx_np durability guarantees
Reference environment: macOS 26.7.1, build 25G241, arm64, local APFS. Consistent capture of a source file We are evaluating NSFileCoordinator with the forUploading and withoutChanges options for a single regular file. Does the resulting snapshot guarantee byte contents corresponding to a single point in time, even if another process writes during capture without file coordination, using write/pwrite or a shared writable memory mapping? We need to establish the scope, conditions, and limitations of this guarantee. We do not require capturing an editor’s unsaved changes or application-level database consistency. If any of these concurrent writing methods are not covered, please identify them explicitly. Durability of the final filename after a rename We are evaluating the following sequence: a verified temporary file has successfully completed strong synchronization, and is then renamed using renameatx_np with RENAME_EXCL. The temporary and final names are in the same directory on the same volume. Next, fsync_volume_np is called with SYNC_VOLUME_FULLSYNC and SYNC_VOLUME_WAIT. Under what conditions does a successful return confirm that the final filename and its association with the prepared file contents will survive a system crash or power loss? We also need clarification on whether all relevant data and metadata write errors are propagated to the caller, or whether an earlier error might remain unreported by this operation. Please provide the documented scope and limitations for this environment.
0
0
131
6d
macOS 15.7.9/APFS: How to diagnose slow SQLite quick_check with pread-heavy samples?
I am seeking advice about supported macOS performance tracing, NOT reporting a confirmed APFS bug. This is a real application failure. AI assisted with organizing this report, and the measurements were reviewed against existing records. Environment Apple Silicon Mac Studio, 32 GB RAM, macOS 15.7.9 (24G830). CPython 3.11.15, linked SQLite 3.50.4. SQLite database: 3,224,576,000 bytes on an internal APFS volume, journal_mode=DELETE. The application runs PRAGMA quick_check before starting worker processes. A progress handler cancels the operation after 30 seconds, producing SQLITE_INTERRUPT. This is application-triggered, not proof of corruption. Observed results Original database: 30.008 s wall / 5.220 s CPU; a separate run took 30.192 s wall / 5.420 s CPU. Both were interrupted. A two-second sample showed 95/96 samples on SQLite's checkTreePage → readDbPage → unixRead → pread path. Individual pread latency was not measured. A transaction-consistent SQLite Backup API snapshot on a different APFS volume completed quick_check in 2.412 s and integrity_check in 8.797 s, both returning "ok". The snapshot and original were checked at different times with uncontrolled cache and system-load conditions. Additional mmap experiment On the same offline snapshot: A: mmap_size=0, executed first, quick_check took 31.070 s and was interrupted. B: reported mmap limit approximately 2 GiB, executed second, quick_check returned "ok" after 22.146 s. Cache conditions and host load were not equivalent, so these observations do NOT establish an mmap performance improvement. A separate deliberate mapped-I/O error test ended with SIGBUS in an isolated child process. This does not establish an ordinary APFS defect. Questions Which supported macOS Instruments templates or APIs can correlate pread offsets, sizes and timings with physical disk latency, filesystem cache activity, memory pressure and thread scheduling, without disabling system security protections? What minimum set of simultaneous observations could distinguish cache misses, APFS metadata/layout overhead, physical device delays and CPU scheduling contention? How should process read-byte counts be interpreted against physical disk I/O? How should I safely compare read-only SQLite mmap against normal pread access on disposable copies, without mistaking a warmer second run for a performance gain? What SIGBUS containment and recovery checks would be appropriate? I am primarily looking for a reliable instrumentation plan and interpretation criteria before conducting further tests. I do not want to modify the original database, weaken integrity checks or bypass security controls.
1
0
130
1w
Supported safe-save contract for a sandboxed AIFF editor on APFS
We are evaluating a separately App-Sandboxed GUI helper for one explicitly reviewed AIFF NAME edit on internal-disk APFS. The main app retains user-selected read-only access. The helper has only App Sandbox and user-selected read/write entitlements. We would like the supported API and failure/reconciliation contract before implementing physical-file edits. Bounded observation A local synthetic-fixture probe used macOS 27.2 (26B118), SDK 27.0, arm64, ad-hoc signing with Hardened Runtime, LaunchServices and the helper's own NSOpenPanel. Captured stat fields, raw xattrs and bytes were unchanged after selection and an O_RDONLY read. Across a later O_RDWR open/fstat/close gate, com.apple.quarantine was added and ctime changed; bytes stayed identical and close returned 0. There was no content-write call. This describes one observed build/run, not a general OS mechanism. We have not tested copyfile, clonefile or replacement paths. Questions Existing-file conflicts. We read the later DTS explanation in thread 850377 about path-based link/rename substitution limits. Our use case is an ordinary editor replacing an existing user-selected file while another uncoordinated app might edit or replace it. What supported pattern and limits should we use to avoid silently overwriting unrelated updates, detect conflicts and retain truthful indeterminate outcomes? Is any supported replacement operation conditional on the previously reviewed destination object/content version, or should that guarantee be treated as unavailable under this concurrency model? We do not assume a post-operation identity check prevents an earlier effect. Protected metadata. What preservation contract should this sandboxed helper rely on for quarantine/provenance, ACLs and unrelated xattrs through copy/clone, a native-field edit and replacement? The current copyfile/clonefile manuals describe metadata copying and exceptions, while FileManager replacement documents selected original metadata. If exact raw quarantine equality is not the supported invariant, which public properties or behaviors should verification check, including originally absent quarantine? We want to retain Apple's security semantics without stripping quarantine, normalizing undocumented flags or disabling App Sandbox. Replacement access. After selecting an existing file in NSOpenPanel, is FileManager's itemReplacementDirectory plus replaceItemAt a supported safe-save route under that file selection? What additional consent, if any, is required for temporary-file creation and namespace publication? We do not assume parent-directory access or propose adding selected-source write rights to the main app. Relevant references: FileManager replacement File coordination No user media, paths, saved grants, private logs or binaries are attached. We are seeking supported semantics and refusal boundaries before further implementation or experiments.
0
0
107
1w
macOS/APFS: Is there a supported way to create a hard link from an open file descriptor without pathname substitution?
We are developing a security-sensitive local execution system on macOS and need clarification about supported Darwin/APFS filesystem APIs. Our requirement is to create an additional directory entry (hard link) for an existing, authorized regular-file object while retaining its original directory entry. SECURITY REQUIREMENTS The source file has already been opened and its identity verified using a held file descriptor and fstat(). The source must remain the exact same filesystem object (device/inode identity), not a copy or clone. An attacker operating under the same user account may concurrently rename, unlink, or replace the source pathname. The publication operation must not create a hard link to, or otherwise mutate, a substituted source object. The new link must be created within an already-open, authorized destination directory. Unsupported configurations must be detectable before attempting a potentially unsafe publication mutation. The original source directory entry must remain present. We have reviewed linkat(), fclonefileat(), rename-based approaches, filesystem flags, and directory-descriptor-relative operations. The difficulty is that linkat() identifies its source through a pathname. Holding a verified source file descriptor does not appear to guarantee that the pathname still identifies the same object when linkat() performs the mutation. A subsequent fstat() or pathname identity check cannot undo an already-created link to a substituted object. QUESTIONS Does macOS provide a supported public API that creates an additional hard link directly from an existing open file descriptor, without resolving a replaceable source pathname? Does Darwin support an equivalent of Linux linkat() with AT_EMPTY_PATH, or another documented descriptor-based source-linking mechanism? Can any supported macOS filesystem API guarantee that a concurrent same-user replacement of the source directory entry cannot redirect the publication mutation? If descriptor-based hard linking is unavailable, is there a supported filesystem or namespace protection mechanism that prevents same-owner source-entry substitution throughout the operation? Do AT_SYMLINK_FOLLOW, AT_SYMLINK_NOFOLLOW, AT_RESOLVE_BENEATH, AT_RESOLVE_NOFOLLOW_ANY, or related Darwin flags provide any guarantee that the linked source is the previously verified inode rather than a replacement? Are the relevant guarantees dependent on macOS version, APFS volume configuration, filesystem flags, privileges, or entitlements? Is there a supported way to determine whether the required operation and guarantees are available before performing the publication mutation? We are specifically interested in documented and supported APIs, their identity guarantees, availability conditions, and limitations. We are not seeking a workaround based solely on comparing file identities after the operation, copying/cloning the file, or assuming that same-user pathname replacement cannot occur. If no supported public API provides these guarantees, confirmation of that limitation would also be helpful. Thank you.
5
0
281
1w
macOS 27/APFS: Supported ACL Absence Verification When acl_get_fd_np Returns ENOENT
Subject: Supported fail-closed ACL absence verification on macOS 27.0.1 / APFS Environment: macOS 27.0.1, build 26A434; APFS; installed macOS 27.0 SDK. We need a supported, documented way to determine whether an existing filesystem object has no effective ACL entries, while rejecting genuine retrieval failures and unsupported or unavailable ACL evidence. We are seeking clarification of the public interface contract, not alleging an Apple defect. For existing directory and regular-file fixtures, pathname metadata and descriptor metadata identify the same object. Errno is cleared immediately before each native call and captured immediately afterward. ACL retrieval uses ACL_TYPE_EXTENDED: acl_get_file(path, ACL_TYPE_EXTENDED) acl_get_fd_np(fd, ACL_TYPE_EXTENDED) On fresh objects, both return NULL with ENOENT. Explicit one-entry fixture ACLs are retrieved successfully. Explicit zero-entry fixture ACLs can also yield NULL/ENOENT, while attribute queries return a serialized zero-entry ACL. The attribute queries use getattrlist() and descriptor-bound fgetattrlist(), requesting ATTR_CMN_RETURNED_ATTRS | ATTR_CMN_EXTENDED_SECURITY, with FSOPT_NOFOLLOW | FSOPT_REPORT_FULLSIZE and WITHOUT FSOPT_PACK_INVAL_ATTRS. Buffer lengths, variable-reference bounds and returned-attribute validity are checked. For the existing directories of interest, both calls succeed but omit the ATTR_CMN_EXTENDED_SECURITY returned bit. Explicit populated and zero-entry fixture records do set the bit. APFS reports valid VOL_CAP_INT_EXTENDED_SECURITY support; we do not assume that volume capability proves per-object ACL availability. On macOS 27.0.1, build 26A434, using APFS, which supported interface and documented conditions allow software to distinguish an absent ACL from unavailable or unsupported ACL evidence when descriptor-bound attribute queries succeed but omit ATTR_CMN_EXTENDED_SECURITY and native ACL getters return ENOENT for an existing object? Please clarify: Whether ENOENT has a supported ACL-absence interpretation, and under exactly which checked conditions. Whether an omitted extended-security attribute can establish ACL absence, rather than unavailable or unsupported evidence. How explicit zero-entry ACLs differ from absent ACL records through supported interfaces. How KAUTH_FILESEC_NOACL should be interpreted through supported APIs. How genuine retrieval failures, including permission, I/O, allocation and unsupported-operation errors, must remain distinguishable. Whether a supported descriptor-bound verification method exists that preserves fail-closed security checks and object identity binding; please identify its guarantees and limitations regarding pathname/ancestor changes and later operations. Whether relevant behavior is specific to this macOS/APFS version. Please identify the applicable public documentation or supported verification sequence. We do not want to modify permissions, synthesize ACLs on target objects, treat invalid-attribute defaults as real evidence, or accept ambiguous omission/ENOENT as success. Existing ownership, mode and confinement checks must remain separate mandatory checks. If no public API can make this distinction reliably, please state that limitation.
2
0
280
1w
Durability of a directory entry after `rename()` on APFS — what is documented?
What we are building We maintain an append-only on-disk store. Every update has the same shape: write a temporary file and make its contents durable; rename() it to its final name; only then publish the new state to the rest of the system. Step 3 is the one we must get right. Once we publish, other components treat the preceding step as committed. If power is lost after we publish but the renamed entry was not yet durable, we would have published a state the filesystem can no longer support after reboot. Our question is therefore narrow: after rename() returns, what does Apple document about when the resulting directory entry may be treated as durable across power loss? Two cases matter, and we would like them distinguished wherever the answer differs: the target name did not exist before — an entry is added; the target name already existed and is replaced — an entry is replaced and an older link is removed. We are not asking you to review or endorse our protocol — only what the platform documents. What we have read, and where we stopped fsync(2) here causes "all modified data and attributes of fildes to be moved to a permanent storage device", then warns that after power loss an application "may find that only some or none of their data was written". fcntl(2) says of F_FULLFSYNC that "data that had been fsync'd on the same device before is guaranteed to be persisted when this call returns", and lists APFS as supported. rename(2) "guarantees that an instance of new will always exist, even if the system should crash in the middle of the operation". In what we read, we did not find a statement connecting a successful synchronisation call on a descriptor that refers to a directory with the durability of a name added, removed or replaced in that directory. We are not claiming no such statement exists — only that we did not find one, which is why we are asking. Three questions, independent of one another Q1 — How are these calls supported on a directory descriptor? On APFS, how are fsync(2) and fcntl(fd, F_FULLFSYNC) supported when fd refers to a directory (for example one obtained with O_DIRECTORY)? Please treat the two calls separately, since they carry different documented guarantees. "Supported", "not supported" and "not specified for this use" are all useful answers to us. Q2 — If such a call succeeds, what does it cover? If the call in Q1 returns successfully, which changes are guaranteed to have been completed — the directory's own attributes; the entries added, removed or replaced; related metadata? We are asking for the documented scope, not the implementation. Q3 — Is there a documented sequence an application can rely on? Is there a sequence of calls that Apple documents for an application that needs the name resulting from a rename() to survive power loss before it publishes its next state? If so, we would appreciate the reference, the conditions it depends on — filesystem, device, call ordering — and its stated limits. If there is no public commitment of this kind, we would rather be told so plainly, together with whatever level you are able to confirm, including "this is not currently specified" if that is the accurate answer. One distinction we do not want to get wrong rename(2) uses the word crash. We do not want to read a statement about crash behaviour as one about power loss, since the two can differ at the device layer. If a documented guarantee covers one and not the other, that distinction is exactly what we need. We also note the device-level caveat in the same manual page — certain drives "have also been known to ignore the request to flush their buffered data" — and we are not asking you to speak for any particular drive. Environment macOS 26.3, build 25D125, APFS — read on our own development machine and reported here as such; not independently verified by a third party. Deliberately outside this request A rename() between two different directories touches a source directory and a target directory. Whether a guarantee would have to cover both is tracked separately and is not asked here, so that an answer about one directory is not read as covering two. We have not fixed where the temporary file lives, and we are not asking you to choose that layout. Nor do we assume your answer is independent of it: if any of the above depends on whether the source and target directories are the same directory or two different ones, please say so explicitly. We would rather be told the answer is conditional than read an unconditional answer into it.
1
0
433
4w
APFS worse than HFS for SSD file enumeration
A user of my app reported that it is slower when enumerating a large number of files on APFS compared to HFS+. Online I can only find information that this is expected for rotational hard disks, but apparently APFS should be optimized for SSDs and hence the observed performance doesn't make sense. I used the code below to enumerate a folder hierarchy with about 100'000 files. I ran it several times on both APFS and HFS+ to minimize differences due to caching. On APFS the last runs took about 4.5 seconds, while on HFS+ the last runs took about 1.3 seconds. How can this big difference be explained? Is APFS really slower than HFS+ when enumerating files on SSDs? let openPanel = NSOpenPanel() openPanel.canChooseDirectories = true openPanel.canChooseFiles = false if openPanel.runModal() == .cancel { return } let resourceKeys: [URLResourceKey] = [.isDirectoryKey, .fileSizeKey, .creationDateKey, .contentModificationDateKey, .fileIdentifierKey, .isSymbolicLinkKey, .isHiddenKey, .isUserImmutableKey, .attributeModificationDateKey] let enumerator = FileManager.default.enumerator(at: openPanel.urls[0], includingPropertiesForKeys: resourceKeys) { url, error in print(error) return true }! let date = Date() var i = 0 for case let url as URL in enumerator { let _ = try? url.resourceValues(forKeys: Set(resourceKeys)) i += 1 if i % 10000 == 0 { print(i) } } print(-date.timeIntervalSinceNow)
0
0
238
Oct ’26
Is there any way to reconstruct a corrupted APFS root tree?
Hi everyone. I've been at this for about 9 hours already but I just needed to ask this somewhere where somebody with experience might pop up. As usual, I left my iPhone backing up its photos and videos to a Photos library in an APFS 1TB Western Digital HDD drive. Today I woke up with an error window saying that the drive is corrupted in some way. Here are the steps that followed: 1- Tried to mount the drive in Disk Utility -> doesn't work 2- Ran first aid in Disk Utility -> doesn't work 3- fsck_apfs with multiple different options in Terminal -> doesn't work 4- Used ddrescue to clone the corrupted hard drive to a 2TB drive -> worked fine with no unreadable/corrupt sectors. 5- I downloaded the WD Drive Utilities and the quick drive test passed -> no error. 6- Called Apple Support (shout out to Imelda for being incredibly nice and experienced) but it seems the only solution is to erase the drive or contact WD. This is not an option for me since it's got my photos library from the last decade. I had a backup in another drive but it's very out of date. I just bought a NAS to transfer it all to a safer place, so the timing for this to happen is the worst case. 7- I noticed that in the Library folder in my Mac, I got a 1.3GB Photos library with many thumbnails of the pictures I was importing last night. The filename is Syndication.photoslibrary. Here's the log from fsck_apfs fsck_apfs Log After all the steps I took, it seems to me that: A- The hard drive is completely fine hardware-wise, evidenced by points 4 and 5. So I would assume that WD can't really help me recover my data. B- The "only" thing that's broken is the apfs_root. So my question is if there is some sort of way to reconstruct the root tree somehow. I would assume that this structure is only partially broken and that there are addresses that it should point to properly, that can support some sort of more involved recovery process. I tried reading the APFS documentation but I'm currently very emotionally distressed at the potential loss of my data that I can't parse that information right now. Does anybody have any clue if something can be done about this? Some sort of script? Literally anything. Many thanks in advance. Best, Andres PS: Please let me know if this forum is the appropriate place for this question. I'm mostly posting here since I feel this is a more advanced subject and I need all the help I can get.
1
0
456
Aug ’26
SIGSTOP logd causes panic?
Hi, we're seeing a panic when we SIGSTOP the logd pid. panic(cpu 2 caller 0xfffffe0020e9a364): userspace watchdog timeout: no successful checkins from logd (0 induced crashes) in 120 seconds You may ask "well why would you do that?" and the answer is that we're seeing panics from watchdog/logd when we hammer the diskIO for a download/write (APFS sparse file creation) operation in our software. Is it normal to see this?
5
0
1k
Jul ’26
Matching between raw and APFS disk number
Hello, I have a raw device number, as an input, for external usb/thunderbolt device (i.e. for /dev/disk9 - it is 9). And I want to format it to APFS or read/confirm APFS FS type if it is already formatted. But I can see that APFS container/volume have another disk number (i.e /dev/disk10) in compare with for my raw disk. Is there a guaranteed way to match raw disk number to underlying APFS container/volume disk number? May be some API? Or just add +1 to raw disk number for getting APFS container/volume disk device number?
1
0
872
Jun ’26
Lock Contention in APFS/Kernel?
Hello! Some colleagues and work on Jujutsu, a version control system compatible with git, and I think we've uncovered a potential lock contention bug in either APFS or the Darwin kernel. There are four contributing factors to us thinking this is related to APFS or the Kernel: jj's testsuite uses nextest, a test runner for Rust that spawns each individual test as a separate process. The testsuite slowed down by a factor of ~5x on macOS after jj started using fsync. The slowdown increases as additional cores are allocated. A similar slowdown did not occur on ext4. Similar performance issues were reported in the past by a former Mercurial maintainer: https://gregoryszorc.com/blog/2018/10/29/global-kernel-locks-in-apfs/. My friend and colleague André has measured the test suite on an M3 Ultra with both a ramdisk and a traditional SSD and produced this graph: (The most thorough writeup is the discussion on this pull request.) I know I should file a feedback/bug report, but before I do, I'm struggling with profiling and finding kernel/APFS frames in my profiles so that I can properly attribute the cause of this apparent lock contention. Naively, I ran xctrace record --template 'Time Profiler' --output output.trace --launch /Users/dbarsky/.cargo/bin/cargo-nextest nextest run, and while that detected all processes spawned by nextest, it didn't record all processes as part of the same inspectable profile and didn't really show any frames from the kernel/APFS—I had to select individual processes. So I don't waste people's time and so that I can point a frame/smoking gun in the right system, how can I can use instruments to profile where the kernel and/or APFS are spending its time? Do I need to disable SIP?
9
1
2k
Jun ’26
Time Machine destination automatically converted to Case-Sensitive APFS in macOS Tahoe?
Mac: MacBook Pro 16-inch (Intel, 2019) macOS: Tahoe 26.5.1 I'm trying to determine whether this is expected behavior or a bug. Setup I purchased a new 2TB SSD to use exclusively for Time Machine. Before configuring Time Machine, I manually erased the SSD in Disk Utility and formatted it as: APFS (non-case-sensitive) Encrypted I specifically did not choose APFS (Case-sensitive). What happened After selecting the SSD as a Time Machine destination and allowing macOS to prepare the disk, I later checked the volume information and found: File System Personality: Case-sensitive APFS and: APFS Volume Disk (Role): Backup Name: Brad Mac Backups SSD (Case-sensitive) The volume appears to have been converted to a dedicated APFS Backup volume and is now reported as case-sensitive. Additional observations After backups complete: tmutil status reports: Running = 0 indicating Time Machine is no longer running. However, Spotlight processes (mds and mds_store) continue accessing the backup volume for many hours afterwards, preventing normal ejection of the SSD. Using: sudo lsof | grep "/Volumes/Brad Mac Backups SSD" shows Spotlight processes holding the drive open. Finder's "Force Eject" works successfully. Questions Is it expected behavior in macOS Tahoe for Time Machine to create a Case-sensitive APFS Backup volume, even when the destination was originally formatted as standard APFS? Has anyone else observed a Time Machine destination changing from APFS (non-case-sensitive) to APFS (Case-sensitive) during setup? Could the case-sensitive APFS format be related to Spotlight continuously indexing the backup volume and preventing normal ejection? Relevant Output diskutil info disk3s2 returns: File System Personality: Case-sensitive APFS and: diskutil apfs list shows: APFS Volume Disk (Role): Backup Name: Brad Mac Backups SSD (Case-sensitive) Mount Point: /Volumes/Brad Mac Backups SSD 1 Any insight would be appreciated, as Apple Support was unable to explain why the backup volume became case-sensitive.
0
0
518
Jun ’26
App cannot export from/import to file system anymore
Hi, a user of one of my apps running on his iPhone 15 with the latest iOS reports that he suddenly cannot import or export files anymore. My app allows to save and load databases from iCloud or locally on the iPhone. This is done using buttons on a main menu which are not reacting anymore for this user. He still can use buttons which trigger functions not requiring file access (like printing data from the database). So far, it is an isolated case (1 of about 500 users reporting this behaviour) but I cannot find an explanation. Has anybody ever seen something like this? Thanks for any ideas/help.
1
0
502
Jun ’26
open / libsystem_kernel.dylib slow on first run for any .img
We see a major delay for the first open("disk.img", O_RDONLY); we perform. If it helps, we use clonefile() to copy a sparsed image. if (-1 == (fd = open(path, (mode & O_ACCMODE) | O_CLOEXEC))) return -1; 1791 Thread_1071327 DispatchQueue_1: com.apple.main-thread (serial) 1791 start (in dyld) + 6076 [0x189f72b98] 1791 main (in anka_image) + 20 [0x102171bb8] 1791 clp_main (in libpolicy.dylib) + 2120 [0x102a49eac] 1790 process_info (in anka_image) + 68 [0x1021723f4] + 1790 vdsk_open (in libvdsk.dylib) + 92 [0x1021d90e8] + 1790 vdsk_open_native (in libvdsk.dylib) + 164 [0x1021d91c0] + 1790 open (in libsystem_kernel.dylib) + 64 [0x18a2dd6a4] + 1790 __open (in libsystem_kernel.dylib) + 8 [0x18a2d2678] What advice do you have for diagnosing what is causing the first open to do this? Is this some sort of security scan happening? Indexing?
7
0
953
May ’26
File Provider: case-insensitive collision check prevents mounting case-sensitive remote filesystems correctly
When a File Provider extension (NSFileProviderReplicatedExtension) mounts a Linux server via SFTP, remote directories containing files that differ only in case (e.g., "README" and "readme") are not represented correctly. The framework silently renames one file locally via the before-bounce mechanism, even though the extension reports both items with distinct identifiers and correct filenames. NSFileProviderActions.h states: "Collision checks should be case insensitive even if the filesystem or file provider might allow two coexisting filenames differing only by their case." This check runs in the framework before writing to disk. Placing the domain on a case-sensitive APFS volume via NSFileProviderDomain(displayName:userInfo:volumeURL:) does not help — the volume passes eligibility but the collision check still applies. This breaks any File Provider extension that mounts case-sensitive filesystems where case-variant filenames are common (especially git repositories). Is there any way to opt out of the case-insensitive collision check per domain? A supportsCaseSensitiveNames property on NSFileProviderDomain would solve this.
2
0
1k
Apr ’26
Kernel panic when using fclonefileat from ES
Hi, I am developing instant snapshot backup solution for macOS using Endpoint Security. We have stumbled upon a Kernel Panic when using "fclonefileat" API. We are catching a kernel panic on customer machines when attempting to clone the file during ES sync callback: panic(cpu 0 caller 0xfffffe002c495508): "apfs_io_lock_exclusive : Recursive exclusive lock attempt" @fs_utils.c:435 I have symbolized the backtrace to know it is related to clone operation with the following backtrace: apfs_io_lock_exclusive apfs_clone_internal apfs_vnop_clonefile I made a minimal repro that boils down to the following operations: apfs_crash_stress - launch thread to do rsrc writes static void *rsrc_write_worker(void *arg) { int id = (int)(long)arg; char buf[8192]; long n = 0; fill_pattern(buf, sizeof(buf), 'W' + id); while (n < ITERATION_LIMIT) { int file_idx = n % NUM_SOURCE_FILES; int fd = open(g_src_rsrc[file_idx], O_WRONLY | O_CREAT, 0644); if (fd >= 0) { off_t off = ((n * 4096) % RSRC_DATA_SIZE); pwrite(fd, buf, sizeof(buf), off); if ((n & 0x7) == 0) fsync(fd); close(fd); } else { setxattr(g_src[file_idx], "com.apple.ResourceFork", buf, sizeof(buf), 0, 0); } n++; } printf("[rsrc_wr_%d] done (%ld ops)\n", id, n); return NULL; } apfs_crash_es - simple ES client that is cloning the file (error checking omitted for brevity) static std::string volfsPath(uint64_t devId, uint64_t vnodeId) { return "/.vol/" + std::to_string(devId) + "/" + std::to_string(vnodeId); } static void cloneAndScheduleDelete(const std::string& sourcePath, dispatch_queue_t queue, uint64_t devId, uint64_t vnodeId) { struct stat st; if (stat(sourcePath.c_str(), &st) != 0 || !S_ISREG(st.st_mode)) return; int srcFd = open(sourcePath.c_str(), O_RDONLY); const char* cloneDir = "/Users/admin/Downloads/_clone"; mkdir(cloneDir, 0755); const char* filename = strrchr(sourcePath.c_str(), '/'); filename = filename ? filename + 1 : sourcePath.c_str(); std::string cloneFilename = std::string(filename) + ".clone." + std::to_string(time(nullptr)) + "." + std::to_string(getpid()); std::string clonePath = std::string(cloneDir) + "/" + cloneFilename; fclonefileat(srcFd, AT_FDCWD, clonePath.c_str(), 0); { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), queue, ^{ if (unlink(clonePath.c_str()) == 0) { LOG("Deleted clone: %s", clonePath.c_str()); } else { LOG("Failed to delete clone: %s", clonePath.c_str()); } }); } close(srcFd); } static const es_file_t* file(const es_message_t* msg) { switch (msg->event_type) { case ES_EVENT_TYPE_AUTH_OPEN: return msg->event.open.file; case ES_EVENT_TYPE_AUTH_EXEC: return msg->event.exec.target->executable; case ES_EVENT_TYPE_AUTH_RENAME: return msg->event.rename.source; } return nullptr; } int main(void) { es_client_t* cli; auto ret = es_new_client(&cli, ^(es_client_t* client, const es_message_t * msgc) { if (msgc->process->is_es_client) { es_mute_process(client, &msgc->process->audit_token); return respond(client, msgc, true); } dispatch_async(esQueue, ^{ bool shouldClone = false; if (msgc->event_type == ES_EVENT_TYPE_AUTH_OPEN) { auto& ev = msgc->event.open; if (ev.fflag & (FWRITE | O_RDWR | O_WRONLY | O_TRUNC | O_APPEND)) { shouldClone = true; } } else if (msgc->event_type == ES_EVENT_TYPE_AUTH_UNLINK || msgc->event_type == ES_EVENT_TYPE_AUTH_RENAME) { shouldClone = true; } if (shouldClone) { if (auto f = ::file(msgc)) cloneAndScheduleDelete(f->path.data, cloneQueue, f->stat.st_dev, f->stat.st_ino); } respond(client, msgc, true); }); }); LOG("es_new_client -> %d", ret); es_event_type_t events[] = { ES_EVENT_TYPE_AUTH_OPEN, ES_EVENT_TYPE_AUTH_EXEC, ES_EVENT_TYPE_AUTH_RENAME, ES_EVENT_TYPE_AUTH_UNLINK, }; es_subscribe(cli, events, sizeof(events) / sizeof(*events)); } Create 2 terminal sessions and run the following commands: % sudo ./apfs_crash_es % sudo ./apfs_crash_stress ~/Downloads/test/ Machine will very quickly panic due to APFS deadlock. I expect that no userspace syscall should be able to cause kernel panic. It looks like a bug in APFS implementation and requires fix on XNU/kext side. We were able to reproduce this issue on macOS 26.3.1/15.6.1 on Intel/ARM machines. Here is the panic string: panic_string.txt Source code without XCode project: apfs_crash_es.cpp apfs_crash_stress.cpp Full XCode project + full panic is available at https://www.icloud.com/iclouddrive/0f215KkZffPOTLpETPo-LdaXw#apfs%5Fcrash%5Fes
5
0
1.1k
Apr ’26
System-wide deadlock in removexattr from revisiond / APFS
System-wide deadlock in removexattr from revisiond / APFS We're experiencing a deadlock on certains systems when our software is installed, which is causing side effects in our process (and likely others) such as blocked queues and increased memory usage. According to the spindump, revisiond appears to be holding an exclusive lock within the kernel. Process: revisiond [426] UUID: 5E9B9E04-984B-31AD-A4FF-A1A90B7D53A1 Path: /System/Library/PrivateFrameworks/GenerationalStorage.framework/Versions/A/Support/revisiond Codesigning ID: com.apple.revisiond Shared Cache: 25AE5A2A-FE2A-3998-8D4E-F3C5C6E6CEB6 slid base address 0x189834000, slide 0x9834000 (System Primary) Architecture: arm64e Parent: launchd [1] UID: 0 Sudden Term: Tracked Memory Limit: 50MB Jetsam Priority: 40 Footprint: 6225 KB Time Since Fork: 1740319s Num samples: 940 (1-940) Num threads: 5 Note: 1 idle work queue thread omitted [...] Thread 0xc0616d 940 samples (1-940) priority 46 (base 4) last ran 241692.754s ago 940 start_wqthread + 8 (libsystem_pthread.dylib + 7068) [0x189d0ab9c] 940 _pthread_wqthread + 292 (libsystem_pthread.dylib + 11852) [0x189d0be4c] 940 _dispatch_workloop_worker_thread + 692 (libdispatch.dylib + 85356) [0x189b65d6c] 940 _dispatch_root_queue_drain_deferred_wlh + 292 (libdispatch.dylib + 87156) [0x189b66474] 940 _dispatch_lane_invoke + 440 (libdispatch.dylib + 45048) [0x189b5bff8] 940 _dispatch_lane_serial_drain + 944 (libdispatch.dylib + 42420) [0x189b5b5b4] 940 _dispatch_client_callout + 16 (libdispatch.dylib + 113364) [0x189b6cad4] 940 _dispatch_call_block_and_release + 32 (libdispatch.dylib + 7004) [0x189b52b5c] 940 ??? (revisiond + 168768) [0x10494d340] 940 ??? (revisiond + 165940) [0x10494c834] 940 ??? (revisiond + 40264) [0x10492dd48] 940 ??? (revisiond + 56680) [0x104931d68] 940 <patched truncated backtrace> 940 removexattr + 8 (libsystem_kernel.dylib + 23768) [0x189cd1cd8] *940 ??? (kernel.release.t6000 + 15240) [0xfffffe000886fb88] *940 ??? (kernel.release.t6000 + 1886348) [0xfffffe0008a3888c] *940 ??? (kernel.release.t6000 + 7730436) [0xfffffe0008fcb504] *940 ??? (kernel.release.t6000 + 2759592) [0xfffffe0008b0dba8] *940 ??? (kernel.release.t6000 + 2808244) [0xfffffe0008b199b4] *940 apfs_vnop_removexattr + 1044 (apfs + 474512) [0xfffffe000be8d4d0] *940 decmpfs_cnode_set_vnode_state + 80 (kernel.release.t6000 + 2945816) [0xfffffe0008b3b318] *940 IORWLockWrite + 184 (kernel.release.t6000 + 496184) [0xfffffe00088e5238] *940 ??? (kernel.release.t6000 + 494624) [0xfffffe00088e4c20] *940 ??? (kernel.release.t6000 + 619452) [0xfffffe00089033bc] *940 ??? (kernel.release.t6000 + 624472) [0xfffffe0008904758] The bulk of the other processes are waiting for that lock. (suspended, blocked by krwlock for reading owned by revisiond [426] thread 0xc0616d) (blocked by krwlock for writing owned by revisiond [426] thread 0xc0616d) Around the time of the event, these messages were logged by revision: 2026-03-06 18:49:37.781673-0500 0x16b7 Error 0x7f92f364 426 14 revisiond: [com.apple.revisiond:default] [ERROR] CSCopyChunkIDsForToken failed for 41639 2026-03-06 18:49:37.781716-0500 0x16b7 Error 0x7f92f365 426 14 revisiond: [com.apple.revisiond:default] [ERROR] updateEntry for new entry <private> failed 2026-03-06 18:49:37.781738-0500 0x16b7 Error 0x7f92f366 426 14 revisiond: [com.apple.revisiond:default] [ERROR] no entry for '<private>' 2026-03-06 18:49:37.781754-0500 0x16b7 Error 0x7f92f367 426 14 revisiond: [com.apple.revisiond:default] [ERROR] failed assembleInfoForOffset for fsid 16777234 fileid 359684022 offset 0 size 14334 (path <private>) Our agent uses Endpoint Security Framework to monitor events, and provide anti-tamper functionality for installed components and processes. While several EndpointSecurity calls appear in the spindump stack traces, we don't have any evidence that any calls from revisiond were blocked. What we'd really like to to understand what that lock is (appears to be decompressing an object on an APFS volume), what revisiond and APFS are doing with it, and what might cause it to deadlock. Of note, one of our processes is also waiting on that lock, one thread for reading and the other for writing. This issue affects machines running several macOS versions (15.x, 26.x). The machine in the examples is running macOS 26.3 (25D125)
20
0
1.9k
Apr ’26
How can a macOS application establish that an open APFS file has no extended ACL?
On macOS 26.5.2 (build 25F84), which documented API and return conditions, if any, establish that a regular file on APFS has no extended access control list (ACL), using an already-open file descriptor? We tested three disposable regular files on an APFS volume reporting ACL support. For each file, we opened a read-only file descriptor and called: acl_get_fd_np(fd, ACL_TYPE_EXTENDED) fgetattrlist() requesting ATTR_CMN_RETURNED_ATTRS | ATTR_CMN_EXTENDED_SECURITY Before and after inspection, fstat() confirmed stable device, inode, mode, and change timestamp. Observed results: 1. Newly created file, no ACL explicitly assigned acl_get_fd_np() returned NULL with errno == ENOENT. fgetattrlist() succeeded but omitted ATTR_CMN_EXTENDED_SECURITY from the returned attribute mask. FSOPT_PACK_INVAL_ATTRS also left that bit clear. 2. File with an explicitly assigned empty ACL acl_get_fd_np() returned NULL with errno == ENOENT. fgetattrlist() returned the extended-security attribute with an ACL entry count of zero. 3. File with one explicit ACL entry acl_get_fd_np() returned a non-null ACL. fgetattrlist() returned the extended-security attribute with an ACL entry count of one. Apple's published XNU attribute-packing implementation appears to use the same omission branch when ACL metadata is unsupported or when the ACL pointer is null. My question: Is there a supported descriptor-based API sequence that reliably distinguishes: Genuine absence of an extended ACL Unavailable or unsupported per-file ACL metadata An ACL retrieval failure If so, which API, capability checks, return values, attribute bits, or error conditions should a caller rely on? Are there relevant APFS or macOS version limitations? If the public API cannot establish ACL absence unambiguously in this situation, confirmation of that limitation would also be helpful. Thank you for your guidance.
Replies
0
Boosts
0
Views
15
Activity
1h
Requesting com.apple.developer.vfs.snapshot for a Developer ID backup app (Team LM3P28DNVQ)
Hello, I am Ahmed Hamade, founder of Pixel Ventures LLC, Apple Developer Program Team ID LM3P28DNVQ. I am asking Apple to grant the restricted entitlement com.apple.developer.vfs.snapshot to our team for a macOS backup application named PixelProtect. If this is not the right channel, please tell me where to send the request. PixelProtect backs up a whole Mac volume. It keeps one primary backup set on a local disk and a replica of that same set in cloud storage, protects both copies against deletion, and supports recovery. We built it for people whose AI coding agents can delete data. We need snapshots for three reasons. First, files change while a backup runs, so the backup must read from one point in time to copy a consistent state. Second, snapshots let us keep local restore points without copying the data again. Third, Time Machine takes local snapshots for the same purpose. The only alternative today is tmutil localsnapshot, whose snapshots the system manages and ages out, so we could not keep restore points of our own. We would use fs_snapshot_create, fs_snapshot_list, fs_snapshot_delete and fs_snapshot_mount. We do not use fs_snapshot_revert. Restores copy files out of a mounted snapshot. Only our privileged helper calls these functions. It runs as root, is registered with SMAppService, and is packaged as an app-like bundle (planned App ID ai.pixelventures.pixelprotect.daemon) so it can embed a provisioning profile. The main app (ai.pixelventures.pixelprotect) and our command line tool send requests to the helper and do not call these functions. We limit use as follows. Snapshots are created only on volumes the user chose to back up. The user controls how long snapshots are kept. The helper deletes only snapshots it created, which carry our own name prefix, and only under the user's retention rules or an action the user confirms. PixelProtect is signed with our Developer ID Application certificate, uses the hardened runtime, is notarized, and is distributed outside the Mac App Store to Pixel Ventures clients. It is not sandboxed, because a whole-volume backup reads the whole volume. It has no public marketing page yet, so a product description is attached. Please enable the entitlement for Team ID LM3P28DNVQ for development and for Developer ID distribution, or tell me what further information you need. I tried the code-level support request form and it requires a sample project, so I am asking here as the form suggested Thank you, Ahmed Hamade Founder, Pixel Ventures LLC Team ID LM3P28DNVQ I tried the code-level support request form and it requires a sample project, so I am asking here as the form suggested
Replies
3
Boosts
0
Views
54
Activity
13h
macOS APFS: NSFileCoordinator snapshot consistency and renameatx_np durability guarantees
Reference environment: macOS 26.7.1, build 25G241, arm64, local APFS. Consistent capture of a source file We are evaluating NSFileCoordinator with the forUploading and withoutChanges options for a single regular file. Does the resulting snapshot guarantee byte contents corresponding to a single point in time, even if another process writes during capture without file coordination, using write/pwrite or a shared writable memory mapping? We need to establish the scope, conditions, and limitations of this guarantee. We do not require capturing an editor’s unsaved changes or application-level database consistency. If any of these concurrent writing methods are not covered, please identify them explicitly. Durability of the final filename after a rename We are evaluating the following sequence: a verified temporary file has successfully completed strong synchronization, and is then renamed using renameatx_np with RENAME_EXCL. The temporary and final names are in the same directory on the same volume. Next, fsync_volume_np is called with SYNC_VOLUME_FULLSYNC and SYNC_VOLUME_WAIT. Under what conditions does a successful return confirm that the final filename and its association with the prepared file contents will survive a system crash or power loss? We also need clarification on whether all relevant data and metadata write errors are propagated to the caller, or whether an earlier error might remain unreported by this operation. Please provide the documented scope and limitations for this environment.
Replies
0
Boosts
0
Views
131
Activity
6d
macOS 15.7.9/APFS: How to diagnose slow SQLite quick_check with pread-heavy samples?
I am seeking advice about supported macOS performance tracing, NOT reporting a confirmed APFS bug. This is a real application failure. AI assisted with organizing this report, and the measurements were reviewed against existing records. Environment Apple Silicon Mac Studio, 32 GB RAM, macOS 15.7.9 (24G830). CPython 3.11.15, linked SQLite 3.50.4. SQLite database: 3,224,576,000 bytes on an internal APFS volume, journal_mode=DELETE. The application runs PRAGMA quick_check before starting worker processes. A progress handler cancels the operation after 30 seconds, producing SQLITE_INTERRUPT. This is application-triggered, not proof of corruption. Observed results Original database: 30.008 s wall / 5.220 s CPU; a separate run took 30.192 s wall / 5.420 s CPU. Both were interrupted. A two-second sample showed 95/96 samples on SQLite's checkTreePage → readDbPage → unixRead → pread path. Individual pread latency was not measured. A transaction-consistent SQLite Backup API snapshot on a different APFS volume completed quick_check in 2.412 s and integrity_check in 8.797 s, both returning "ok". The snapshot and original were checked at different times with uncontrolled cache and system-load conditions. Additional mmap experiment On the same offline snapshot: A: mmap_size=0, executed first, quick_check took 31.070 s and was interrupted. B: reported mmap limit approximately 2 GiB, executed second, quick_check returned "ok" after 22.146 s. Cache conditions and host load were not equivalent, so these observations do NOT establish an mmap performance improvement. A separate deliberate mapped-I/O error test ended with SIGBUS in an isolated child process. This does not establish an ordinary APFS defect. Questions Which supported macOS Instruments templates or APIs can correlate pread offsets, sizes and timings with physical disk latency, filesystem cache activity, memory pressure and thread scheduling, without disabling system security protections? What minimum set of simultaneous observations could distinguish cache misses, APFS metadata/layout overhead, physical device delays and CPU scheduling contention? How should process read-byte counts be interpreted against physical disk I/O? How should I safely compare read-only SQLite mmap against normal pread access on disposable copies, without mistaking a warmer second run for a performance gain? What SIGBUS containment and recovery checks would be appropriate? I am primarily looking for a reliable instrumentation plan and interpretation criteria before conducting further tests. I do not want to modify the original database, weaken integrity checks or bypass security controls.
Replies
1
Boosts
0
Views
130
Activity
1w
Supported safe-save contract for a sandboxed AIFF editor on APFS
We are evaluating a separately App-Sandboxed GUI helper for one explicitly reviewed AIFF NAME edit on internal-disk APFS. The main app retains user-selected read-only access. The helper has only App Sandbox and user-selected read/write entitlements. We would like the supported API and failure/reconciliation contract before implementing physical-file edits. Bounded observation A local synthetic-fixture probe used macOS 27.2 (26B118), SDK 27.0, arm64, ad-hoc signing with Hardened Runtime, LaunchServices and the helper's own NSOpenPanel. Captured stat fields, raw xattrs and bytes were unchanged after selection and an O_RDONLY read. Across a later O_RDWR open/fstat/close gate, com.apple.quarantine was added and ctime changed; bytes stayed identical and close returned 0. There was no content-write call. This describes one observed build/run, not a general OS mechanism. We have not tested copyfile, clonefile or replacement paths. Questions Existing-file conflicts. We read the later DTS explanation in thread 850377 about path-based link/rename substitution limits. Our use case is an ordinary editor replacing an existing user-selected file while another uncoordinated app might edit or replace it. What supported pattern and limits should we use to avoid silently overwriting unrelated updates, detect conflicts and retain truthful indeterminate outcomes? Is any supported replacement operation conditional on the previously reviewed destination object/content version, or should that guarantee be treated as unavailable under this concurrency model? We do not assume a post-operation identity check prevents an earlier effect. Protected metadata. What preservation contract should this sandboxed helper rely on for quarantine/provenance, ACLs and unrelated xattrs through copy/clone, a native-field edit and replacement? The current copyfile/clonefile manuals describe metadata copying and exceptions, while FileManager replacement documents selected original metadata. If exact raw quarantine equality is not the supported invariant, which public properties or behaviors should verification check, including originally absent quarantine? We want to retain Apple's security semantics without stripping quarantine, normalizing undocumented flags or disabling App Sandbox. Replacement access. After selecting an existing file in NSOpenPanel, is FileManager's itemReplacementDirectory plus replaceItemAt a supported safe-save route under that file selection? What additional consent, if any, is required for temporary-file creation and namespace publication? We do not assume parent-directory access or propose adding selected-source write rights to the main app. Relevant references: FileManager replacement File coordination No user media, paths, saved grants, private logs or binaries are attached. We are seeking supported semantics and refusal boundaries before further implementation or experiments.
Replies
0
Boosts
0
Views
107
Activity
1w
macOS/APFS: Is there a supported way to create a hard link from an open file descriptor without pathname substitution?
We are developing a security-sensitive local execution system on macOS and need clarification about supported Darwin/APFS filesystem APIs. Our requirement is to create an additional directory entry (hard link) for an existing, authorized regular-file object while retaining its original directory entry. SECURITY REQUIREMENTS The source file has already been opened and its identity verified using a held file descriptor and fstat(). The source must remain the exact same filesystem object (device/inode identity), not a copy or clone. An attacker operating under the same user account may concurrently rename, unlink, or replace the source pathname. The publication operation must not create a hard link to, or otherwise mutate, a substituted source object. The new link must be created within an already-open, authorized destination directory. Unsupported configurations must be detectable before attempting a potentially unsafe publication mutation. The original source directory entry must remain present. We have reviewed linkat(), fclonefileat(), rename-based approaches, filesystem flags, and directory-descriptor-relative operations. The difficulty is that linkat() identifies its source through a pathname. Holding a verified source file descriptor does not appear to guarantee that the pathname still identifies the same object when linkat() performs the mutation. A subsequent fstat() or pathname identity check cannot undo an already-created link to a substituted object. QUESTIONS Does macOS provide a supported public API that creates an additional hard link directly from an existing open file descriptor, without resolving a replaceable source pathname? Does Darwin support an equivalent of Linux linkat() with AT_EMPTY_PATH, or another documented descriptor-based source-linking mechanism? Can any supported macOS filesystem API guarantee that a concurrent same-user replacement of the source directory entry cannot redirect the publication mutation? If descriptor-based hard linking is unavailable, is there a supported filesystem or namespace protection mechanism that prevents same-owner source-entry substitution throughout the operation? Do AT_SYMLINK_FOLLOW, AT_SYMLINK_NOFOLLOW, AT_RESOLVE_BENEATH, AT_RESOLVE_NOFOLLOW_ANY, or related Darwin flags provide any guarantee that the linked source is the previously verified inode rather than a replacement? Are the relevant guarantees dependent on macOS version, APFS volume configuration, filesystem flags, privileges, or entitlements? Is there a supported way to determine whether the required operation and guarantees are available before performing the publication mutation? We are specifically interested in documented and supported APIs, their identity guarantees, availability conditions, and limitations. We are not seeking a workaround based solely on comparing file identities after the operation, copying/cloning the file, or assuming that same-user pathname replacement cannot occur. If no supported public API provides these guarantees, confirmation of that limitation would also be helpful. Thank you.
Replies
5
Boosts
0
Views
281
Activity
1w
macOS 27/APFS: Supported ACL Absence Verification When acl_get_fd_np Returns ENOENT
Subject: Supported fail-closed ACL absence verification on macOS 27.0.1 / APFS Environment: macOS 27.0.1, build 26A434; APFS; installed macOS 27.0 SDK. We need a supported, documented way to determine whether an existing filesystem object has no effective ACL entries, while rejecting genuine retrieval failures and unsupported or unavailable ACL evidence. We are seeking clarification of the public interface contract, not alleging an Apple defect. For existing directory and regular-file fixtures, pathname metadata and descriptor metadata identify the same object. Errno is cleared immediately before each native call and captured immediately afterward. ACL retrieval uses ACL_TYPE_EXTENDED: acl_get_file(path, ACL_TYPE_EXTENDED) acl_get_fd_np(fd, ACL_TYPE_EXTENDED) On fresh objects, both return NULL with ENOENT. Explicit one-entry fixture ACLs are retrieved successfully. Explicit zero-entry fixture ACLs can also yield NULL/ENOENT, while attribute queries return a serialized zero-entry ACL. The attribute queries use getattrlist() and descriptor-bound fgetattrlist(), requesting ATTR_CMN_RETURNED_ATTRS | ATTR_CMN_EXTENDED_SECURITY, with FSOPT_NOFOLLOW | FSOPT_REPORT_FULLSIZE and WITHOUT FSOPT_PACK_INVAL_ATTRS. Buffer lengths, variable-reference bounds and returned-attribute validity are checked. For the existing directories of interest, both calls succeed but omit the ATTR_CMN_EXTENDED_SECURITY returned bit. Explicit populated and zero-entry fixture records do set the bit. APFS reports valid VOL_CAP_INT_EXTENDED_SECURITY support; we do not assume that volume capability proves per-object ACL availability. On macOS 27.0.1, build 26A434, using APFS, which supported interface and documented conditions allow software to distinguish an absent ACL from unavailable or unsupported ACL evidence when descriptor-bound attribute queries succeed but omit ATTR_CMN_EXTENDED_SECURITY and native ACL getters return ENOENT for an existing object? Please clarify: Whether ENOENT has a supported ACL-absence interpretation, and under exactly which checked conditions. Whether an omitted extended-security attribute can establish ACL absence, rather than unavailable or unsupported evidence. How explicit zero-entry ACLs differ from absent ACL records through supported interfaces. How KAUTH_FILESEC_NOACL should be interpreted through supported APIs. How genuine retrieval failures, including permission, I/O, allocation and unsupported-operation errors, must remain distinguishable. Whether a supported descriptor-bound verification method exists that preserves fail-closed security checks and object identity binding; please identify its guarantees and limitations regarding pathname/ancestor changes and later operations. Whether relevant behavior is specific to this macOS/APFS version. Please identify the applicable public documentation or supported verification sequence. We do not want to modify permissions, synthesize ACLs on target objects, treat invalid-attribute defaults as real evidence, or accept ambiguous omission/ENOENT as success. Existing ownership, mode and confinement checks must remain separate mandatory checks. If no public API can make this distinction reliably, please state that limitation.
Replies
2
Boosts
0
Views
280
Activity
1w
Durability of a directory entry after `rename()` on APFS — what is documented?
What we are building We maintain an append-only on-disk store. Every update has the same shape: write a temporary file and make its contents durable; rename() it to its final name; only then publish the new state to the rest of the system. Step 3 is the one we must get right. Once we publish, other components treat the preceding step as committed. If power is lost after we publish but the renamed entry was not yet durable, we would have published a state the filesystem can no longer support after reboot. Our question is therefore narrow: after rename() returns, what does Apple document about when the resulting directory entry may be treated as durable across power loss? Two cases matter, and we would like them distinguished wherever the answer differs: the target name did not exist before — an entry is added; the target name already existed and is replaced — an entry is replaced and an older link is removed. We are not asking you to review or endorse our protocol — only what the platform documents. What we have read, and where we stopped fsync(2) here causes "all modified data and attributes of fildes to be moved to a permanent storage device", then warns that after power loss an application "may find that only some or none of their data was written". fcntl(2) says of F_FULLFSYNC that "data that had been fsync'd on the same device before is guaranteed to be persisted when this call returns", and lists APFS as supported. rename(2) "guarantees that an instance of new will always exist, even if the system should crash in the middle of the operation". In what we read, we did not find a statement connecting a successful synchronisation call on a descriptor that refers to a directory with the durability of a name added, removed or replaced in that directory. We are not claiming no such statement exists — only that we did not find one, which is why we are asking. Three questions, independent of one another Q1 — How are these calls supported on a directory descriptor? On APFS, how are fsync(2) and fcntl(fd, F_FULLFSYNC) supported when fd refers to a directory (for example one obtained with O_DIRECTORY)? Please treat the two calls separately, since they carry different documented guarantees. "Supported", "not supported" and "not specified for this use" are all useful answers to us. Q2 — If such a call succeeds, what does it cover? If the call in Q1 returns successfully, which changes are guaranteed to have been completed — the directory's own attributes; the entries added, removed or replaced; related metadata? We are asking for the documented scope, not the implementation. Q3 — Is there a documented sequence an application can rely on? Is there a sequence of calls that Apple documents for an application that needs the name resulting from a rename() to survive power loss before it publishes its next state? If so, we would appreciate the reference, the conditions it depends on — filesystem, device, call ordering — and its stated limits. If there is no public commitment of this kind, we would rather be told so plainly, together with whatever level you are able to confirm, including "this is not currently specified" if that is the accurate answer. One distinction we do not want to get wrong rename(2) uses the word crash. We do not want to read a statement about crash behaviour as one about power loss, since the two can differ at the device layer. If a documented guarantee covers one and not the other, that distinction is exactly what we need. We also note the device-level caveat in the same manual page — certain drives "have also been known to ignore the request to flush their buffered data" — and we are not asking you to speak for any particular drive. Environment macOS 26.3, build 25D125, APFS — read on our own development machine and reported here as such; not independently verified by a third party. Deliberately outside this request A rename() between two different directories touches a source directory and a target directory. Whether a guarantee would have to cover both is tracked separately and is not asked here, so that an answer about one directory is not read as covering two. We have not fixed where the temporary file lives, and we are not asking you to choose that layout. Nor do we assume your answer is independent of it: if any of the above depends on whether the source and target directories are the same directory or two different ones, please say so explicitly. We would rather be told the answer is conditional than read an unconditional answer into it.
Replies
1
Boosts
0
Views
433
Activity
4w
APFS worse than HFS for SSD file enumeration
A user of my app reported that it is slower when enumerating a large number of files on APFS compared to HFS+. Online I can only find information that this is expected for rotational hard disks, but apparently APFS should be optimized for SSDs and hence the observed performance doesn't make sense. I used the code below to enumerate a folder hierarchy with about 100'000 files. I ran it several times on both APFS and HFS+ to minimize differences due to caching. On APFS the last runs took about 4.5 seconds, while on HFS+ the last runs took about 1.3 seconds. How can this big difference be explained? Is APFS really slower than HFS+ when enumerating files on SSDs? let openPanel = NSOpenPanel() openPanel.canChooseDirectories = true openPanel.canChooseFiles = false if openPanel.runModal() == .cancel { return } let resourceKeys: [URLResourceKey] = [.isDirectoryKey, .fileSizeKey, .creationDateKey, .contentModificationDateKey, .fileIdentifierKey, .isSymbolicLinkKey, .isHiddenKey, .isUserImmutableKey, .attributeModificationDateKey] let enumerator = FileManager.default.enumerator(at: openPanel.urls[0], includingPropertiesForKeys: resourceKeys) { url, error in print(error) return true }! let date = Date() var i = 0 for case let url as URL in enumerator { let _ = try? url.resourceValues(forKeys: Set(resourceKeys)) i += 1 if i % 10000 == 0 { print(i) } } print(-date.timeIntervalSinceNow)
Replies
0
Boosts
0
Views
238
Activity
Oct ’26
Is there any way to reconstruct a corrupted APFS root tree?
Hi everyone. I've been at this for about 9 hours already but I just needed to ask this somewhere where somebody with experience might pop up. As usual, I left my iPhone backing up its photos and videos to a Photos library in an APFS 1TB Western Digital HDD drive. Today I woke up with an error window saying that the drive is corrupted in some way. Here are the steps that followed: 1- Tried to mount the drive in Disk Utility -> doesn't work 2- Ran first aid in Disk Utility -> doesn't work 3- fsck_apfs with multiple different options in Terminal -> doesn't work 4- Used ddrescue to clone the corrupted hard drive to a 2TB drive -> worked fine with no unreadable/corrupt sectors. 5- I downloaded the WD Drive Utilities and the quick drive test passed -> no error. 6- Called Apple Support (shout out to Imelda for being incredibly nice and experienced) but it seems the only solution is to erase the drive or contact WD. This is not an option for me since it's got my photos library from the last decade. I had a backup in another drive but it's very out of date. I just bought a NAS to transfer it all to a safer place, so the timing for this to happen is the worst case. 7- I noticed that in the Library folder in my Mac, I got a 1.3GB Photos library with many thumbnails of the pictures I was importing last night. The filename is Syndication.photoslibrary. Here's the log from fsck_apfs fsck_apfs Log After all the steps I took, it seems to me that: A- The hard drive is completely fine hardware-wise, evidenced by points 4 and 5. So I would assume that WD can't really help me recover my data. B- The "only" thing that's broken is the apfs_root. So my question is if there is some sort of way to reconstruct the root tree somehow. I would assume that this structure is only partially broken and that there are addresses that it should point to properly, that can support some sort of more involved recovery process. I tried reading the APFS documentation but I'm currently very emotionally distressed at the potential loss of my data that I can't parse that information right now. Does anybody have any clue if something can be done about this? Some sort of script? Literally anything. Many thanks in advance. Best, Andres PS: Please let me know if this forum is the appropriate place for this question. I'm mostly posting here since I feel this is a more advanced subject and I need all the help I can get.
Replies
1
Boosts
0
Views
456
Activity
Aug ’26
SIGSTOP logd causes panic?
Hi, we're seeing a panic when we SIGSTOP the logd pid. panic(cpu 2 caller 0xfffffe0020e9a364): userspace watchdog timeout: no successful checkins from logd (0 induced crashes) in 120 seconds You may ask "well why would you do that?" and the answer is that we're seeing panics from watchdog/logd when we hammer the diskIO for a download/write (APFS sparse file creation) operation in our software. Is it normal to see this?
Replies
5
Boosts
0
Views
1k
Activity
Jul ’26
Is it possible to clone data into existing files?
macOS has the clonefile*() calls to create a new file that's a clone of an existing file, but is it possible to clone only parts of an existing file into a different existing file? Linux (FICLONERANGE) and Windows (FSCTL_DUPLICATE_EXTENTS_TO_FILE) both provide this functionality. I previously filed FB12737014 with this request.
Replies
7
Boosts
0
Views
1.1k
Activity
Jul ’26
Matching between raw and APFS disk number
Hello, I have a raw device number, as an input, for external usb/thunderbolt device (i.e. for /dev/disk9 - it is 9). And I want to format it to APFS or read/confirm APFS FS type if it is already formatted. But I can see that APFS container/volume have another disk number (i.e /dev/disk10) in compare with for my raw disk. Is there a guaranteed way to match raw disk number to underlying APFS container/volume disk number? May be some API? Or just add +1 to raw disk number for getting APFS container/volume disk device number?
Replies
1
Boosts
0
Views
872
Activity
Jun ’26
Lock Contention in APFS/Kernel?
Hello! Some colleagues and work on Jujutsu, a version control system compatible with git, and I think we've uncovered a potential lock contention bug in either APFS or the Darwin kernel. There are four contributing factors to us thinking this is related to APFS or the Kernel: jj's testsuite uses nextest, a test runner for Rust that spawns each individual test as a separate process. The testsuite slowed down by a factor of ~5x on macOS after jj started using fsync. The slowdown increases as additional cores are allocated. A similar slowdown did not occur on ext4. Similar performance issues were reported in the past by a former Mercurial maintainer: https://gregoryszorc.com/blog/2018/10/29/global-kernel-locks-in-apfs/. My friend and colleague André has measured the test suite on an M3 Ultra with both a ramdisk and a traditional SSD and produced this graph: (The most thorough writeup is the discussion on this pull request.) I know I should file a feedback/bug report, but before I do, I'm struggling with profiling and finding kernel/APFS frames in my profiles so that I can properly attribute the cause of this apparent lock contention. Naively, I ran xctrace record --template 'Time Profiler' --output output.trace --launch /Users/dbarsky/.cargo/bin/cargo-nextest nextest run, and while that detected all processes spawned by nextest, it didn't record all processes as part of the same inspectable profile and didn't really show any frames from the kernel/APFS—I had to select individual processes. So I don't waste people's time and so that I can point a frame/smoking gun in the right system, how can I can use instruments to profile where the kernel and/or APFS are spending its time? Do I need to disable SIP?
Replies
9
Boosts
1
Views
2k
Activity
Jun ’26
Time Machine destination automatically converted to Case-Sensitive APFS in macOS Tahoe?
Mac: MacBook Pro 16-inch (Intel, 2019) macOS: Tahoe 26.5.1 I'm trying to determine whether this is expected behavior or a bug. Setup I purchased a new 2TB SSD to use exclusively for Time Machine. Before configuring Time Machine, I manually erased the SSD in Disk Utility and formatted it as: APFS (non-case-sensitive) Encrypted I specifically did not choose APFS (Case-sensitive). What happened After selecting the SSD as a Time Machine destination and allowing macOS to prepare the disk, I later checked the volume information and found: File System Personality: Case-sensitive APFS and: APFS Volume Disk (Role): Backup Name: Brad Mac Backups SSD (Case-sensitive) The volume appears to have been converted to a dedicated APFS Backup volume and is now reported as case-sensitive. Additional observations After backups complete: tmutil status reports: Running = 0 indicating Time Machine is no longer running. However, Spotlight processes (mds and mds_store) continue accessing the backup volume for many hours afterwards, preventing normal ejection of the SSD. Using: sudo lsof | grep "/Volumes/Brad Mac Backups SSD" shows Spotlight processes holding the drive open. Finder's "Force Eject" works successfully. Questions Is it expected behavior in macOS Tahoe for Time Machine to create a Case-sensitive APFS Backup volume, even when the destination was originally formatted as standard APFS? Has anyone else observed a Time Machine destination changing from APFS (non-case-sensitive) to APFS (Case-sensitive) during setup? Could the case-sensitive APFS format be related to Spotlight continuously indexing the backup volume and preventing normal ejection? Relevant Output diskutil info disk3s2 returns: File System Personality: Case-sensitive APFS and: diskutil apfs list shows: APFS Volume Disk (Role): Backup Name: Brad Mac Backups SSD (Case-sensitive) Mount Point: /Volumes/Brad Mac Backups SSD 1 Any insight would be appreciated, as Apple Support was unable to explain why the backup volume became case-sensitive.
Replies
0
Boosts
0
Views
518
Activity
Jun ’26
App cannot export from/import to file system anymore
Hi, a user of one of my apps running on his iPhone 15 with the latest iOS reports that he suddenly cannot import or export files anymore. My app allows to save and load databases from iCloud or locally on the iPhone. This is done using buttons on a main menu which are not reacting anymore for this user. He still can use buttons which trigger functions not requiring file access (like printing data from the database). So far, it is an isolated case (1 of about 500 users reporting this behaviour) but I cannot find an explanation. Has anybody ever seen something like this? Thanks for any ideas/help.
Replies
1
Boosts
0
Views
502
Activity
Jun ’26
open / libsystem_kernel.dylib slow on first run for any .img
We see a major delay for the first open("disk.img", O_RDONLY); we perform. If it helps, we use clonefile() to copy a sparsed image. if (-1 == (fd = open(path, (mode & O_ACCMODE) | O_CLOEXEC))) return -1; 1791 Thread_1071327 DispatchQueue_1: com.apple.main-thread (serial) 1791 start (in dyld) + 6076 [0x189f72b98] 1791 main (in anka_image) + 20 [0x102171bb8] 1791 clp_main (in libpolicy.dylib) + 2120 [0x102a49eac] 1790 process_info (in anka_image) + 68 [0x1021723f4] + 1790 vdsk_open (in libvdsk.dylib) + 92 [0x1021d90e8] + 1790 vdsk_open_native (in libvdsk.dylib) + 164 [0x1021d91c0] + 1790 open (in libsystem_kernel.dylib) + 64 [0x18a2dd6a4] + 1790 __open (in libsystem_kernel.dylib) + 8 [0x18a2d2678] What advice do you have for diagnosing what is causing the first open to do this? Is this some sort of security scan happening? Indexing?
Replies
7
Boosts
0
Views
953
Activity
May ’26
File Provider: case-insensitive collision check prevents mounting case-sensitive remote filesystems correctly
When a File Provider extension (NSFileProviderReplicatedExtension) mounts a Linux server via SFTP, remote directories containing files that differ only in case (e.g., "README" and "readme") are not represented correctly. The framework silently renames one file locally via the before-bounce mechanism, even though the extension reports both items with distinct identifiers and correct filenames. NSFileProviderActions.h states: "Collision checks should be case insensitive even if the filesystem or file provider might allow two coexisting filenames differing only by their case." This check runs in the framework before writing to disk. Placing the domain on a case-sensitive APFS volume via NSFileProviderDomain(displayName:userInfo:volumeURL:) does not help — the volume passes eligibility but the collision check still applies. This breaks any File Provider extension that mounts case-sensitive filesystems where case-variant filenames are common (especially git repositories). Is there any way to opt out of the case-insensitive collision check per domain? A supportsCaseSensitiveNames property on NSFileProviderDomain would solve this.
Replies
2
Boosts
0
Views
1k
Activity
Apr ’26
Kernel panic when using fclonefileat from ES
Hi, I am developing instant snapshot backup solution for macOS using Endpoint Security. We have stumbled upon a Kernel Panic when using "fclonefileat" API. We are catching a kernel panic on customer machines when attempting to clone the file during ES sync callback: panic(cpu 0 caller 0xfffffe002c495508): "apfs_io_lock_exclusive : Recursive exclusive lock attempt" @fs_utils.c:435 I have symbolized the backtrace to know it is related to clone operation with the following backtrace: apfs_io_lock_exclusive apfs_clone_internal apfs_vnop_clonefile I made a minimal repro that boils down to the following operations: apfs_crash_stress - launch thread to do rsrc writes static void *rsrc_write_worker(void *arg) { int id = (int)(long)arg; char buf[8192]; long n = 0; fill_pattern(buf, sizeof(buf), 'W' + id); while (n < ITERATION_LIMIT) { int file_idx = n % NUM_SOURCE_FILES; int fd = open(g_src_rsrc[file_idx], O_WRONLY | O_CREAT, 0644); if (fd >= 0) { off_t off = ((n * 4096) % RSRC_DATA_SIZE); pwrite(fd, buf, sizeof(buf), off); if ((n & 0x7) == 0) fsync(fd); close(fd); } else { setxattr(g_src[file_idx], "com.apple.ResourceFork", buf, sizeof(buf), 0, 0); } n++; } printf("[rsrc_wr_%d] done (%ld ops)\n", id, n); return NULL; } apfs_crash_es - simple ES client that is cloning the file (error checking omitted for brevity) static std::string volfsPath(uint64_t devId, uint64_t vnodeId) { return "/.vol/" + std::to_string(devId) + "/" + std::to_string(vnodeId); } static void cloneAndScheduleDelete(const std::string& sourcePath, dispatch_queue_t queue, uint64_t devId, uint64_t vnodeId) { struct stat st; if (stat(sourcePath.c_str(), &st) != 0 || !S_ISREG(st.st_mode)) return; int srcFd = open(sourcePath.c_str(), O_RDONLY); const char* cloneDir = "/Users/admin/Downloads/_clone"; mkdir(cloneDir, 0755); const char* filename = strrchr(sourcePath.c_str(), '/'); filename = filename ? filename + 1 : sourcePath.c_str(); std::string cloneFilename = std::string(filename) + ".clone." + std::to_string(time(nullptr)) + "." + std::to_string(getpid()); std::string clonePath = std::string(cloneDir) + "/" + cloneFilename; fclonefileat(srcFd, AT_FDCWD, clonePath.c_str(), 0); { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), queue, ^{ if (unlink(clonePath.c_str()) == 0) { LOG("Deleted clone: %s", clonePath.c_str()); } else { LOG("Failed to delete clone: %s", clonePath.c_str()); } }); } close(srcFd); } static const es_file_t* file(const es_message_t* msg) { switch (msg->event_type) { case ES_EVENT_TYPE_AUTH_OPEN: return msg->event.open.file; case ES_EVENT_TYPE_AUTH_EXEC: return msg->event.exec.target->executable; case ES_EVENT_TYPE_AUTH_RENAME: return msg->event.rename.source; } return nullptr; } int main(void) { es_client_t* cli; auto ret = es_new_client(&cli, ^(es_client_t* client, const es_message_t * msgc) { if (msgc->process->is_es_client) { es_mute_process(client, &msgc->process->audit_token); return respond(client, msgc, true); } dispatch_async(esQueue, ^{ bool shouldClone = false; if (msgc->event_type == ES_EVENT_TYPE_AUTH_OPEN) { auto& ev = msgc->event.open; if (ev.fflag & (FWRITE | O_RDWR | O_WRONLY | O_TRUNC | O_APPEND)) { shouldClone = true; } } else if (msgc->event_type == ES_EVENT_TYPE_AUTH_UNLINK || msgc->event_type == ES_EVENT_TYPE_AUTH_RENAME) { shouldClone = true; } if (shouldClone) { if (auto f = ::file(msgc)) cloneAndScheduleDelete(f->path.data, cloneQueue, f->stat.st_dev, f->stat.st_ino); } respond(client, msgc, true); }); }); LOG("es_new_client -> %d", ret); es_event_type_t events[] = { ES_EVENT_TYPE_AUTH_OPEN, ES_EVENT_TYPE_AUTH_EXEC, ES_EVENT_TYPE_AUTH_RENAME, ES_EVENT_TYPE_AUTH_UNLINK, }; es_subscribe(cli, events, sizeof(events) / sizeof(*events)); } Create 2 terminal sessions and run the following commands: % sudo ./apfs_crash_es % sudo ./apfs_crash_stress ~/Downloads/test/ Machine will very quickly panic due to APFS deadlock. I expect that no userspace syscall should be able to cause kernel panic. It looks like a bug in APFS implementation and requires fix on XNU/kext side. We were able to reproduce this issue on macOS 26.3.1/15.6.1 on Intel/ARM machines. Here is the panic string: panic_string.txt Source code without XCode project: apfs_crash_es.cpp apfs_crash_stress.cpp Full XCode project + full panic is available at https://www.icloud.com/iclouddrive/0f215KkZffPOTLpETPo-LdaXw#apfs%5Fcrash%5Fes
Replies
5
Boosts
0
Views
1.1k
Activity
Apr ’26
System-wide deadlock in removexattr from revisiond / APFS
System-wide deadlock in removexattr from revisiond / APFS We're experiencing a deadlock on certains systems when our software is installed, which is causing side effects in our process (and likely others) such as blocked queues and increased memory usage. According to the spindump, revisiond appears to be holding an exclusive lock within the kernel. Process: revisiond [426] UUID: 5E9B9E04-984B-31AD-A4FF-A1A90B7D53A1 Path: /System/Library/PrivateFrameworks/GenerationalStorage.framework/Versions/A/Support/revisiond Codesigning ID: com.apple.revisiond Shared Cache: 25AE5A2A-FE2A-3998-8D4E-F3C5C6E6CEB6 slid base address 0x189834000, slide 0x9834000 (System Primary) Architecture: arm64e Parent: launchd [1] UID: 0 Sudden Term: Tracked Memory Limit: 50MB Jetsam Priority: 40 Footprint: 6225 KB Time Since Fork: 1740319s Num samples: 940 (1-940) Num threads: 5 Note: 1 idle work queue thread omitted [...] Thread 0xc0616d 940 samples (1-940) priority 46 (base 4) last ran 241692.754s ago 940 start_wqthread + 8 (libsystem_pthread.dylib + 7068) [0x189d0ab9c] 940 _pthread_wqthread + 292 (libsystem_pthread.dylib + 11852) [0x189d0be4c] 940 _dispatch_workloop_worker_thread + 692 (libdispatch.dylib + 85356) [0x189b65d6c] 940 _dispatch_root_queue_drain_deferred_wlh + 292 (libdispatch.dylib + 87156) [0x189b66474] 940 _dispatch_lane_invoke + 440 (libdispatch.dylib + 45048) [0x189b5bff8] 940 _dispatch_lane_serial_drain + 944 (libdispatch.dylib + 42420) [0x189b5b5b4] 940 _dispatch_client_callout + 16 (libdispatch.dylib + 113364) [0x189b6cad4] 940 _dispatch_call_block_and_release + 32 (libdispatch.dylib + 7004) [0x189b52b5c] 940 ??? (revisiond + 168768) [0x10494d340] 940 ??? (revisiond + 165940) [0x10494c834] 940 ??? (revisiond + 40264) [0x10492dd48] 940 ??? (revisiond + 56680) [0x104931d68] 940 <patched truncated backtrace> 940 removexattr + 8 (libsystem_kernel.dylib + 23768) [0x189cd1cd8] *940 ??? (kernel.release.t6000 + 15240) [0xfffffe000886fb88] *940 ??? (kernel.release.t6000 + 1886348) [0xfffffe0008a3888c] *940 ??? (kernel.release.t6000 + 7730436) [0xfffffe0008fcb504] *940 ??? (kernel.release.t6000 + 2759592) [0xfffffe0008b0dba8] *940 ??? (kernel.release.t6000 + 2808244) [0xfffffe0008b199b4] *940 apfs_vnop_removexattr + 1044 (apfs + 474512) [0xfffffe000be8d4d0] *940 decmpfs_cnode_set_vnode_state + 80 (kernel.release.t6000 + 2945816) [0xfffffe0008b3b318] *940 IORWLockWrite + 184 (kernel.release.t6000 + 496184) [0xfffffe00088e5238] *940 ??? (kernel.release.t6000 + 494624) [0xfffffe00088e4c20] *940 ??? (kernel.release.t6000 + 619452) [0xfffffe00089033bc] *940 ??? (kernel.release.t6000 + 624472) [0xfffffe0008904758] The bulk of the other processes are waiting for that lock. (suspended, blocked by krwlock for reading owned by revisiond [426] thread 0xc0616d) (blocked by krwlock for writing owned by revisiond [426] thread 0xc0616d) Around the time of the event, these messages were logged by revision: 2026-03-06 18:49:37.781673-0500 0x16b7 Error 0x7f92f364 426 14 revisiond: [com.apple.revisiond:default] [ERROR] CSCopyChunkIDsForToken failed for 41639 2026-03-06 18:49:37.781716-0500 0x16b7 Error 0x7f92f365 426 14 revisiond: [com.apple.revisiond:default] [ERROR] updateEntry for new entry <private> failed 2026-03-06 18:49:37.781738-0500 0x16b7 Error 0x7f92f366 426 14 revisiond: [com.apple.revisiond:default] [ERROR] no entry for '<private>' 2026-03-06 18:49:37.781754-0500 0x16b7 Error 0x7f92f367 426 14 revisiond: [com.apple.revisiond:default] [ERROR] failed assembleInfoForOffset for fsid 16777234 fileid 359684022 offset 0 size 14334 (path <private>) Our agent uses Endpoint Security Framework to monitor events, and provide anti-tamper functionality for installed components and processes. While several EndpointSecurity calls appear in the spindump stack traces, we don't have any evidence that any calls from revisiond were blocked. What we'd really like to to understand what that lock is (appears to be decompressing an object on an APFS volume), what revisiond and APFS are doing with it, and what might cause it to deadlock. Of note, one of our processes is also waiting on that lock, one thread for reading and the other for writing. This issue affects machines running several macOS versions (15.x, 26.x). The machine in the examples is running macOS 26.3 (25D125)
Replies
20
Boosts
0
Views
1.9k
Activity
Apr ’26