As per Quinns request here is a more detailed version of my code
static func handleProcessExec(_ msg: UnsafePointer<es_message_t>) {
let target = msg.pointee.event.exec.target.pointee
guard msg.pointee.process.pointee.is_es_client == false else {
es_respond_auth_result(esClient.client!, msg, ES_AUTH_RESULT_ALLOW, true)
return
}
// copy message so it can be used on another thread
guard let copiedMessage = copyMessage(msg) else {
es_respond_auth_result(esClient.client!, msg, ES_AUTH_RESULT_DENY, false)
return
}
DispatchQueue.global().async {
var process: ProcessDetails? = nil
let deadline = DispatchTime(uptimeNanoseconds: copiedMessage.pointee.deadline - (2*NSEC_PER_SEC))
let semaphore = DispatchSemaphore(value: 0)
// RuleResult contains what rule matched and if we should allow/deny
var result = RuleResult()
let timestamp = copiedMessage.pointee.time.tv_sec
DispatchQueue.global().async {
process = ProcessDetails(process: copiedMessage.pointee.event.exec.target.pointee)
ESEventRulesRunner.runProcessExecRules(process: process!, &result)
semaphore.signal()
}
_ = semaphore.wait(timeout: deadline)
es_respond_auth_result(esClient.client!, copiedMessage, result.verdict, false)
if result.verdict == ES_AUTH_RESULT_DENY {
// Log event to api
let event = ESEvent(process: process!, timestamp: timestamp, ruleType: result.type)
Api.postEvent(event: event)
}
freeMessage(copiedMessage)
}
}