Does SessionGetInfo provide authoritative current-session liveness for an ASID from a Mach audit token?

Environment:

macOS 26.6.2 (25G83)

Xcode 26.6 (17F113)

macOS command-line process

Security.framework SessionGetInfo

ASID obtained from the kernel-provided audit token in a received Mach message

I’m implementing a security-sensitive Mach IPC receiver.

The receiver obtains the sender’s audit token from the Mach message trailer and derives the sender PID, effective UID, and audit session ID (ASID). The sender executable identity is validated separately.

Given the ASID, SessionGetInfo can successfully return the corresponding SecuritySessionId and session attributes.

The question is about the freshness and synchronization semantics of that lookup.

At the point where the receiver authorizes a request, can a successful SessionGetInfo(asid, ...) result be treated as authoritative evidence that the corresponding login/audit session is still currently valid?

In particular:

What happens if the session logs out, terminates, or is revoked concurrently with the lookup?

Can SessionGetInfo successfully return information for a session that is no longer current due to caching or propagation delay?

Are there documented ordering or synchronization guarantees between session termination and subsequent SessionGetInfo calls from another process?

Can the lookup block for an unbounded period if the underlying security service is unavailable?

Is there a supported timeout or cancellation mechanism?

Is there another supported public macOS API better suited to establishing authoritative current-session liveness for an ASID obtained from an audit token?

The security requirement is fail-closed. I’m specifically trying to avoid private APIs, process-table heuristics, diagnostic launchctl output, or assumptions that the ASID encoded in a previously received audit token necessarily represents current session state.

If the public API does not provide an authoritative liveness/freshness guarantee, confirmation of that limitation would also answer the design question.

I also have a minimal 122-line Xcode sample that:

creates and receives a Mach message,

reads the kernel-provided audit trailer,

extracts the ASID,

calls SessionGetInfo, and

prints the returned session ID and attributes.

I can provide the sample project if useful.

Answered by DTS Engineer in 907576022

On modern systems SessionGetInfo is basically a wrapper around auditon with the A_GETSINFO_ADDR selector. See the auditon man page for more on that.

Both of these APIs are fundamentally racy. There’s a source of truth (currently held in the kernel) and the API returns a copy of the information from that source of truth. The API has no locking, so the source of truth can change between when the system makes the copy to return to you and when you look at it. There’s simply no way to avoid that.

Audit sessions IDs are relatively large (32 bits) and the system tries to avoid reusing them, so if the session has gone away then you’re likely to get an error rather than the data for an unrelated session. However, I use the word likely deliberately. I don’t think there’s anything that’ll explicitly prevent that.

A process references its audit session and, in general, that doesn’t change for the lifetime of the process [1]. So, if you know that the process is still alive you can reasonably assume that the audit session is as well.


What are you actually planning to do with the session ID and attributes you get back from this exercise?

Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Although it can change. This must necessarily happen within launchd, but it’s definitely possible in other situations. A quick look at the code suggests that it involves some pretty strict security checking, but I’ve not spent a lot of time on the details.

On modern systems SessionGetInfo is basically a wrapper around auditon with the A_GETSINFO_ADDR selector. See the auditon man page for more on that.

Both of these APIs are fundamentally racy. There’s a source of truth (currently held in the kernel) and the API returns a copy of the information from that source of truth. The API has no locking, so the source of truth can change between when the system makes the copy to return to you and when you look at it. There’s simply no way to avoid that.

Audit sessions IDs are relatively large (32 bits) and the system tries to avoid reusing them, so if the session has gone away then you’re likely to get an error rather than the data for an unrelated session. However, I use the word likely deliberately. I don’t think there’s anything that’ll explicitly prevent that.

A process references its audit session and, in general, that doesn’t change for the lifetime of the process [1]. So, if you know that the process is still alive you can reasonably assume that the audit session is as well.


What are you actually planning to do with the session ID and attributes you get back from this exercise?

Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Although it can change. This must necessarily happen within launchd, but it’s definitely possible in other situations. A quick look at the code suggests that it involves some pretty strict security checking, but I’ve not spent a lot of time on the details.

Thanks - this is exactly the distinction I was trying to establish.

The session ID itself is not the ultimate security objective.

The receiver is making a security-sensitive authorization decision for a Mach IPC request. From the kernel-provided audit token, it validates the sender process identity, including PID and code-signing identity, and we were considering the ASID/session state as an additional check that the requesting principal had not become stale due to logout, session termination, or a similar transition before authority is exercised.

The property we actually need is:

At the point the receiver authorizes the request, establish that the request still belongs to the same live, authenticated sender principal that originated the Mach message, and fail closed if that authority has become stale or invalid.

We do not need SessionGetInfo specifically if another supported macOS design pattern provides a stronger way to establish that property.

Given the race you described, would you recommend anchoring this primarily to the lifetime and identity of the sender process instead of trying to independently prove audit-session liveness?

For example, if the receiver validates the kernel-provided audit token, sender PID, code-signing identity, and that the originating process is still alive at the authorization point, is there a supported mechanism or pattern you would recommend to prevent stale/replayed authority across logout, process exit/restart, PID reuse, or other principal changes?

I’m specifically trying to avoid relying on an inherently racy session lookup if macOS provides a stronger process- or connection-bound primitive.

would you recommend anchoring this primarily to the lifetime and identity of the sender process … ?

Yes. Processes have commonly accepted semantics, but that’s not really true for security sessions. They’re more of an implementation detail than an API. And the primary API they’re used by, BSM, has itself been deprecated (check out the __AUDIT_API_DEPRECATED macro).

My general take on this is to try to use audit tokens as much as possible, because they have built-in protection against pid reuse. You can see this via audit_token_to_pidversion, but I try to avoid relying on that but instead try to stick with APIs that work in terms of audit tokens [1]. For example, when dealing with code signing I prefer kSecGuestAttributeAudit over kSecGuestAttributePid.

Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] And sometimes those show up in the most unexpected places.

Does SessionGetInfo provide authoritative current-session liveness for an ASID from a Mach audit token?
 
 
Q