I'm using this code to get the path of an executable from the audit token provided in NEFilterDataProvider.handleNewFlow(_:)
, forwarded from the Network Extension to the main app via IPC:
private func securePathFromAuditToken(_ auditToken: Data) throws -> String {
let secFlags = SecCSFlags()
var secCode: SecCode?
var status = SecCodeCopyGuestWithAttributes(nil, [kSecGuestAttributeAudit: auditToken] as CFDictionary, secFlags, &secCode)
guard let secCode = secCode else {
throw NSError(domain: NSOSStatusErrorDomain, code: Int(status))
}
var secStaticCode: SecStaticCode?
status = SecCodeCopyStaticCode(secCode, secFlags, &secStaticCode)
guard let secStaticCode = secStaticCode else {
throw NSError(domain: NSOSStatusErrorDomain, code: Int(status))
}
var url: CFURL?
status = SecCodeCopyPath(secStaticCode, secFlags, &url)
guard let url = url as URL? else {
throw NSError(domain: NSOSStatusErrorDomain, code: Int(status))
}
return url.path
}
This code sometimes returns paths like /System/Library/PrivateFrameworks/HelpData.framework/Versions/A/Resources/helpd
or /Library/Developer/CoreSimulator/Volumes/iOS_21A328/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 17.0.simruntime/Contents/Resources/RuntimeRoot/usr/libexec/mobileassetd
.
But sometimes the SecCodeCopyGuestWithAttributes
fails with status 100001
which is defined in MacErrors.h
as kPOSIXErrorEPERM = 100001, /* Operation not permitted */
. In these cases I resort to this code, which I have read is not as secure:
private func insecurePathFromAuditToken(_ auditToken: Data) throws -> String? {
if auditToken.count == MemoryLayout<audit_token_t>.size {
let pid = auditToken.withUnsafeBytes { buffer in
audit_token_to_pid(buffer.baseAddress!.assumingMemoryBound(to: audit_token_t.self).pointee)
}
let pathbuf = UnsafeMutablePointer<Int8>.allocate(capacity: Int(PROC_PIDPATHINFO_SIZE))
defer {
pathbuf.deallocate()
}
let ret = proc_pidpath(pid, pathbuf, UInt32(PROC_PIDPATHINFO_SIZE))
if ret <= 0 {
throw NSError(domain: NSPOSIXErrorDomain, code: Int(errno))
}
return String(cString: pathbuf)
}
return nil
}
This insecure code then returns paths like /usr/libexec/trustd
, /usr/libexec/rapportd
, /usr/libexec/nsurlsessiond
and /usr/libexec/timed
.
From what I can see, SecCodeCopyGuestWithAttributes
fails for all processes in /usr/libexec
. Some of these processes have executables with the same name placed in another directory, like /Library/Developer/CoreSimulator/Volumes/iOS_21A328/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 17.0.simruntime/Contents/Resources/RuntimeRoot/usr/libexec/mobileassetd
for which it succeeds, while for /usr/libexec/mobileassetd
it fails.
Occasionally, both the secure and the insecure methods fail and in these cases the secure one returns status code 100003
, which is defined as kPOSIXErrorESRCH = 100003, /* No such process */
. When can this happen?
This seems to happen with both NEFilterFlow.sourceAppAuditToken
and sourceProcessAuditToken
. What is the problem?