-
Notifications
You must be signed in to change notification settings - Fork 298
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add transitive whitelisting to Santa #224
Changes from 5 commits
8f972eb
48b656d
1a9d07b
0d77a2c
a594175
881322f
7a32d31
0f9d63a
163ac9b
47a981e
16092cd
0b106e4
9c4c7fa
6348fd1
04d8f41
fef9351
0e840d2
c4b47e1
43ce8aa
83649ee
079a6d3
dc10e23
d35f0b5
6cb4ad5
aa01a79
a08e7f8
88b0972
0cb3d6a
1cd9551
8f82370
1b687a1
d2df097
340f59d
b9c7585
c293d5d
a9201dd
91c5d71
e583712
75de096
6d295c9
ca00a28
e0bf6dd
16769e8
93a7e86
bba1aee
21561ef
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,13 @@ | |
|
||
#include "SantaDecisionManager.h" | ||
|
||
// This is a made-up KAUTH_FILEOP constant which represents a KAUTH_VNODE_WRITE_DATA event | ||
// that gets passed to SantaDecisionManager's FileOpCallback method. It is defined as 8 | ||
// because that was the first unused integer from sys/kauth.h. The reason that we don't | ||
// simply use the KAUTH_VNODE_WRITE_DATA constant as is is because it overlaps with the other | ||
// KAUTH_FILEOP constants. | ||
#define KAUTH_FILEOP_WRITE 8 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If this is still needed we should give the actions used by KAUTH_SCOPE_FILEOP room to grow. I don't really like the idea of adding our own action, but if we need to make it more than 8 incase fileop adds a new action in the future. Maybe KAUTH_FILEOP_DELETE + 32 or something There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
|
||
#define super OSObject | ||
OSDefineMetaClassAndStructors(SantaDecisionManager, OSObject); | ||
|
||
|
@@ -28,6 +35,7 @@ bool SantaDecisionManager::init() { | |
|
||
decision_dataqueue_lock_ = lck_mtx_alloc_init(sdm_lock_grp_, sdm_lock_attr_); | ||
log_dataqueue_lock_ = lck_mtx_alloc_init(sdm_lock_grp_, sdm_lock_attr_); | ||
compiler_dataqueue_lock_ = lck_mtx_alloc_init(sdm_lock_grp_, sdm_lock_attr_); | ||
|
||
root_decision_cache_ = new SantaCache<uint64_t>(5000, 2); | ||
non_root_decision_cache_ = new SantaCache<uint64_t>(500, 2); | ||
|
@@ -41,6 +49,10 @@ bool SantaDecisionManager::init() { | |
kMaxLogQueueEvents, sizeof(santa_message_t)); | ||
if (!log_dataqueue_) return kIOReturnNoMemory; | ||
|
||
compiler_dataqueue_ = IOSharedDataQueue::withEntries( | ||
kMaxCompilerQueueEvents, sizeof(santa_message_t)); | ||
if (!compiler_dataqueue_) return kIOReturnNoMemory; | ||
|
||
client_pid_ = 0; | ||
root_fsid_ = 0; | ||
|
||
|
@@ -65,6 +77,11 @@ void SantaDecisionManager::free() { | |
log_dataqueue_lock_ = nullptr; | ||
} | ||
|
||
if (compiler_dataqueue_lock_) { | ||
lck_mtx_free(compiler_dataqueue_lock_, sdm_lock_grp_); | ||
compiler_dataqueue_lock_ = nullptr; | ||
} | ||
|
||
if (sdm_lock_attr_) { | ||
lck_attr_free(sdm_lock_attr_); | ||
sdm_lock_attr_ = nullptr; | ||
|
@@ -82,6 +99,7 @@ void SantaDecisionManager::free() { | |
|
||
OSSafeReleaseNULL(decision_dataqueue_); | ||
OSSafeReleaseNULL(log_dataqueue_); | ||
OSSafeReleaseNULL(compiler_dataqueue_); | ||
|
||
super::free(); | ||
} | ||
|
@@ -110,6 +128,7 @@ void SantaDecisionManager::ConnectClient(pid_t pid) { | |
|
||
failed_decision_queue_requests_ = 0; | ||
failed_log_queue_requests_ = 0; | ||
failed_compiler_queue_requests_ = 0; | ||
} | ||
|
||
void SantaDecisionManager::DisconnectClient(bool itDied) { | ||
|
@@ -137,6 +156,12 @@ void SantaDecisionManager::DisconnectClient(bool itDied) { | |
log_dataqueue_ = IOSharedDataQueue::withEntries( | ||
kMaxLogQueueEvents, sizeof(santa_message_t)); | ||
lck_mtx_unlock(log_dataqueue_lock_); | ||
|
||
lck_mtx_lock(compiler_dataqueue_lock_); | ||
compiler_dataqueue_->release(); | ||
compiler_dataqueue_ = IOSharedDataQueue::withEntries( | ||
kMaxCompilerQueueEvents, sizeof(santa_message_t)); | ||
lck_mtx_unlock(compiler_dataqueue_lock_); | ||
} | ||
} | ||
|
||
|
@@ -163,6 +188,12 @@ void SantaDecisionManager::SetLogPort(mach_port_t port) { | |
lck_mtx_unlock(log_dataqueue_lock_); | ||
} | ||
|
||
void SantaDecisionManager::SetCompilerPort(mach_port_t port) { | ||
lck_mtx_lock(compiler_dataqueue_lock_); | ||
compiler_dataqueue_->setNotificationPort(port); | ||
lck_mtx_unlock(compiler_dataqueue_lock_); | ||
} | ||
|
||
IOMemoryDescriptor *SantaDecisionManager::GetDecisionMemoryDescriptor() const { | ||
return decision_dataqueue_->getMemoryDescriptor(); | ||
} | ||
|
@@ -171,6 +202,10 @@ IOMemoryDescriptor *SantaDecisionManager::GetLogMemoryDescriptor() const { | |
return log_dataqueue_->getMemoryDescriptor(); | ||
} | ||
|
||
IOMemoryDescriptor *SantaDecisionManager::GetCompilerMemoryDescriptor() const { | ||
return compiler_dataqueue_->getMemoryDescriptor(); | ||
} | ||
|
||
#pragma mark Listener Control | ||
|
||
kern_return_t SantaDecisionManager::StartListener() { | ||
|
@@ -417,6 +452,26 @@ bool SantaDecisionManager::PostToLogQueue(santa_message_t *message) { | |
return kr; | ||
} | ||
|
||
bool SantaDecisionManager::PostToCompilerQueue(santa_message_t *message) { | ||
lck_mtx_lock(compiler_dataqueue_lock_); | ||
auto kr = compiler_dataqueue_->enqueue(message, sizeof(santa_message_t)); | ||
if (!kr) { | ||
if (failed_compiler_queue_requests_++ == 0) { | ||
LOGW("Dropping compiler queue messages"); | ||
} | ||
// If enqueue failed, pop an item off the queue and try again. | ||
uint32_t dataSize = 0; | ||
compiler_dataqueue_->dequeue(0, &dataSize); | ||
kr = compiler_dataqueue_->enqueue(message, sizeof(santa_message_t)); | ||
} else { | ||
if (failed_compiler_queue_requests_ > 0) { | ||
failed_compiler_queue_requests_--; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can remove this pop and re-queue bit, it's unnecessary. |
||
} | ||
lck_mtx_unlock(compiler_dataqueue_lock_); | ||
return kr; | ||
} | ||
|
||
#pragma mark Invocation Tracking & PID comparison | ||
|
||
void SantaDecisionManager::IncrementListenerInvocations() { | ||
|
@@ -495,6 +550,7 @@ void SantaDecisionManager::FileOpCallback( | |
message->ppid = (val & ~0xFFFFFFFF00000000); | ||
} | ||
PostToLogQueue(message); | ||
PostToCompilerQueue(message); | ||
delete message; | ||
return; | ||
} | ||
|
@@ -509,9 +565,13 @@ void SantaDecisionManager::FileOpCallback( | |
proc_name(message->pid, message->pname, sizeof(message->pname)); | ||
|
||
switch (action) { | ||
case KAUTH_FILEOP_CLOSE: | ||
case KAUTH_FILEOP_WRITE: | ||
// This is actually a KAUTH_VNODE_WRITE_DATA event. | ||
message->action = ACTION_NOTIFY_WRITE; | ||
break; | ||
case KAUTH_FILEOP_CLOSE: | ||
message->action = ACTION_NOTIFY_CLOSE; | ||
break; | ||
case KAUTH_FILEOP_RENAME: | ||
message->action = ACTION_NOTIFY_RENAME; | ||
break; | ||
|
@@ -529,7 +589,16 @@ void SantaDecisionManager::FileOpCallback( | |
return; | ||
} | ||
|
||
PostToLogQueue(message); | ||
// We don't log the ACTION_NOTIFY_CLOSE messages because they mostly duplicate the | ||
// ACTION_NOTIFY_WRITE messages (though they aren't precisely the same) | ||
if (message->action != ACTION_NOTIFY_CLOSE) { | ||
PostToLogQueue(message); | ||
} | ||
|
||
if (message->action == ACTION_NOTIFY_CLOSE || message->action == ACTION_NOTIFY_RENAME) { | ||
PostToCompilerQueue(message); | ||
} | ||
|
||
delete message; | ||
} | ||
} | ||
|
@@ -552,6 +621,10 @@ extern "C" int fileop_scope_callback( | |
char *new_path = nullptr; | ||
|
||
switch (action) { | ||
// We only care about KAUTH_FILEOP_CLOSE events where the closed file was modified. | ||
case KAUTH_FILEOP_CLOSE: | ||
if (!(arg2 & KAUTH_FILEOP_CLOSE_MODIFIED)) | ||
return KAUTH_RESULT_DEFER; | ||
case KAUTH_FILEOP_DELETE: | ||
case KAUTH_FILEOP_EXEC: | ||
vp = reinterpret_cast<vnode_t>(arg0); | ||
|
@@ -604,7 +677,9 @@ extern "C" int vnode_scope_callback( | |
char path[MAXPATHLEN]; | ||
int pathlen = MAXPATHLEN; | ||
vn_getpath(vp, path, &pathlen); | ||
sdm->FileOpCallback(KAUTH_FILEOP_CLOSE, vp, path, nullptr); | ||
// KAUTH_VNODE_WRITE_DATA events are translated into a fake KAUTH_FILEOP_WRITE event | ||
// so that we can handle them in the FileOpCallback function. | ||
sdm->FileOpCallback(KAUTH_FILEOP_WRITE, vp, path, nullptr); | ||
sdm->DecrementListenerInvocations(); | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove any DevelopmentTeam additions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.