Hello,
Starting with macOS 26 beta 4, I’ve noticed that the fflag field in es_event_open_t sometimes contains O_SEARCH instead of the expected FREAD or FWRITE values.
According to the documentation, fflag should represent the kernel-applied flags (e.g., FREAD, FWRITE), not the open(2) oflag values. However, in my tests, when intercepting ES_EVENT_TYPE_AUTH_OPEN events, the value appears to match O_SEARCH in certain cases.
Is this an intentional change in macOS 26, or could it be a bug in the current beta? If this is expected behavior, could you clarify under what conditions O_SEARCH or some oflag are returned?
Environment:
macOS 26 beta 4
Endpoint Security Framework
Thanks in advance for any clarification!
According to the documentation, fflag should represent the kernel-applied flags (e.g., FREAD, FWRITE), not the open(2) O_SEARCH values.
That's not quite correct. It's not a case of "should", it's that they ARE the kernel's flags. More specifically, the ES system is simply passing up the exact values it "got" from the MAC system in the kernel, so whatever it passes up is in fact exactly what was moving through the kernel.
The documentation calls out FREAD/FWRITE, but that's primarily because they have different flags. If you compare the definitions of XNU fcntl.h (kernel) and libc fcntl.h (user space), you'll find that most of their definitions are identical, with FREAD/FWRITE being the most notable exceptions.
However, in my tests, when intercepting ES_EVENT_TYPE_AUTH_OPEN events, the value appears to match O_SEARCH in certain cases.
What is generating the event and what was it targeting? What's the full flag value you're receiving?
Is this an intentional change in macOS 26, or could it be a bug in the current beta?
I'm not sure. If you're getting O_SEARCH on directories, then I suspect that's normal behavior, but if you're getting it on files, then that's at least "odd". The typical behavior is that O_SEARCH on a file will fail with ENOTDIR before the MAC check (which is what calls out to the ES system) occurs, but there has been some reordering of MAC check calls, so it's possible there is an edge case that's moved the check "earlier".
If this is expected behavior, could you clarify under what conditions O_SEARCH or some oflag are returned?
Well, the direct answer is because someone passed O_SEARCH into open. More practically, what O_SEARCH actually provides is a file descriptor reference for a directory without also providing read access to its contents. In practice, the main reason for using O_SEARCH is to pass the open descriptor into one of the "at" function variants. As a concrete example, which you may be seeing a lot of, the "cp" command has tweaked its implementation to favor open objects with O_SEARCH and then pass them into file descriptor-based APIs instead of using paths.
__
Kevin Elliott
DTS Engineer, CoreOS/Hardware