Firewall-related commands porting
Test: built, flashed, booted
system/netd/tests/runtests.sh passes
Change-Id: I0fcf6ac4e5d96cbf63d6752bee7202cdef940e82
diff --git a/server/BandwidthController.cpp b/server/BandwidthController.cpp
index 5669a96..6a40ba2 100644
--- a/server/BandwidthController.cpp
+++ b/server/BandwidthController.cpp
@@ -72,9 +72,10 @@
using android::base::Join;
using android::base::StringAppendF;
using android::base::StringPrintf;
+using android::net::FirewallController;
using android::net::gCtls;
-using android::netdutils::StatusOr;
using android::netdutils::Status;
+using android::netdutils::StatusOr;
using android::netdutils::UniqueFile;
namespace {
diff --git a/server/CommandListener.cpp b/server/CommandListener.cpp
index 4e1887f..7629c9a 100644
--- a/server/CommandListener.cpp
+++ b/server/CommandListener.cpp
@@ -1058,11 +1058,7 @@
}
FirewallType firewallType = parseFirewallType(argv[2]);
- int res = gCtls->firewallCtrl.enableFirewall(firewallType);
- return sendGenericOkFail(cli, res);
- }
- if (!strcmp(argv[1], "disable")) {
- int res = gCtls->firewallCtrl.disableFirewall();
+ int res = gCtls->firewallCtrl.setFirewallType(firewallType);
return sendGenericOkFail(cli, res);
}
if (!strcmp(argv[1], "is_enabled")) {
diff --git a/server/FirewallController.cpp b/server/FirewallController.cpp
index 4e5e3e5..890ab5b 100644
--- a/server/FirewallController.cpp
+++ b/server/FirewallController.cpp
@@ -59,6 +59,9 @@
} // namespace
+namespace android {
+namespace net {
+
auto FirewallController::execIptablesRestore = ::execIptablesRestore;
const char* FirewallController::TABLE = "filter";
@@ -101,11 +104,11 @@
return res;
}
-int FirewallController::enableFirewall(FirewallType ftype) {
+int FirewallController::setFirewallType(FirewallType ftype) {
int res = 0;
if (mFirewallType != ftype) {
// flush any existing rules
- disableFirewall();
+ resetFirewall();
if (ftype == WHITELIST) {
// create default rule to drop all traffic
@@ -121,10 +124,10 @@
// Set this after calling disableFirewall(), since it defaults to WHITELIST there
mFirewallType = ftype;
}
- return res;
+ return res ? -EREMOTEIO : 0;
}
-int FirewallController::disableFirewall(void) {
+int FirewallController::resetFirewall(void) {
mFirewallType = WHITELIST;
mIfaceRules.clear();
@@ -136,7 +139,7 @@
":fw_FORWARD -\n"
"COMMIT\n";
- return execIptablesRestore(V4V6, command.c_str());
+ return (execIptablesRestore(V4V6, command.c_str()) == 0) ? 0 : -EREMOTEIO;
}
int FirewallController::enableChildChains(ChildChain chain, bool enable) {
@@ -177,12 +180,12 @@
int FirewallController::setInterfaceRule(const char* iface, FirewallRule rule) {
if (mFirewallType == BLACKLIST) {
// Unsupported in BLACKLIST mode
- return -1;
+ return -EINVAL;
}
if (!isIfaceName(iface)) {
errno = ENOENT;
- return -1;
+ return -ENOENT;
}
// Only delete rules if we actually added them, because otherwise our iptables-restore
@@ -205,7 +208,7 @@
StringPrintf("%s fw_OUTPUT -o %s -j RETURN", op, iface),
"COMMIT\n"
}, "\n");
- return execIptablesRestore(V4V6, command);
+ return (execIptablesRestore(V4V6, command) == 0) ? 0 : -EREMOTEIO;
}
FirewallType FirewallController::getFirewallType(ChildChain chain) {
@@ -253,7 +256,7 @@
break;
default:
ALOGW("Unknown child chain: %d", chain);
- return -1;
+ return -EINVAL;
}
if (mUseBpfOwnerMatch) {
return gCtls->trafficCtrl.changeUidOwnerRule(chain, uid, rule, firewallType);
@@ -266,7 +269,7 @@
}
StringAppendF(&command, "COMMIT\n");
- return execIptablesRestore(V4V6, command);
+ return (execIptablesRestore(V4V6, command) == 0) ? 0 : -EREMOTEIO;
}
int FirewallController::createChain(const char* chain, FirewallType type) {
@@ -393,3 +396,6 @@
return maxUid;
}
+
+} // namespace net
+} // namespace android
\ No newline at end of file
diff --git a/server/FirewallController.h b/server/FirewallController.h
index c43e94e..a7082da 100644
--- a/server/FirewallController.h
+++ b/server/FirewallController.h
@@ -23,16 +23,27 @@
#include <string>
#include <vector>
+#include "android/net/INetd.h"
+
#include "NetdConstants.h"
-enum FirewallRule { DENY, ALLOW };
+namespace android {
+namespace net {
+
+enum FirewallRule { ALLOW = INetd::FIREWALL_RULE_ALLOW, DENY = INetd::FIREWALL_RULE_DENY };
// WHITELIST means the firewall denies all by default, uids must be explicitly ALLOWed
// BLACKLIST means the firewall allows all by default, uids must be explicitly DENYed
-enum FirewallType { WHITELIST, BLACKLIST };
+enum FirewallType { WHITELIST = INetd::FIREWALL_WHITELIST, BLACKLIST = INetd::FIREWALL_BLACKLIST };
-enum ChildChain { NONE, DOZABLE, STANDBY, POWERSAVE, INVALID_CHAIN };
+enum ChildChain {
+ NONE = INetd::FIREWALL_CHAIN_NONE,
+ DOZABLE = INetd::FIREWALL_CHAIN_DOZABLE,
+ STANDBY = INetd::FIREWALL_CHAIN_STANDBY,
+ POWERSAVE = INetd::FIREWALL_CHAIN_POWERSAVE,
+ INVALID_CHAIN
+};
/*
* Simple firewall that drops all packets except those matching explicitly
@@ -48,8 +59,8 @@
int setupIptablesHooks(void);
- int enableFirewall(FirewallType);
- int disableFirewall(void);
+ int setFirewallType(FirewallType);
+ int resetFirewall(void);
int isFirewallEnabled(void);
/* Match traffic going in/out over the given iface. */
@@ -100,4 +111,7 @@
FirewallType getFirewallType(ChildChain);
};
+} // namespace net
+} // namespace android
+
#endif
diff --git a/server/FirewallControllerTest.cpp b/server/FirewallControllerTest.cpp
index 240c85d..836adb8 100644
--- a/server/FirewallControllerTest.cpp
+++ b/server/FirewallControllerTest.cpp
@@ -33,6 +33,9 @@
using android::base::StringPrintf;
using android::base::WriteStringToFile;
+namespace android {
+namespace net {
+
class FirewallControllerTest : public IptablesBaseTest {
protected:
FirewallControllerTest() {
@@ -51,7 +54,6 @@
}
};
-
TEST_F(FirewallControllerTest, TestCreateWhitelistChain) {
std::vector<std::string> expectedRestore4 = {
"*filter",
@@ -241,16 +243,16 @@
};
std::vector<std::string> noCommands = {};
- EXPECT_EQ(0, mFw.disableFirewall());
+ EXPECT_EQ(0, mFw.resetFirewall());
expectIptablesRestoreCommands(disableCommands);
- EXPECT_EQ(0, mFw.disableFirewall());
+ EXPECT_EQ(0, mFw.resetFirewall());
expectIptablesRestoreCommands(disableCommands);
- EXPECT_EQ(0, mFw.enableFirewall(BLACKLIST));
+ EXPECT_EQ(0, mFw.setFirewallType(BLACKLIST));
expectIptablesRestoreCommands(disableCommands);
- EXPECT_EQ(0, mFw.enableFirewall(BLACKLIST));
+ EXPECT_EQ(0, mFw.setFirewallType(BLACKLIST));
expectIptablesRestoreCommands(noCommands);
std::vector<std::string> disableEnableCommands;
@@ -259,7 +261,7 @@
disableEnableCommands.insert(
disableEnableCommands.end(), enableCommands.begin(), enableCommands.end());
- EXPECT_EQ(0, mFw.enableFirewall(WHITELIST));
+ EXPECT_EQ(0, mFw.setFirewallType(WHITELIST));
expectIptablesRestoreCommands(disableEnableCommands);
std::vector<std::string> ifaceCommands = {
@@ -286,15 +288,15 @@
EXPECT_EQ(0, mFw.setInterfaceRule("rmnet_data0", DENY));
expectIptablesRestoreCommands(noCommands);
- EXPECT_EQ(0, mFw.enableFirewall(WHITELIST));
+ EXPECT_EQ(0, mFw.setFirewallType(WHITELIST));
expectIptablesRestoreCommands(noCommands);
- EXPECT_EQ(0, mFw.disableFirewall());
+ EXPECT_EQ(0, mFw.resetFirewall());
expectIptablesRestoreCommands(disableCommands);
- // TODO: calling disableFirewall and then enableFirewall(WHITELIST) does
+ // TODO: calling resetFirewall and then setFirewallType(WHITELIST) does
// nothing. This seems like a clear bug.
- EXPECT_EQ(0, mFw.enableFirewall(WHITELIST));
+ EXPECT_EQ(0, mFw.setFirewallType(WHITELIST));
expectIptablesRestoreCommands(noCommands);
}
@@ -344,3 +346,6 @@
EXPECT_NE(0, access(tempFile.c_str(), F_OK));
EXPECT_EQ(4294967294, FirewallController::discoverMaximumValidUid(tempFile));
}
+
+} // namespace net
+} // namespace android
\ No newline at end of file
diff --git a/server/InterfaceController.cpp b/server/InterfaceController.cpp
index 7006fee..fde7f4f 100644
--- a/server/InterfaceController.cpp
+++ b/server/InterfaceController.cpp
@@ -21,7 +21,6 @@
#include <sys/socket.h>
#include <functional>
-
#define LOG_TAG "InterfaceController"
#include <android-base/file.h>
#include <android-base/properties.h>
diff --git a/server/NetdHwService.h b/server/NetdHwService.h
index a814fe4..458c6fa 100644
--- a/server/NetdHwService.h
+++ b/server/NetdHwService.h
@@ -19,16 +19,16 @@
#include <android/system/net/netd/1.1/INetd.h>
-using android::hardware::Return;
-using android::hardware::hidl_string;
-using android::system::net::netd::V1_1::INetd;
-using StatusCode = android::system::net::netd::V1_1::INetd::StatusCode;
-
namespace android {
namespace net {
-class NetdHwService : public INetd {
-public:
+using android::hardware::Return;
+using android::hardware::hidl_string;
+using INetdHw = android::system::net::netd::V1_1::INetd;
+using StatusCode = android::system::net::netd::V1_1::INetd::StatusCode;
+
+class NetdHwService : INetdHw {
+ public:
// 1.0
status_t start();
Return<void> createOemNetwork(createOemNetwork_cb _hidl_cb) override;
diff --git a/server/NetdNativeService.cpp b/server/NetdNativeService.cpp
index 09b7efc..1e993c1 100644
--- a/server/NetdNativeService.cpp
+++ b/server/NetdNativeService.cpp
@@ -959,6 +959,7 @@
gLog.log(entry.returns(res).withAutomaticDuration());
return statusFromErrcode(res);
}
+
binder::Status NetdNativeService::clatdStart(const std::string& ifName) {
NETD_LOCKING_RPC(NETWORK_STACK, gCtls->clatdCtrl.mutex);
auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(ifName);
@@ -1259,5 +1260,95 @@
return binder::Status::ok();
}
+namespace {
+std::string ruleToString(int32_t rule) {
+ switch (rule) {
+ case INetd::FIREWALL_RULE_DENY:
+ return "DENY";
+ case INetd::FIREWALL_RULE_ALLOW:
+ return "ALLOW";
+ default:
+ return "INVALID";
+ }
+}
+
+std::string typeToString(int32_t type) {
+ switch (type) {
+ case INetd::FIREWALL_WHITELIST:
+ return "WHITELIST";
+ case INetd::FIREWALL_BLACKLIST:
+ return "BLACKLIST";
+ default:
+ return "INVALID";
+ }
+}
+
+std::string chainToString(int32_t chain) {
+ switch (chain) {
+ case INetd::FIREWALL_CHAIN_NONE:
+ return "NONE";
+ case INetd::FIREWALL_CHAIN_DOZABLE:
+ return "DOZABLE";
+ case INetd::FIREWALL_CHAIN_STANDBY:
+ return "STANDBY";
+ case INetd::FIREWALL_CHAIN_POWERSAVE:
+ return "POWERSAVE";
+ default:
+ return "INVALID";
+ }
+}
+
+} // namespace
+
+binder::Status NetdNativeService::firewallSetFirewallType(int32_t firewallType) {
+ NETD_LOCKING_RPC(NETWORK_STACK, gCtls->firewallCtrl.lock);
+ auto entry =
+ gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(typeToString(firewallType));
+ auto type = static_cast<FirewallType>(firewallType);
+
+ int res = gCtls->firewallCtrl.setFirewallType(type);
+ gLog.log(entry.returns(res).withAutomaticDuration());
+ return statusFromErrcode(res);
+}
+
+binder::Status NetdNativeService::firewallSetInterfaceRule(const std::string& ifName,
+ int32_t firewallRule) {
+ NETD_LOCKING_RPC(NETWORK_STACK, gCtls->firewallCtrl.lock);
+ auto entry = gLog.newEntry()
+ .prettyFunction(__PRETTY_FUNCTION__)
+ .args(ifName, ruleToString(firewallRule));
+ auto rule = static_cast<FirewallRule>(firewallRule);
+
+ int res = gCtls->firewallCtrl.setInterfaceRule(ifName.c_str(), rule);
+ gLog.log(entry.returns(res).withAutomaticDuration());
+ return statusFromErrcode(res);
+}
+
+binder::Status NetdNativeService::firewallSetUidRule(int32_t childChain, int32_t uid,
+ int32_t firewallRule) {
+ NETD_LOCKING_RPC(NETWORK_STACK, gCtls->firewallCtrl.lock);
+ auto entry = gLog.newEntry()
+ .prettyFunction(__PRETTY_FUNCTION__)
+ .args(chainToString(childChain), uid, ruleToString(firewallRule));
+ auto chain = static_cast<ChildChain>(childChain);
+ auto rule = static_cast<FirewallRule>(firewallRule);
+
+ int res = gCtls->firewallCtrl.setUidRule(chain, uid, rule);
+ gLog.log(entry.returns(res).withAutomaticDuration());
+ return statusFromErrcode(res);
+}
+
+binder::Status NetdNativeService::firewallEnableChildChain(int32_t childChain, bool enable) {
+ NETD_LOCKING_RPC(NETWORK_STACK, gCtls->firewallCtrl.lock);
+ auto entry = gLog.newEntry()
+ .prettyFunction(__PRETTY_FUNCTION__)
+ .args(chainToString(childChain), enable);
+ auto chain = static_cast<ChildChain>(childChain);
+
+ int res = gCtls->firewallCtrl.enableChildChains(chain, enable);
+ gLog.log(entry.returns(res).withAutomaticDuration());
+ return statusFromErrcode(res);
+}
+
} // namespace net
} // namespace android
diff --git a/server/NetdNativeService.h b/server/NetdNativeService.h
index 1d5caf6..77179cd 100644
--- a/server/NetdNativeService.h
+++ b/server/NetdNativeService.h
@@ -40,6 +40,12 @@
binder::Status firewallReplaceUidChain(
const std::string& chainName, bool isWhitelist,
const std::vector<int32_t>& uids, bool *ret) override;
+ binder::Status firewallSetFirewallType(int32_t firewallType) override;
+ binder::Status firewallSetInterfaceRule(const std::string& ifName,
+ int32_t firewallRule) override;
+ binder::Status firewallSetUidRule(int32_t childChain, int32_t uid,
+ int32_t firewallRule) override;
+ binder::Status firewallEnableChildChain(int32_t childChain, bool enable) override;
// Bandwidth control commands.
binder::Status bandwidthEnableDataSaver(bool enable, bool *ret) override;
@@ -249,6 +255,8 @@
private:
std::vector<uid_t> intsToUids(const std::vector<int32_t>& intUids);
Permission convertPermission(int32_t permission);
+ static FirewallRule parseRule(int32_t firewallRule);
+ static ChildChain parseChildChain(int32_t childChain);
};
} // namespace net
diff --git a/server/binder/android/net/INetd.aidl b/server/binder/android/net/INetd.aidl
index 19a3e40..395d706 100644
--- a/server/binder/android/net/INetd.aidl
+++ b/server/binder/android/net/INetd.aidl
@@ -996,4 +996,66 @@
* @return true if the user can protect sockets from VPN, false otherwise.
*/
boolean networkCanProtect(int uid);
+
+ // Whitelist only allows packets from specific UID/Interface
+ const int FIREWALL_WHITELIST = 0;
+ // Blacklist blocks packets from specific UID/Interface
+ const int FIREWALL_BLACKLIST = 1;
+
+ /**
+ * Set type of firewall
+ * Type whitelist only allows packets from specific UID/Interface
+ * Type blacklist blocks packets from specific UID/Interface
+ *
+ * @param firewalltype type of firewall, either FIREWALL_WHITELIST or FIREWALL_BLACKLIST
+ * @throws ServiceSpecificException in case of failure, with an error code indicating the
+ * cause of the the failure.
+ */
+ void firewallSetFirewallType(int firewalltype);
+
+ // Specify allow Rule which allows packets
+ const int FIREWALL_RULE_ALLOW = 1;
+ // Specify deny Rule which drops packets
+ const int FIREWALL_RULE_DENY = 2;
+
+ // No specific chain is chosen, use general firewall chain(fw_input, fw_output)
+ const int FIREWALL_CHAIN_NONE = 0;
+ // Specify DOZABLE chain(fw_dozable) which is used in dozable mode
+ const int FIREWALL_CHAIN_DOZABLE = 1;
+ // Specify STANDBY chain(fw_standby) which is used in standby mode
+ const int FIREWALL_CHAIN_STANDBY = 2;
+ // Specify POWERSAVE chain(fw_powersave) which is used in power save mode
+ const int FIREWALL_CHAIN_POWERSAVE = 3;
+
+ /**
+ * Set firewall rule for interface
+ *
+ * @param ifName the interface to allow/deny
+ * @param firewallRule either FIREWALL_RULE_ALLOW or FIREWALL_RULE_DENY
+ * @throws ServiceSpecificException in case of failure, with an error code indicating the
+ * cause of the the failure.
+ */
+ void firewallSetInterfaceRule(in @utf8InCpp String ifName, int firewallRule);
+
+ /**
+ * Set firewall rule for uid
+ *
+ * @param childChain target chain
+ * @param uid uid to allow/deny
+ * @param firewallRule either FIREWALL_RULE_ALLOW or FIREWALL_RULE_DENY
+ * @throws ServiceSpecificException in case of failure, with an error code indicating the
+ * cause of the the failure.
+ */
+ void firewallSetUidRule(int childChain, int uid, int firewallRule);
+
+ /**
+ * Enable/Disable target firewall child chain
+ *
+ * @param childChain target chain to enable
+ * @param enable whether to enable or disable child chain.
+ * @throws ServiceSpecificException in case of failure, with an error code indicating the
+ * cause of the the failure.
+ */
+ void firewallEnableChildChain(int childChain, boolean enable);
+
}