Skip to content
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

Merged
merged 46 commits into from
Jul 20, 2018
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
8f972eb
prototype code for santa transitive whitelisting
nguyen-phillip Nov 2, 2017
48b656d
prototype code for santa transitive whitelisting
nguyen-phillip Nov 2, 2017
1a9d07b
added a separate message queue to handle events related to compiler w…
nguyen-phillip Dec 4, 2017
0d77a2c
Merge remote-tracking branch 'origin/master' into compiler
nguyen-phillip Dec 4, 2017
a594175
forgot to add updated project.pbxproj file with commit
nguyen-phillip Dec 5, 2017
881322f
Replaced functionality of compiler vnode cache with new ACTION_RESPON…
nguyen-phillip Dec 7, 2017
7a32d31
Removed separate compiler message queue; send these messages to decis…
nguyen-phillip Dec 7, 2017
0f9d63a
Remove references to DevelopmentTeam from project.pbxproj
nguyen-phillip Dec 7, 2017
163ac9b
Define KAUTH_FILEOP_WRITE as a larger constant to avoid future conflicts
nguyen-phillip Dec 7, 2017
47a981e
Remove reference to Podfile.lock
nguyen-phillip Dec 7, 2017
16092cd
replace copyright notice
nguyen-phillip Dec 7, 2017
0b106e4
moved compiler process exit monitoring from userspace to kernelspace
nguyen-phillip Dec 8, 2017
9c4c7fa
switched from IOCreateThread to kernel_thread_start and friends
nguyen-phillip Dec 8, 2017
6348fd1
added timestamps to transitive rules & extra info to santactl status
nguyen-phillip Dec 8, 2017
04d8f41
Send transitive rule state back to kernel so that it is stored in dec…
nguyen-phillip Dec 12, 2017
fef9351
update timestamp of transitive rules whenever they are accessed for e…
nguyen-phillip Dec 12, 2017
0e840d2
some minor cleanup
nguyen-phillip Dec 12, 2017
c4b47e1
Stop watching RENAME actions for transitive whitelisting. Don't look …
nguyen-phillip Dec 12, 2017
43ce8aa
add ability for sync server to send down WHITELIST_COMPILER rules and…
nguyen-phillip Dec 13, 2017
83649ee
made SNTRule timestamp property readonly, plus other fixes
nguyen-phillip Dec 13, 2017
079a6d3
rename refreshTimestampForRule: to resetTimestampForRule
nguyen-phillip Dec 13, 2017
dc10e23
refresh transitive rule timestamps based on ACTION_NOTIFY_EXEC messag…
nguyen-phillip Dec 14, 2017
d35f0b5
fix broken testPreflighDatabaseCounts
nguyen-phillip Dec 14, 2017
6cb4ad5
don't pass SantaDecisionManager ref to process monitoring threads, in…
nguyen-phillip Dec 15, 2017
aa01a79
remove most of the debugging cruft
nguyen-phillip Jan 4, 2018
a08e7f8
some minor fixes
nguyen-phillip Jan 8, 2018
88b0972
fix merge conflict
nguyen-phillip Jan 8, 2018
0cb3d6a
Merge branch 'master' into compiler
nguyen-phillip Jan 8, 2018
1cd9551
Merge branch 'master' into compiler
nguyen-phillip Jan 8, 2018
8f82370
added compiler and transitive rule tests to SNTExecutionControllerTest.m
nguyen-phillip Jan 8, 2018
1b687a1
Merge branch 'compiler' of https://github.com/nguyen-phillip/santa in…
nguyen-phillip Jan 8, 2018
d2df097
merge with upstream, renumber ACTION_RESPOND_ALLOW enums
nguyen-phillip Jan 24, 2018
340f59d
* Pass SantaDecisionManager to the pid monitor threads so that compil…
nguyen-phillip Jan 25, 2018
b9c7585
Allow enabling of transitive whitelisting from mobile config.
nguyen-phillip Jan 29, 2018
c293d5d
Add a temporary allow rule to kernel's decision cache for files writt…
nguyen-phillip Feb 1, 2018
a9201dd
compiler_pid_set_ now maps pid to ppid and a given process is considered
nguyen-phillip Feb 1, 2018
91c5d71
renamed ACTION_RESPOND_TEMPORARY to ACTION_RESPOND_PENDING_TRANSITIVE…
nguyen-phillip Feb 7, 2018
e583712
Merge remote-tracking branch 'origin/master' into compiler
nguyen-phillip May 21, 2018
75de096
fix formatting
nguyen-phillip May 29, 2018
6d295c9
merged up to #267
nguyen-phillip May 29, 2018
ca00a28
Started watching for KAUTH_FILEOP_RENAME in addition to KAUTH_FILEOP_…
nguyen-phillip May 29, 2018
e0bf6dd
Merge remote-tracking branch 'origin/master' into compiler
nguyen-phillip May 30, 2018
16769e8
merge
nguyen-phillip Jul 16, 2018
93a7e86
Add kernel tests for transitive whitelisting
nguyen-phillip Jul 16, 2018
bba1aee
fix comments
nguyen-phillip Jul 16, 2018
21561ef
don't hardcode ld path; fix indentation
nguyen-phillip Jul 17, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 48 additions & 5 deletions Santa.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@
59D56CF2D9C5BD9B7E3CC56D /* libPods-santad-santabs.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14B98F4051188ECB7D024331 /* libPods-santad-santabs.a */; };
81133DB01F3A76F700917FF9 /* SNTCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = 81133DAF1F3A75CE00917FF9 /* SNTCommand.m */; };
81133DB11F3A77C600917FF9 /* SNTCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = 81133DAF1F3A75CE00917FF9 /* SNTCommand.m */; };
81A00E7F1FD74F8E00A84676 /* SNTCompilerController.m in Sources */ = {isa = PBXBuildFile; fileRef = 81A00E7E1FD74EFF00A84676 /* SNTCompilerController.m */; };
81A00E801FD74F9100A84676 /* SNTCompilerController.m in Sources */ = {isa = PBXBuildFile; fileRef = 81A00E7E1FD74EFF00A84676 /* SNTCompilerController.m */; };
B352A545B76783D568A6D0C5 /* libPods-Santa.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 90E9D568200AB9B642E06272 /* libPods-Santa.a */; };
C714F8B11D8044D400700EDF /* SNTCommandFileInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD5FBE1909D64A006B445C /* SNTCommandFileInfo.m */; };
C714F8B21D8044FE00700EDF /* SNTCommandController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D35BDAB18FD7CFD00921A21 /* SNTCommandController.m */; };
Expand Down Expand Up @@ -431,6 +433,8 @@
7D949AA996AEAC326A4F6596 /* libPods-LogicTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-LogicTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
81133DAE1F3A75CE00917FF9 /* SNTCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTCommand.h; sourceTree = "<group>"; };
81133DAF1F3A75CE00917FF9 /* SNTCommand.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTCommand.m; sourceTree = "<group>"; };
81A00E7D1FD74EFF00A84676 /* SNTCompilerController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNTCompilerController.h; sourceTree = "<group>"; };
81A00E7E1FD74EFF00A84676 /* SNTCompilerController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SNTCompilerController.m; sourceTree = "<group>"; };
8EF10E4B8C86CED022C72F1B /* Pods-santactl.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-santactl.debug.xcconfig"; path = "Pods/Target Support Files/Pods-santactl/Pods-santactl.debug.xcconfig"; sourceTree = "<group>"; };
90E9D568200AB9B642E06272 /* libPods-Santa.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Santa.a"; sourceTree = BUILT_PRODUCTS_DIR; };
A6A91785C40257CC156B4F05 /* Pods-Santa.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Santa.release.xcconfig"; path = "Pods/Target Support Files/Pods-Santa/Pods-Santa.release.xcconfig"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -767,6 +771,8 @@
0DB8ACC0185662DC00FEF9C7 /* SNTApplication.m */,
0DE71A731B95F7F900518526 /* SNTCachedDecision.h */,
0DE71A741B95F7F900518526 /* SNTCachedDecision.m */,
81A00E7D1FD74EFF00A84676 /* SNTCompilerController.h */,
81A00E7E1FD74EFF00A84676 /* SNTCompilerController.m */,
0D8E18CB19107B56000F89B8 /* SNTDaemonControlController.h */,
0D8E18CC19107B56000F89B8 /* SNTDaemonControlController.m */,
0D63DD5A1906FCB400D346C4 /* SNTDatabaseController.h */,
Expand Down Expand Up @@ -1051,11 +1057,31 @@
attributes = {
LastUpgradeCheck = 0730;
TargetAttributes = {
0D0016A1192BCD3C005E7FCD = {
DevelopmentTeam = 9L79GAXCBC;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove any DevelopmentTeam additions

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

};
0D260DAB18B68E12002A0B55 = {
DevelopmentTeam = 9L79GAXCBC;
TestTargetID = 0D385DB5180DE4A900418BC6;
};
0D35BD9D18FD71CE00921A21 = {
DevelopmentTeam = 9L79GAXCBC;
};
0D385DB5180DE4A900418BC6 = {
DevelopmentTeam = 9L79GAXCBC;
};
0D91BCB3174E8A7E00131A7D = {
DevelopmentTeam = 9L79GAXCBC;
};
0D91BCDC174E8AE600131A7D = {
DevelopmentTeam = 9L79GAXCBC;
};
0D9A7F3C1759330400035EB5 = {
DevelopmentTeam = 9L79GAXCBC;
};
C78227531E1C3C58006EB2D6 = {
CreatedOnToolsVersion = 7.3.1;
DevelopmentTeam = 9L79GAXCBC;
};
};
};
Expand Down Expand Up @@ -1221,13 +1247,16 @@
files = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-santad-santabs-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
2146C1274A8C11B3755A8A67 /* [CP] Check Pods Manifest.lock */ = {
Expand All @@ -1236,13 +1265,16 @@
files = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-santad-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
23869BA352E2C86DEFE62819 /* [CP] Copy Pods Resources */ = {
Expand Down Expand Up @@ -1296,13 +1328,16 @@
files = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-LogicTests-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
B193461D3612BCB47C16E407 /* [CP] Check Pods Manifest.lock */ = {
Expand All @@ -1311,13 +1346,16 @@
files = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Santa-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
BA20035148DDEF5808B2C7EF /* [CP] Embed Pods Frameworks */ = {
Expand Down Expand Up @@ -1358,13 +1396,16 @@
files = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-santactl-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
D49A3AB950AFD99741E9AF89 /* [CP] Embed Pods Frameworks */ = {
Expand Down Expand Up @@ -1465,6 +1506,7 @@
0D41DAD41A7C28C800A890FE /* SNTEventTableTest.m in Sources */,
0D3AFBEE18FB4C6C0087BCEE /* SNTApplication.m in Sources */,
0DD0D48F194F78F8005F27EB /* SNTFileInfoTest.m in Sources */,
81A00E801FD74F9100A84676 /* SNTCompilerController.m in Sources */,
0DC5D86E191AED220078A5C0 /* SNTRuleTable.m in Sources */,
0DD0D492194F9BEF005F27EB /* SNTLogging.m in Sources */,
0DE71A761B95F7F900518526 /* SNTCachedDecision.m in Sources */,
Expand Down Expand Up @@ -1574,6 +1616,7 @@
0D377C2A17A071B7008453DB /* SNTEventTable.m in Sources */,
0DE50F681912716A007B2B0C /* SNTRule.m in Sources */,
0DB77FD81CCE824A004DF060 /* SNTBlockMessage.m in Sources */,
81A00E7F1FD74F8E00A84676 /* SNTCompilerController.m in Sources */,
0D37C10F18F6029A0069BC61 /* SNTDatabaseTable.m in Sources */,
0D42D2B819D2042900955F08 /* SNTConfigurator.m in Sources */,
0DCD605519115D17006B445C /* SNTXPCControlInterface.m in Sources */,
Expand Down
5 changes: 5 additions & 0 deletions Source/common/SNTCommonEnums.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ typedef NS_ENUM(NSInteger, SNTRuleState) {
SNTRuleStateBlacklist = 2,
SNTRuleStateSilentBlacklist = 3,
SNTRuleStateRemove = 4,

SNTRuleStateWhitelistCompiler = 5,
SNTRuleStateWhitelistTransitive = 6,
};

typedef NS_ENUM(NSInteger, SNTClientMode) {
Expand All @@ -58,6 +61,8 @@ typedef NS_ENUM(NSInteger, SNTEventState) {
SNTEventStateAllowBinary = 1 << 25,
SNTEventStateAllowCertificate = 1 << 26,
SNTEventStateAllowScope = 1 << 27,
SNTEventStateAllowCompiler = 1 << 28,
SNTEventStateAllowTransitive = 1 << 29,

// Block and Allow masks
SNTEventStateBlock = 0xFF << 16,
Expand Down
4 changes: 3 additions & 1 deletion Source/common/SNTKernelCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ enum SantaDriverMethods {

typedef enum {
QUEUETYPE_DECISION,
QUEUETYPE_LOG
QUEUETYPE_LOG,
QUEUETYPE_COMPILER,
} santa_queuetype_t;

// Enum defining actions that can be passed down the IODataQueue and in
Expand All @@ -71,6 +72,7 @@ typedef enum {
ACTION_NOTIFY_LINK = 33,
ACTION_NOTIFY_EXCHANGE = 34,
ACTION_NOTIFY_DELETE = 35,
ACTION_NOTIFY_CLOSE = 36,

// ERROR
ACTION_ERROR = 99,
Expand Down
81 changes: 78 additions & 3 deletions Source/santa-driver/SantaDecisionManager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The 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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


#define super OSObject
OSDefineMetaClassAndStructors(SantaDecisionManager, OSObject);

Expand All @@ -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);
Expand All @@ -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;

Expand All @@ -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;
Expand All @@ -82,6 +99,7 @@ void SantaDecisionManager::free() {

OSSafeReleaseNULL(decision_dataqueue_);
OSSafeReleaseNULL(log_dataqueue_);
OSSafeReleaseNULL(compiler_dataqueue_);

super::free();
}
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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_);
}
}

Expand All @@ -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();
}
Expand All @@ -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() {
Expand Down Expand Up @@ -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_--;
}
Copy link
Contributor

Choose a reason for hiding this comment

The 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() {
Expand Down Expand Up @@ -495,6 +550,7 @@ void SantaDecisionManager::FileOpCallback(
message->ppid = (val & ~0xFFFFFFFF00000000);
}
PostToLogQueue(message);
PostToCompilerQueue(message);
delete message;
return;
}
Expand All @@ -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;
Expand All @@ -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;
}
}
Expand All @@ -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);
Expand Down Expand Up @@ -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();
}

Expand Down
Loading