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.