Skip to content

Commit

Permalink
Merge 83e3b8d into e31aa5c
Browse files Browse the repository at this point in the history
  • Loading branch information
pmarkowsky committed Mar 20, 2024
2 parents e31aa5c + 83e3b8d commit 5a8c288
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 13 deletions.
48 changes: 35 additions & 13 deletions Source/santad/DataLayer/SNTRuleTable.m
Original file line number Diff line number Diff line change
Expand Up @@ -463,25 +463,47 @@ - (BOOL)addRules:(NSArray *)rules
}

- (BOOL)addedRulesShouldFlushDecisionCache:(NSArray *)rules {
// Check for non-plain-allowlist rules first before querying the database.
uint64_t blockingRuleCount = 0;

for (SNTRule *rule in rules) {
if (rule.state != SNTRuleStateAllow) return YES;
if (rule.state != SNTRuleStateAllow) {
blockingRuleCount++;
}
}

// If still here, then all rules in the array are allowlist rules. So now we look for allowlist
// rules where there is a previously existing allowlist compiler rule for the same identifier.
// If so we find such a rule, then cache should be flushed.
// Just flush if we have a lot of block rules.
if (blockingRuleCount >= 1000) {
return YES;
}

// Check newly synced rules for any blocking rules. If any are found, check
// in the db to see if they already exist. If they're not found or were
// previously allow rules flush the cache.
//
// If all rules in the array are allowlist rules, look for allowlist rules
// where there is a previously existing allowlist compiler rule for the same
// identifier. If so we find such a rule, then cache should be flushed.
__block BOOL flushDecisionCache = NO;

[self inTransaction:^(FMDatabase *db, BOOL *rollback) {
for (SNTRule *rule in rules) {
// Allowlist certificate rules are ignored
if (rule.type == SNTRuleTypeCertificate) continue;

if ([db longForQuery:
@"SELECT COUNT(*) FROM rules WHERE identifier=? AND type=? AND state=? LIMIT 1",
rule.identifier, @(SNTRuleTypeBinary), @(SNTRuleStateAllowCompiler)] > 0) {
flushDecisionCache = YES;
break;
if (rule.state != SNTRuleStateAllow) {
if ([db longForQuery:
@"SELECT COUNT(*) FROM rules WHERE identifier=? AND type=? AND state=? LIMIT 1",
rule.identifier, @(rule.type), @(rule.state)] == 0) {
flushDecisionCache = YES;
break;
}

// Allowlist certificate rules are ignored
if (rule.type == SNTRuleTypeCertificate) continue;

if ([db longForQuery:
@"SELECT COUNT(*) FROM rules WHERE identifier=? AND type=? AND state=? LIMIT 1",
rule.identifier, @(SNTRuleTypeBinary), @(SNTRuleStateAllowCompiler)] > 0) {
flushDecisionCache = YES;
break;
}
}
}
}];
Expand Down
42 changes: 42 additions & 0 deletions Source/santad/DataLayer/SNTRuleTableTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -437,4 +437,46 @@ - (void)testRetrieveAllRulesWithMultipleRules {
XCTAssertEqualObjects(rules[4], [self _exampleCDHashRule]);
}

- (void)testAddedRulesShouldFlushDecisionCacheWithNewBlockRule {
// Ensure that a brand new block rule flushes the decision cache.
NSError *error;
SNTRule *r = [self _exampleBinaryRule];
[self.sut addRules:@[ r ] ruleCleanup:SNTRuleCleanupNone error:&error];
XCTAssertNil(error);
XCTAssertEqual(self.sut.ruleCount, 1);
XCTAssertEqual(self.sut.binaryRuleCount, 1);

// Change the identifer so that the hash of a block rule is not found in the
// db.
r.identifier = @"bfff7d3f6c389ebf7a76a666c484d42ea447834901bc29141439ae7c7b96ff09";
XCTAssertEqual(YES, [self.sut addedRulesShouldFlushDecisionCache:@[ r ]]);
}

- (void)testAddedRulesShouldFlushDecisionCacheWithOldBlockRule {
// Ensure that a brand new block rule flushes the decision cache.
NSError *error;
SNTRule *r = [self _exampleBinaryRule];
[self.sut addRules:@[ r ] ruleCleanup:SNTRuleCleanupNone error:&error];
XCTAssertNil(error);
XCTAssertEqual(self.sut.ruleCount, 1);
XCTAssertEqual(self.sut.binaryRuleCount, 1);
XCTAssertEqual(NO, [self.sut addedRulesShouldFlushDecisionCache:@[ r ]]);
}

- (void)testAddedRulesShouldFlushDecisionCacheWithLargeNumberOfBlocks {
// Ensure that a brand new block rule flushes the decision cache.
NSError *error;
SNTRule *r = [self _exampleBinaryRule];
[self.sut addRules:@[ r ] ruleCleanup:SNTRuleCleanupNone error:&error];
XCTAssertNil(error);
XCTAssertEqual(self.sut.ruleCount, 1);
XCTAssertEqual(self.sut.binaryRuleCount, 1);
NSMutableArray<SNTRule *> *newRules = [NSMutableArray array];
for (int i = 0; i < 1000; i++) {
newRules[i] = r;
}

XCTAssertEqual(YES, [self.sut addedRulesShouldFlushDecisionCache:newRules]);
}

@end

0 comments on commit 5a8c288

Please sign in to comment.