A security session is set up when the user logs in, but you don’t get a new session when you launch a sandboxed app. You can confirm this with SessionGetInfo.
Indeed, it appears that every "regular app" is sharing the same security and audit sessions.
Here are some details about the security and audit sessions:
Without JoinExistingSession:
Main app:
My security session (id 100019) has attributes: [.sessionHasGraphicAccess, .sessionHasTTY])
My audit session (id 100019) and has flags: [AU_SESSION_FLAG_HAS_GRAPHIC_ACCESS, AU_SESSION_FLAG_HAS_TTY, AU_SESSION_FLAG_HAS_CONSOLE_ACCESS, AU_SESSION_FLAG_HAS_AUTHENTICATED]
XPC Service:
My security session (id 103826) has attributes: [])
My audit session (id 103826) and has flags: []
With JoinExistingSession:
EBAS has these same flags, as well.
Main app:
My security session (id 100019) has attributes: [.sessionHasGraphicAccess, .sessionHasTTY])
My audit session (id 100019) and has flags: [AU_SESSION_FLAG_HAS_GRAPHIC_ACCESS, AU_SESSION_FLAG_HAS_TTY, AU_SESSION_FLAG_HAS_CONSOLE_ACCESS]
XPC Service:
My security session (id 100019) has attributes: [.sessionHasGraphicAccess, .sessionHasTTY])
My audit session (id 100019) and has flags: [AU_SESSION_FLAG_HAS_GRAPHIC_ACCESS, AU_SESSION_FLAG_HAS_TTY, AU_SESSION_FLAG_HAS_CONSOLE_ACCESS, AU_SESSION_FLAG_HAS_AUTHENTICATED]
Security and Audit session logging code
Here's the code I used to generate those messages, in case you're curious.
extension SessionAttributeBits: CaseIterable {
public static var allCases: [SessionAttributeBits] {
[
.sessionIsRoot,
.sessionHasGraphicAccess,
.sessionHasTTY,
.sessionIsRemote,
]
}
}
extension SessionAttributeBits: CustomStringConvertible {
public var description: String {
switch self {
case .sessionIsRoot: return ".sessionIsRoot"
case .sessionHasGraphicAccess: return ".sessionHasGraphicAccess"
case .sessionHasTTY: return ".sessionHasTTY"
case .sessionIsRemote: return ".sessionIsRemote"
default: return Self.allCases.filter(self.contains).description
}
}
}
// Why isn't `audit_session_flags` imported as an OptionSet to begin with?
extension audit_session_flags: OptionSet {}
extension audit_session_flags: CaseIterable {
public static var allCases: [audit_session_flags] {
[
AU_SESSION_FLAG_IS_INITIAL,
AU_SESSION_FLAG_HAS_GRAPHIC_ACCESS,
AU_SESSION_FLAG_HAS_TTY,
AU_SESSION_FLAG_IS_REMOTE,
AU_SESSION_FLAG_HAS_CONSOLE_ACCESS,
AU_SESSION_FLAG_HAS_AUTHENTICATED,
]
}
}
extension audit_session_flags: CustomStringConvertible {
public var description: String {
switch self {
case AU_SESSION_FLAG_IS_INITIAL: return "AU_SESSION_FLAG_IS_INITIAL"
case AU_SESSION_FLAG_HAS_GRAPHIC_ACCESS: return "AU_SESSION_FLAG_HAS_GRAPHIC_ACCESS"
case AU_SESSION_FLAG_HAS_TTY: return "AU_SESSION_FLAG_HAS_TTY"
case AU_SESSION_FLAG_IS_REMOTE: return "AU_SESSION_FLAG_IS_REMOTE"
case AU_SESSION_FLAG_HAS_CONSOLE_ACCESS: return "AU_SESSION_FLAG_HAS_CONSOLE_ACCESS"
case AU_SESSION_FLAG_HAS_AUTHENTICATED: return "AU_SESSION_FLAG_HAS_AUTHENTICATED"
default: return Self.allCases.filter(self.contains).description
}
}
}
extension auditinfo_addr_t {
static func forCurrentProcess() -> Self {
var auditInfo = auditinfo_addr_t();
let errorCode = getaudit_addr(&auditInfo, Int32(MemoryLayout.size(ofValue: auditInfo)))
assert(errorCode == 0, "getaudit_addr returned a non-zero error code: \(errorCode)")
return auditInfo
}
var auditSessionFlags: audit_session_flags {
audit_session_flags(rawValue: UInt32(self.ai_flags))
}
}
public func printSecuritySessionInfo() {
var mySessionID = SecuritySessionId()
var sessionAttributes = SessionAttributeBits()
let errorCode = SessionGetInfo(callerSecuritySession, &mySessionID, &sessionAttributes)
assert(errorCode == errSecSuccess)
print("My security session (id \(mySessionID)) has attributes: \(sessionAttributes))")
}
public func printAuditSessionInfo() {
let auditSession = auditinfo_addr_t.forCurrentProcess()
print("My audit session (id \(auditSession.ai_asid)) and has flags: \(auditSession.auditSessionFlags)")
}
Topic:
Privacy & Security
SubTopic:
General
Tags: