summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--server/StrictController.cpp24
-rw-r--r--server/StrictControllerTest.cpp13
2 files changed, 26 insertions, 11 deletions
diff --git a/server/StrictController.cpp b/server/StrictController.cpp
index ea25b2ea..04c1bfec 100644
--- a/server/StrictController.cpp
+++ b/server/StrictController.cpp
@@ -157,6 +157,13 @@ int StrictController::disableStrict(void) {
}
int StrictController::setUidCleartextPenalty(uid_t uid, StrictPenalty penalty) {
+ // When a penalty is set, we don't know what penalty the UID previously had. In order to be able
+ // to clear the previous penalty without causing an iptables error by deleting rules that don't
+ // exist, put each UID's rules in a chain specific to that UID. That way, the commands we need
+ // to run to clear the previous penalty don't depend on what the penalty actually was - all we
+ // need to do is clear the chain.
+ std::string perUidChain = StringPrintf("st_clear_caught_%u", uid);
+
std::vector<std::string> commands;
if (penalty == ACCEPT) {
// Clean up any old rules
@@ -165,21 +172,24 @@ int StrictController::setUidCleartextPenalty(uid_t uid, StrictPenalty penalty) {
StringPrintf("-D %s -m owner --uid-owner %d -j %s",
LOCAL_OUTPUT, uid, LOCAL_CLEAR_DETECT),
StringPrintf("-D %s -m owner --uid-owner %d -j %s",
- LOCAL_CLEAR_CAUGHT, uid, LOCAL_PENALTY_LOG),
- StringPrintf("-D %s -m owner --uid-owner %d -j %s",
- LOCAL_CLEAR_CAUGHT, uid, LOCAL_PENALTY_REJECT),
+ LOCAL_CLEAR_CAUGHT, uid, perUidChain.c_str()),
+ StringPrintf("-F %s", perUidChain.c_str()),
+ StringPrintf("-X %s", perUidChain.c_str()),
};
} else {
// Always take a detour to investigate this UID
commands.push_back("*filter");
+ commands.push_back(StringPrintf(":%s -", perUidChain.c_str()));
commands.push_back(StringPrintf("-I %s -m owner --uid-owner %d -j %s",
LOCAL_OUTPUT, uid, LOCAL_CLEAR_DETECT));
+ commands.push_back(StringPrintf("-I %s -m owner --uid-owner %d -j %s",
+ LOCAL_CLEAR_CAUGHT, uid, perUidChain.c_str()));
+
if (penalty == LOG) {
- commands.push_back(StringPrintf("-I %s -m owner --uid-owner %d -j %s",
- LOCAL_CLEAR_CAUGHT, uid, LOCAL_PENALTY_LOG));
+ commands.push_back(StringPrintf("-A %s -j %s", perUidChain.c_str(), LOCAL_PENALTY_LOG));
} else if (penalty == REJECT) {
- commands.push_back(StringPrintf("-I %s -m owner --uid-owner %d -j %s",
- LOCAL_CLEAR_CAUGHT, uid, LOCAL_PENALTY_REJECT));
+ commands.push_back(StringPrintf("-A %s -j %s", perUidChain.c_str(),
+ LOCAL_PENALTY_REJECT));
}
}
commands.push_back("COMMIT\n");
diff --git a/server/StrictControllerTest.cpp b/server/StrictControllerTest.cpp
index 82d0cdaf..9770352c 100644
--- a/server/StrictControllerTest.cpp
+++ b/server/StrictControllerTest.cpp
@@ -126,20 +126,25 @@ TEST_F(StrictControllerTest, TestSetUidCleartextPenalty) {
std::vector<std::string> acceptCommands = {
"*filter\n"
"-D st_OUTPUT -m owner --uid-owner 12345 -j st_clear_detect\n"
- "-D st_clear_caught -m owner --uid-owner 12345 -j st_penalty_log\n"
- "-D st_clear_caught -m owner --uid-owner 12345 -j st_penalty_reject\n"
+ "-D st_clear_caught -m owner --uid-owner 12345 -j st_clear_caught_12345\n"
+ "-F st_clear_caught_12345\n"
+ "-X st_clear_caught_12345\n"
"COMMIT\n"
};
std::vector<std::string> logCommands = {
"*filter\n"
+ ":st_clear_caught_12345 -\n"
"-I st_OUTPUT -m owner --uid-owner 12345 -j st_clear_detect\n"
- "-I st_clear_caught -m owner --uid-owner 12345 -j st_penalty_log\n"
+ "-I st_clear_caught -m owner --uid-owner 12345 -j st_clear_caught_12345\n"
+ "-A st_clear_caught_12345 -j st_penalty_log\n"
"COMMIT\n"
};
std::vector<std::string> rejectCommands = {
"*filter\n"
+ ":st_clear_caught_12345 -\n"
"-I st_OUTPUT -m owner --uid-owner 12345 -j st_clear_detect\n"
- "-I st_clear_caught -m owner --uid-owner 12345 -j st_penalty_reject\n"
+ "-I st_clear_caught -m owner --uid-owner 12345 -j st_clear_caught_12345\n"
+ "-A st_clear_caught_12345 -j st_penalty_reject\n"
"COMMIT\n"
};