permission_broker: Remove firewall from permission broker
Remove all references of firewall inside port_tracker
and remove firewall from permission broker.
Instead of calling firewall, port_tracker now calls
patchpanel's DBus API ModifyPortRule. With this change
firewall fuzzer is inactive.
BUG=b:160130580
TEST=FEATURES=test emerge-rammus permission_broker
TEST=USE="asan fuzzer" emerge-atlas permission_broker
TEST=/usr/libexec/fuzzers/port_tracker_fuzzer
TEST=tast run <DUT> platform.Firewall
Cq-Depend: chromium:2291496
Change-Id: Ibb2e4d278c9003af931df19d73c7d1c55bbcb28d
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2291865
Commit-Queue: Jason Jeremy Iman <jasongustaman@chromium.org>
Tested-by: Jason Jeremy Iman <jasongustaman@chromium.org>
Reviewed-by: Jorge Lucangeli Obes <jorgelo@chromium.org>
diff --git a/permission_broker/BUILD.gn b/permission_broker/BUILD.gn
index 50955fd..9215149 100644
--- a/permission_broker/BUILD.gn
+++ b/permission_broker/BUILD.gn
@@ -11,10 +11,7 @@
deps += [ ":permission_broker_test" ]
}
if (use.fuzzer) {
- deps += [
- ":firewall_fuzzer",
- ":port_tracker_fuzzer",
- ]
+ deps += [ ":port_tracker_fuzzer" ]
}
}
@@ -64,7 +61,6 @@
"deny_unsafe_hidraw_device_rule.cc",
"deny_usb_device_class_rule.cc",
"deny_usb_vendor_id_rule.cc",
- "firewall.cc",
"hidraw_subsystem_udev_rule.cc",
"libusb_wrapper.cc",
"permission_broker.cc",
@@ -112,9 +108,7 @@
"deny_usb_device_class_rule_test.cc",
"deny_usb_vendor_id_rule_test.cc",
"fake_libusb_wrapper.cc",
- "firewall_test.cc",
"group_tty_device_rule_test.cc",
- "mock_firewall.cc",
"port_tracker_test.cc",
"rule_engine_test.cc",
"rule_test.cc",
@@ -128,15 +122,6 @@
pkg_config("permission_broker_fuzzer_config") {
pkg_deps = [ "libchrome-test-${libbase_ver}" ]
}
- executable("firewall_fuzzer") {
- configs += [
- "//common-mk/common_fuzzer:common_fuzzer",
- ":permission_broker_fuzzer_config",
- ":target_defaults",
- ]
- deps = [ ":libpermission_broker" ]
- sources = [ "firewall_fuzzer.cc" ]
- }
executable("port_tracker_fuzzer") {
configs += [
"//common-mk/common_fuzzer:common_fuzzer",
diff --git a/permission_broker/firewall.cc b/permission_broker/firewall.cc
deleted file mode 100644
index f82fd7b..0000000
--- a/permission_broker/firewall.cc
+++ /dev/null
@@ -1,403 +0,0 @@
-// Copyright 2017 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "permission_broker/firewall.h"
-
-#include <arpa/inet.h>
-#include <linux/capability.h>
-#include <netinet/in.h>
-
-#include <string>
-#include <vector>
-
-#include <base/bind.h>
-#include <base/bind_helpers.h>
-#include <base/callback.h>
-#include <base/logging.h>
-#include <base/strings/string_number_conversions.h>
-#include <base/strings/string_util.h>
-#include <base/strings/stringprintf.h>
-#include <brillo/minijail/minijail.h>
-
-namespace {
-
-// Interface names must be shorter than 'IFNAMSIZ' chars.
-// See http://man7.org/linux/man-pages/man7/netdevice.7.html
-// 'IFNAMSIZ' is 16 in recent kernels.
-// See https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/if.h?h=v4.14#n33
-constexpr size_t kInterfaceNameSize = 16;
-
-// Interface names are passed directly to the 'iptables' command. Rather than
-// auditing 'iptables' source code to see how it handles malformed names,
-// do some sanitization on the names beforehand.
-bool IsValidInterfaceName(const std::string& iface) {
- // |iface| should be shorter than |kInterfaceNameSize| chars and have only
- // alphanumeric characters (embedded hypens and periods are also permitted).
- if (iface.length() >= kInterfaceNameSize) {
- return false;
- }
- if (base::StartsWith(iface, "-", base::CompareCase::SENSITIVE) ||
- base::EndsWith(iface, "-", base::CompareCase::SENSITIVE) ||
- base::StartsWith(iface, ".", base::CompareCase::SENSITIVE) ||
- base::EndsWith(iface, ".", base::CompareCase::SENSITIVE)) {
- return false;
- }
- for (auto c : iface) {
- if (!std::isalnum(c) && (c != '-') && (c != '.')) {
- return false;
- }
- }
- return true;
-}
-
-} // namespace
-
-namespace permission_broker {
-
-const char kIpTablesPath[] = "/sbin/iptables";
-const char kIp6TablesPath[] = "/sbin/ip6tables";
-
-const std::string ProtocolName(Protocol proto) {
- if (proto == ModifyPortRuleRequest::INVALID_PROTOCOL) {
- NOTREACHED() << "Unexpected L4 protocol value";
- }
- return base::ToLowerASCII(ModifyPortRuleRequest::Protocol_Name(proto));
-}
-
-bool Firewall::AddAcceptRules(Protocol protocol,
- uint16_t port,
- const std::string& interface) {
- if (port == 0U) {
- LOG(ERROR) << "Port 0 is not a valid port";
- return false;
- }
-
- if (!IsValidInterfaceName(interface)) {
- LOG(ERROR) << "Invalid interface name '" << interface << "'";
- return false;
- }
-
- if (!AddAcceptRule(kIpTablesPath, protocol, port, interface)) {
- LOG(ERROR) << "Could not add ACCEPT rule using '" << kIpTablesPath << "'";
- return false;
- }
-
- if (!AddAcceptRule(kIp6TablesPath, protocol, port, interface)) {
- LOG(ERROR) << "Could not add ACCEPT rule using '" << kIp6TablesPath
- << "', aborting operation";
- DeleteAcceptRule(kIpTablesPath, protocol, port, interface);
- return false;
- }
-
- return true;
-}
-
-bool Firewall::DeleteAcceptRules(Protocol protocol,
- uint16_t port,
- const std::string& interface) {
- if (port == 0U) {
- LOG(ERROR) << "Port 0 is not a valid port";
- return false;
- }
-
- if (!IsValidInterfaceName(interface)) {
- LOG(ERROR) << "Invalid interface name '" << interface << "'";
- return false;
- }
-
- bool ip4_success = DeleteAcceptRule(kIpTablesPath, protocol, port,
- interface);
- bool ip6_success = DeleteAcceptRule(kIp6TablesPath, protocol,
- port, interface);
- return ip4_success && ip6_success;
-}
-
-bool Firewall::AddIpv4ForwardRule(Protocol protocol,
- const std::string& input_ip,
- uint16_t port,
- const std::string& interface,
- const std::string& dst_ip,
- uint16_t dst_port) {
- if (!ModifyIpv4DNATRule(protocol, input_ip, port, interface, dst_ip, dst_port, "-I")) {
- return false;
- }
-
- if (!ModifyIpv4ForwardChain(protocol, interface, dst_ip, dst_port, "-A")) {
- ModifyIpv4DNATRule(protocol, input_ip, port, interface, dst_ip, dst_port, "-D");
- return false;
- }
-
- return true;
-}
-
-bool Firewall::DeleteIpv4ForwardRule(Protocol protocol,
- const std::string& input_ip,
- uint16_t port,
- const std::string& interface,
- const std::string& dst_ip,
- uint16_t dst_port) {
- bool success = true;
- if (!ModifyIpv4DNATRule(protocol, input_ip, port, interface, dst_ip, dst_port, "-D")) {
- success = false;
- }
- if (!ModifyIpv4ForwardChain(protocol, interface, dst_ip, dst_port, "-D")) {
- success = false;
- }
- return success;
-}
-
-bool Firewall::ModifyIpv4DNATRule(Protocol protocol,
- const std::string& input_ip,
- uint16_t port,
- const std::string& interface,
- const std::string& dst_ip,
- uint16_t dst_port,
- const std::string& operation) {
- struct in_addr addr;
- if (!input_ip.empty() && inet_pton(AF_INET, input_ip.c_str(), &addr) != 1) {
- LOG(ERROR) << "Invalid input IPv4 address '" << input_ip << "'";
- return false;
- }
-
- if (port == 0U) {
- LOG(ERROR) << "Port 0 is not a valid port";
- return false;
- }
-
- if (!IsValidInterfaceName(interface) || interface.empty()) {
- LOG(ERROR) << "Invalid interface name '" << interface << "'";
- return false;
- }
-
- if (inet_pton(AF_INET, dst_ip.c_str(), &addr) != 1) {
- LOG(ERROR) << "Invalid destination IPv4 address '" << dst_ip << "'";
- return false;
- }
-
- if (dst_port == 0U) {
- LOG(ERROR) << "Destination port 0 is not a valid port";
- return false;
- }
-
- // Only support deleting existing forwarding rules or inserting rules in the
- // first position: ARC++ generic inbound DNAT rule always need to go last.
- if (operation != "-I" && operation != "-D") {
- LOG(ERROR) << "Invalid chain operation '" << operation << "'";
- return false;
- }
-
- std::vector<std::string> argv{kIpTablesPath,
- "-t",
- "nat",
- operation,
- "PREROUTING",
- "-i",
- interface,
- "-p", // protocol
- ProtocolName(protocol)};
- if (!input_ip.empty()) {
- argv.push_back("-d"); // input destination ip
- argv.push_back(input_ip);
- }
- argv.push_back("--dport"); // input destination port
- argv.push_back(std::to_string(port));
- argv.push_back("-j");
- argv.push_back("DNAT");
- argv.push_back("--to-destination"); // new output destination ip:port
- argv.push_back(dst_ip + ":" + std::to_string(dst_port));
- argv.push_back("-w"); // Wait for xtables lock.
- return RunInMinijail(argv) == 0;
-}
-
-bool Firewall::ModifyIpv4ForwardChain(Protocol protocol,
- const std::string& interface,
- const std::string& dst_ip,
- uint16_t dst_port,
- const std::string& operation) {
- if (!IsValidInterfaceName(interface) || interface.empty()) {
- LOG(ERROR) << "Invalid interface name '" << interface << "'";
- return false;
- }
-
- struct in_addr addr;
- if (inet_pton(AF_INET, dst_ip.c_str(), &addr) != 1) {
- LOG(ERROR) << "Invalid IPv4 destination address '" << dst_ip << "'";
- return false;
- }
-
- if (dst_port == 0U) {
- LOG(ERROR) << "Destination port 0 is not a valid port";
- return false;
- }
-
- // Order does not matter for the FORWARD chain: both -A or -I are possible.
- if (operation != "-A" && operation != "-I" && operation != "-D") {
- LOG(ERROR) << "Invalid chain operation '" << operation << "'";
- return false;
- }
-
- std::vector<std::string> argv{
- kIpTablesPath,
- "-t",
- "filter",
- operation,
- "FORWARD",
- "-i",
- interface,
- "-p", // protocol
- ProtocolName(protocol),
- "-d", // destination ip
- dst_ip,
- "--dport", // destination port
- std::to_string(dst_port),
- "-j",
- "ACCEPT",
- "-w"}; // Wait for xtables lock.
- return RunInMinijail(argv) == 0;
-}
-
-bool Firewall::AddLoopbackLockdownRules(Protocol protocol, uint16_t port) {
- if (port == 0U) {
- LOG(ERROR) << "Port 0 is not a valid port";
- return false;
- }
-
- if (!AddLoopbackLockdownRule(kIpTablesPath, protocol, port)) {
- LOG(ERROR) << "Could not add loopback REJECT rule using '" << kIpTablesPath
- << "'";
- return false;
- }
-
- if (!AddLoopbackLockdownRule(kIp6TablesPath, protocol, port)) {
- LOG(ERROR) << "Could not add loopback REJECT rule using '" << kIp6TablesPath
- << "', aborting operation";
- DeleteLoopbackLockdownRule(kIpTablesPath, protocol, port);
- return false;
- }
-
- return true;
-}
-
-bool Firewall::DeleteLoopbackLockdownRules(Protocol protocol, uint16_t port) {
- if (port == 0U) {
- LOG(ERROR) << "Port 0 is not a valid port";
- return false;
- }
-
- bool ip4_success = DeleteLoopbackLockdownRule(kIpTablesPath, protocol, port);
- bool ip6_success = DeleteLoopbackLockdownRule(kIp6TablesPath, protocol, port);
- return ip4_success && ip6_success;
-}
-
-bool Firewall::AddAcceptRule(const std::string& executable_path,
- Protocol protocol,
- uint16_t port,
- const std::string& interface) {
- std::vector<std::string> argv{executable_path,
- "-I", // insert
- "INPUT",
- "-p", // protocol
- ProtocolName(protocol),
- "--dport", // destination port
- std::to_string(port)};
- if (!interface.empty()) {
- argv.push_back("-i"); // interface
- argv.push_back(interface);
- }
- argv.push_back("-j");
- argv.push_back("ACCEPT");
- argv.push_back("-w"); // Wait for xtables lock.
-
- return RunInMinijail(argv) == 0;
-}
-
-bool Firewall::DeleteAcceptRule(const std::string& executable_path,
- Protocol protocol,
- uint16_t port,
- const std::string& interface) {
- std::vector<std::string> argv{executable_path,
- "-D", // delete
- "INPUT",
- "-p", // protocol
- ProtocolName(protocol),
- "--dport", // destination port
- std::to_string(port)};
- if (!interface.empty()) {
- argv.push_back("-i"); // interface
- argv.push_back(interface);
- }
- argv.push_back("-j");
- argv.push_back("ACCEPT");
- argv.push_back("-w"); // Wait for xtables lock.
-
- return RunInMinijail(argv) == 0;
-}
-
-bool Firewall::AddLoopbackLockdownRule(const std::string& executable_path,
- Protocol protocol,
- uint16_t port) {
- std::vector<std::string> argv{
- executable_path,
- "-I", // insert
- "OUTPUT",
- "-p", // protocol
- ProtocolName(protocol),
- "--dport", // destination port
- std::to_string(port),
- "-o", // output interface
- "lo",
- "-m", // match extension
- "owner",
- "!",
- "--uid-owner",
- "chronos",
- "-j",
- "REJECT",
- "-w", // Wait for xtables lock.
- };
-
- return RunInMinijail(argv) == 0;
-}
-
-bool Firewall::DeleteLoopbackLockdownRule(const std::string& executable_path,
- Protocol protocol,
- uint16_t port) {
- std::vector<std::string> argv{
- executable_path,
- "-D", // delete
- "OUTPUT",
- "-p", // protocol
- ProtocolName(protocol),
- "--dport", // destination port
- std::to_string(port),
- "-o", // output interface
- "lo",
- "-m", // match extension
- "owner",
- "!",
- "--uid-owner",
- "chronos",
- "-j",
- "REJECT",
- "-w", // Wait for xtables lock.
- };
-
- return RunInMinijail(argv) == 0;
-}
-
-int Firewall::RunInMinijail(const std::vector<std::string>& argv) {
- brillo::Minijail* m = brillo::Minijail::GetInstance();
- minijail* jail = m->New();
-
- std::vector<char*> args;
- for (const auto& arg : argv) {
- args.push_back(const_cast<char*>(arg.c_str()));
- }
- args.push_back(nullptr);
-
- int status;
- return m->RunSyncAndDestroy(jail, args, &status) ? status : -1;
-}
-
-} // namespace permission_broker
diff --git a/permission_broker/firewall.h b/permission_broker/firewall.h
deleted file mode 100644
index c04fb35..0000000
--- a/permission_broker/firewall.h
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2017 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef PERMISSION_BROKER_FIREWALL_H_
-#define PERMISSION_BROKER_FIREWALL_H_
-
-#include <stdint.h>
-
-#include <set>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include <base/macros.h>
-#include <brillo/errors/error.h>
-#include <gtest/gtest_prod.h>
-#include <patchpanel/proto_bindings/patchpanel_service.pb.h>
-
-namespace permission_broker {
-
-using patchpanel::ModifyPortRuleRequest;
-using Operation = patchpanel::ModifyPortRuleRequest::Operation;
-using Protocol = patchpanel::ModifyPortRuleRequest::Protocol;
-using RuleType = patchpanel::ModifyPortRuleRequest::RuleType;
-
-extern const char kIpTablesPath[];
-extern const char kIp6TablesPath[];
-
-const std::string ProtocolName(Protocol proto);
-
-class Firewall {
- public:
- typedef std::pair<uint16_t, std::string> Hole;
-
- Firewall() = default;
- ~Firewall() = default;
-
- bool AddAcceptRules(Protocol protocol,
- uint16_t port,
- const std::string& interface);
- bool DeleteAcceptRules(Protocol protocol,
- uint16_t port,
- const std::string& interface);
- bool AddLoopbackLockdownRules(Protocol protocol, uint16_t port);
- bool DeleteLoopbackLockdownRules(Protocol protocol, uint16_t port);
- bool AddIpv4ForwardRule(Protocol protocol,
- const std::string& input_ip,
- uint16_t port,
- const std::string& interface,
- const std::string& dst_ip,
- uint16_t dst_port);
- bool DeleteIpv4ForwardRule(Protocol protocol,
- const std::string& input_ip,
- uint16_t port,
- const std::string& interface,
- const std::string& dst_ip,
- uint16_t dst_port);
-
- private:
- friend class FirewallTest;
- // Adds ACCEPT chain rules to the filter INPUT chain.
- virtual bool AddAcceptRule(const std::string& executable_path,
- Protocol protocol,
- uint16_t port,
- const std::string& interface);
- // Removes ACCEPT chain rules from the filter INPUT chain.
- virtual bool DeleteAcceptRule(const std::string& executable_path,
- Protocol protocol,
- uint16_t port,
- const std::string& interface);
- // Adds or removes MASQUERADE chain rules to/from the nat PREROUTING chain.
- virtual bool ModifyIpv4DNATRule(Protocol protocol,
- const std::string& input_ip,
- uint16_t port,
- const std::string& interface,
- const std::string& dst_ip,
- uint16_t dst_port,
- const std::string& operation);
- // Adds or removes ACCEPT chain rules to/from the filter FORWARD chain.
- virtual bool ModifyIpv4ForwardChain(Protocol protocol,
- const std::string& interface,
- const std::string& dst_ip,
- uint16_t dst_port,
- const std::string& operation);
- virtual bool AddLoopbackLockdownRule(const std::string& executable_path,
- Protocol protocol,
- uint16_t port);
- virtual bool DeleteLoopbackLockdownRule(const std::string& executable_path,
- Protocol protocol,
- uint16_t port);
-
- // Even though permission_broker runs as a regular user, it can still add
- // other restrictions when launching 'iptables'.
- virtual int RunInMinijail(const std::vector<std::string>& argv);
-
- DISALLOW_COPY_AND_ASSIGN(Firewall);
-};
-
-} // namespace permission_broker
-
-#endif // PERMISSION_BROKER_FIREWALL_H_
diff --git a/permission_broker/firewall_fuzzer.cc b/permission_broker/firewall_fuzzer.cc
deleted file mode 100644
index 995459c..0000000
--- a/permission_broker/firewall_fuzzer.cc
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright 2018 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <arpa/inet.h>
-#include <net/if.h>
-
-#include <fuzzer/FuzzedDataProvider.h>
-#include <set>
-
-#include "base/logging.h"
-
-#include "permission_broker/firewall.h"
-
-using patchpanel::ModifyPortRuleRequest;
-using Protocol = patchpanel::ModifyPortRuleRequest::Protocol;
-
-namespace permission_broker {
-
-class FakeFirewall : public Firewall {
- public:
- FakeFirewall() = default;
- ~FakeFirewall() = default;
-
- private:
- // The fake's implementation always succeeds.
- int RunInMinijail(const std::vector<std::string>& argv) override {
- return 0;
- }
-
- DISALLOW_COPY_AND_ASSIGN(FakeFirewall);
-};
-
-} // namespace permission_broker
-
-struct Environment {
- Environment() {
- logging::SetMinLogLevel(logging::LOG_FATAL);
- }
-};
-
-void FuzzAcceptRules(permission_broker::FakeFirewall& fake_firewall,
- const uint8_t* data,
- size_t size) {
- FuzzedDataProvider data_provider(data, size);
- while (data_provider.remaining_bytes() > 0) {
- Protocol proto = data_provider.ConsumeBool() ? ModifyPortRuleRequest::TCP
- : ModifyPortRuleRequest::UDP;
- uint16_t port = data_provider.ConsumeIntegral<uint16_t>();
- std::string iface = data_provider.ConsumeRandomLengthString(IFNAMSIZ - 1);
- if (data_provider.ConsumeBool()) {
- fake_firewall.AddAcceptRules(proto, port, iface);
- } else {
- fake_firewall.DeleteAcceptRules(proto, port, iface);
- }
- }
-}
-
-void FuzzForwardRules(permission_broker::FakeFirewall& fake_firewall,
- const uint8_t* data,
- size_t size) {
- FuzzedDataProvider data_provider(data, size);
- while (data_provider.remaining_bytes() > 0) {
- Protocol proto = data_provider.ConsumeBool() ? ModifyPortRuleRequest::TCP
- : ModifyPortRuleRequest::UDP;
- uint16_t forwarded_port = data_provider.ConsumeIntegral<uint16_t>();
- uint16_t dst_port = data_provider.ConsumeIntegral<uint16_t>();
- struct in_addr input_ip_addr = {
- .s_addr = data_provider.ConsumeIntegral<uint32_t>()};
- struct in_addr dst_ip_addr = {
- .s_addr = data_provider.ConsumeIntegral<uint32_t>()};
- char input_buffer[INET_ADDRSTRLEN];
- char dst_buffer[INET_ADDRSTRLEN];
- memset(input_buffer, 0, INET_ADDRSTRLEN);
- memset(dst_buffer, 0, INET_ADDRSTRLEN);
- inet_ntop(AF_INET, &input_ip_addr, input_buffer, INET_ADDRSTRLEN);
- inet_ntop(AF_INET, &dst_ip_addr, dst_buffer, INET_ADDRSTRLEN);
- std::string input_ip = input_buffer;
- std::string dst_ip = dst_buffer;
- std::string iface = data_provider.ConsumeRandomLengthString(IFNAMSIZ - 1);
- if (data_provider.ConsumeBool()) {
- fake_firewall.AddIpv4ForwardRule(proto, input_ip, forwarded_port, iface,
- dst_ip, dst_port);
- } else {
- fake_firewall.DeleteIpv4ForwardRule(proto, input_ip, forwarded_port,
- iface, dst_ip, dst_port);
- }
- }
-}
-
-void FuzzLoopbackLockdownRules(permission_broker::FakeFirewall& fake_firewall,
- const uint8_t* data,
- size_t size) {
- FuzzedDataProvider data_provider(data, size);
- while (data_provider.remaining_bytes() > 0) {
- Protocol proto = data_provider.ConsumeBool() ? ModifyPortRuleRequest::TCP
- : ModifyPortRuleRequest::UDP;
- uint16_t port = data_provider.ConsumeIntegral<uint16_t>();
- if (data_provider.ConsumeBool()) {
- fake_firewall.AddLoopbackLockdownRules(proto, port);
- } else {
- fake_firewall.DeleteLoopbackLockdownRules(proto, port);
- }
- }
-}
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- static Environment env;
-
- permission_broker::FakeFirewall fake_firewall;
-
- FuzzAcceptRules(fake_firewall, data, size);
- FuzzForwardRules(fake_firewall, data, size);
- FuzzLoopbackLockdownRules(fake_firewall, data, size);
-
- return 0;
-}
diff --git a/permission_broker/firewall_test.cc b/permission_broker/firewall_test.cc
deleted file mode 100644
index 8c0829d..0000000
--- a/permission_broker/firewall_test.cc
+++ /dev/null
@@ -1,496 +0,0 @@
-// Copyright 2017 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "permission_broker/firewall.h"
-
-#include <string>
-#include <vector>
-
-#include <gtest/gtest.h>
-
-#include "permission_broker/mock_firewall.h"
-
-namespace permission_broker {
-
-using testing::_;
-using testing::Return;
-
-class FirewallTest : public testing::Test {
- public:
- FirewallTest() = default;
- ~FirewallTest() override = default;
-
- protected:
- void SetMockExpectations(MockFirewall* firewall, bool success) {
- // Empty criterion matches all commands.
- firewall->SetRunInMinijailFailCriterion(std::vector<std::string>(), true,
- success);
- }
-
- void SetMockExpectationsPerExecutable(MockFirewall* firewall,
- bool ip4_success,
- bool ip6_success) {
- if (!ip4_success)
- firewall->SetRunInMinijailFailCriterion(
- std::vector<std::string>({kIpTablesPath}), true /* repeat */,
- false /* omit_failure */);
- if (!ip6_success)
- firewall->SetRunInMinijailFailCriterion(
- std::vector<std::string>({kIp6TablesPath}), true, false);
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(FirewallTest);
-};
-
-TEST_F(FirewallTest, Port0Fails) {
- MockFirewall mock_firewall;
- // Don't fail on anything.
- int id = mock_firewall.SetRunInMinijailFailCriterion(
- std::vector<std::string>(), true, true);
-
- // Try to punch hole for TCP port 0, port 0 is not a valid port.
- EXPECT_FALSE(
- mock_firewall.AddAcceptRules(ModifyPortRuleRequest::TCP, 0, "iface"));
- // Try to punch hole for UDP port 0, port 0 is not a valid port.
- EXPECT_FALSE(
- mock_firewall.AddAcceptRules(ModifyPortRuleRequest::UDP, 0, "iface"));
-
- // Try to plug hole for TCP port 0, port 0 is not a valid port.
- EXPECT_FALSE(
- mock_firewall.DeleteAcceptRules(ModifyPortRuleRequest::TCP, 0, "iface"));
- // Try to plug hole for UDP port 0, port 0 is not a valid port.
- EXPECT_FALSE(
- mock_firewall.DeleteAcceptRules(ModifyPortRuleRequest::UDP, 0, "iface"));
-
- // We should not be adding/removing any rules for port 0.
- EXPECT_EQ(mock_firewall.GetRunInMinijailCriterionMatchCount(id), 0);
-}
-
-TEST_F(FirewallTest, ValidInterfaceName) {
- MockFirewall mock_firewall;
- SetMockExpectations(&mock_firewall, true /* success */);
-
- EXPECT_TRUE(mock_firewall.AddAcceptRules(ModifyPortRuleRequest::TCP, 80,
- "shortname"));
- EXPECT_TRUE(mock_firewall.AddAcceptRules(ModifyPortRuleRequest::UDP, 53,
- "shortname"));
- EXPECT_TRUE(mock_firewall.AddAcceptRules(ModifyPortRuleRequest::TCP, 80,
- "middle-dash"));
- EXPECT_TRUE(mock_firewall.AddAcceptRules(ModifyPortRuleRequest::UDP, 53,
- "middle-dash"));
- EXPECT_TRUE(mock_firewall.AddAcceptRules(ModifyPortRuleRequest::TCP, 80,
- "middle.dot"));
- EXPECT_TRUE(mock_firewall.AddAcceptRules(ModifyPortRuleRequest::UDP, 53,
- "middle.dot"));
-}
-
-TEST_F(FirewallTest, InvalidInterfaceName) {
- MockFirewall mock_firewall;
- int id = mock_firewall.SetRunInMinijailFailCriterion(
- std::vector<std::string>(), true, true);
-
- EXPECT_FALSE(mock_firewall.AddAcceptRules(ModifyPortRuleRequest::TCP, 80,
- "reallylonginterfacename"));
- EXPECT_FALSE(mock_firewall.AddAcceptRules(ModifyPortRuleRequest::TCP, 80,
- "with spaces"));
- EXPECT_FALSE(mock_firewall.AddAcceptRules(ModifyPortRuleRequest::TCP, 80,
- "with$ymbols"));
- EXPECT_FALSE(mock_firewall.AddAcceptRules(ModifyPortRuleRequest::TCP, 80,
- "-startdash"));
- EXPECT_FALSE(
- mock_firewall.AddAcceptRules(ModifyPortRuleRequest::TCP, 80, "enddash-"));
- EXPECT_FALSE(mock_firewall.AddAcceptRules(ModifyPortRuleRequest::TCP, 80,
- ".startdot"));
- EXPECT_FALSE(
- mock_firewall.AddAcceptRules(ModifyPortRuleRequest::TCP, 80, "enddot."));
-
- EXPECT_FALSE(mock_firewall.AddAcceptRules(ModifyPortRuleRequest::UDP, 53,
- "reallylonginterfacename"));
- EXPECT_FALSE(mock_firewall.AddAcceptRules(ModifyPortRuleRequest::UDP, 53,
- "with spaces"));
- EXPECT_FALSE(mock_firewall.AddAcceptRules(ModifyPortRuleRequest::UDP, 53,
- "with$ymbols"));
- EXPECT_FALSE(mock_firewall.AddAcceptRules(ModifyPortRuleRequest::UDP, 53,
- "-startdash"));
- EXPECT_FALSE(
- mock_firewall.AddAcceptRules(ModifyPortRuleRequest::UDP, 53, "enddash-"));
- EXPECT_FALSE(mock_firewall.AddAcceptRules(ModifyPortRuleRequest::UDP, 53,
- ".startdot"));
- EXPECT_FALSE(
- mock_firewall.AddAcceptRules(ModifyPortRuleRequest::UDP, 53, "enddot."));
-
- EXPECT_FALSE(mock_firewall.DeleteAcceptRules(ModifyPortRuleRequest::TCP, 80,
- "reallylonginterfacename"));
- EXPECT_FALSE(mock_firewall.DeleteAcceptRules(ModifyPortRuleRequest::TCP, 80,
- "with spaces"));
- EXPECT_FALSE(mock_firewall.DeleteAcceptRules(ModifyPortRuleRequest::TCP, 80,
- "with$ymbols"));
- EXPECT_FALSE(mock_firewall.DeleteAcceptRules(ModifyPortRuleRequest::TCP, 80,
- "-startdash"));
- EXPECT_FALSE(mock_firewall.DeleteAcceptRules(ModifyPortRuleRequest::TCP, 80,
- "enddash-"));
- EXPECT_FALSE(mock_firewall.DeleteAcceptRules(ModifyPortRuleRequest::TCP, 80,
- ".startdot"));
- EXPECT_FALSE(mock_firewall.DeleteAcceptRules(ModifyPortRuleRequest::TCP, 80,
- "enddot."));
-
- EXPECT_FALSE(mock_firewall.DeleteAcceptRules(ModifyPortRuleRequest::UDP, 53,
- "reallylonginterfacename"));
- EXPECT_FALSE(mock_firewall.DeleteAcceptRules(ModifyPortRuleRequest::UDP, 53,
- "with spaces"));
- EXPECT_FALSE(mock_firewall.DeleteAcceptRules(ModifyPortRuleRequest::UDP, 53,
- "with$ymbols"));
- EXPECT_FALSE(mock_firewall.DeleteAcceptRules(ModifyPortRuleRequest::UDP, 53,
- "-startdash"));
- EXPECT_FALSE(mock_firewall.DeleteAcceptRules(ModifyPortRuleRequest::UDP, 53,
- "enddash-"));
- EXPECT_FALSE(mock_firewall.DeleteAcceptRules(ModifyPortRuleRequest::UDP, 53,
- ".startdot"));
- EXPECT_FALSE(mock_firewall.DeleteAcceptRules(ModifyPortRuleRequest::UDP, 53,
- "enddot."));
-
- // We should not be adding/removing any rules for invalid interface names.
- EXPECT_EQ(mock_firewall.GetRunInMinijailCriterionMatchCount(id), 0);
-}
-
-TEST_F(FirewallTest, AddAcceptRules_Fails) {
- MockFirewall mock_firewall;
- SetMockExpectations(&mock_firewall, false /* success */);
-
- // Punch hole for TCP port 80, should fail.
- ASSERT_FALSE(
- mock_firewall.AddAcceptRules(ModifyPortRuleRequest::TCP, 80, "iface"));
- // Punch hole for UDP port 53, should fail.
- ASSERT_FALSE(
- mock_firewall.AddAcceptRules(ModifyPortRuleRequest::UDP, 53, "iface"));
-}
-
-TEST_F(FirewallTest, AddAcceptRules_Ipv6Fails) {
- MockFirewall mock_firewall;
- SetMockExpectationsPerExecutable(&mock_firewall, true /* ip4_success */,
- false /* ip6_success */);
-
- // Punch hole for TCP port 80, should fail because 'ip6tables' fails.
- ASSERT_FALSE(
- mock_firewall.AddAcceptRules(ModifyPortRuleRequest::TCP, 80, "iface"));
- // Punch hole for UDP port 53, should fail because 'ip6tables' fails.
- ASSERT_FALSE(
- mock_firewall.AddAcceptRules(ModifyPortRuleRequest::UDP, 53, "iface"));
-}
-
-TEST_F(FirewallTest, Port0LockdownFails) {
- MockFirewall mock_firewall;
- // Don't fail on anything.
- int id = mock_firewall.SetRunInMinijailFailCriterion(
- std::vector<std::string>(), true, true);
-
- // Try to lock down TCP port 0, port 0 is not a valid port.
- EXPECT_FALSE(
- mock_firewall.AddLoopbackLockdownRules(ModifyPortRuleRequest::TCP, 0));
- // Try to lock down UDP port 0, port 0 is not a valid port.
- EXPECT_FALSE(
- mock_firewall.AddLoopbackLockdownRules(ModifyPortRuleRequest::UDP, 0));
-
- // We should not be adding/removing any rules for port 0.
- EXPECT_EQ(mock_firewall.GetRunInMinijailCriterionMatchCount(id), 0);
-}
-
-TEST_F(FirewallTest, AddLoopbackLockdownRules_Success) {
- MockFirewall mock_firewall;
- SetMockExpectations(&mock_firewall, true /* success */);
- ASSERT_TRUE(
- mock_firewall.AddLoopbackLockdownRules(ModifyPortRuleRequest::TCP, 80));
- ASSERT_TRUE(
- mock_firewall.AddLoopbackLockdownRules(ModifyPortRuleRequest::UDP, 53));
- ASSERT_TRUE(
- mock_firewall.AddLoopbackLockdownRules(ModifyPortRuleRequest::TCP, 1234));
- ASSERT_TRUE(
- mock_firewall.AddLoopbackLockdownRules(ModifyPortRuleRequest::TCP, 8080));
-}
-
-TEST_F(FirewallTest, AddLoopbackLockdownRules_Fails) {
- MockFirewall mock_firewall;
- SetMockExpectations(&mock_firewall, false /* success */);
-
- // Lock down TCP port 80, should fail.
- ASSERT_FALSE(
- mock_firewall.AddLoopbackLockdownRules(ModifyPortRuleRequest::TCP, 80));
- // Lock down UDP port 53, should fail.
- ASSERT_FALSE(
- mock_firewall.AddLoopbackLockdownRules(ModifyPortRuleRequest::UDP, 53));
-}
-
-TEST_F(FirewallTest, AddLoopbackLockdownRules_Ipv6Fails) {
- MockFirewall mock_firewall;
- SetMockExpectationsPerExecutable(&mock_firewall, true /* ip4_success */,
- false /* ip6_success */);
-
- // Lock down TCP port 80, should fail because 'ip6tables' fails.
- ASSERT_FALSE(
- mock_firewall.AddLoopbackLockdownRules(ModifyPortRuleRequest::TCP, 80));
- // Lock down UDP port 53, should fail because 'ip6tables' fails.
- ASSERT_FALSE(
- mock_firewall.AddLoopbackLockdownRules(ModifyPortRuleRequest::UDP, 53));
-}
-
-TEST_F(FirewallTest, AddIpv4ForwardRules_InvalidArguments) {
- MockFirewall mock_firewall;
- // Don't fail on anything.
- mock_firewall.SetRunInMinijailFailCriterion({}, true, true);
-
- // Invalid input interface. No iptables commands are issued.
- ASSERT_FALSE(mock_firewall.AddIpv4ForwardRule(
- ModifyPortRuleRequest::TCP, "", 80, "-startdash", "100.115.92.5", 8080));
- ASSERT_FALSE(mock_firewall.AddIpv4ForwardRule(
- ModifyPortRuleRequest::UDP, "", 80, "enddash-", "100.115.92.5", 8080));
- ASSERT_FALSE(mock_firewall.DeleteIpv4ForwardRule(
- ModifyPortRuleRequest::TCP, "", 80, ".startdot", "100.115.92.5", 8080));
- ASSERT_FALSE(mock_firewall.DeleteIpv4ForwardRule(
- ModifyPortRuleRequest::UDP, "", 80, "enddot.", "100.115.92.5", 8080));
- ASSERT_TRUE(mock_firewall.GetAllCommands().empty());
- mock_firewall.ResetStoredCommands();
-
- // Empty interface. No iptables commands are issused.
- ASSERT_FALSE(mock_firewall.AddIpv4ForwardRule(ModifyPortRuleRequest::TCP, "",
- 80, "", "100.115.92.5", 8080));
- ASSERT_FALSE(mock_firewall.AddIpv4ForwardRule(ModifyPortRuleRequest::UDP, "",
- 80, "", "100.115.92.5", 8080));
- ASSERT_FALSE(mock_firewall.DeleteIpv4ForwardRule(
- ModifyPortRuleRequest::TCP, "", 80, "", "100.115.92.5", 8080));
- ASSERT_FALSE(mock_firewall.DeleteIpv4ForwardRule(
- ModifyPortRuleRequest::UDP, "", 80, "", "100.115.92.5", 8080));
- ASSERT_TRUE(mock_firewall.GetAllCommands().empty());
- mock_firewall.ResetStoredCommands();
-
- // Invalid input dst address. No iptables commands are issused.
- ASSERT_FALSE(mock_firewall.AddIpv4ForwardRule(ModifyPortRuleRequest::TCP,
- "256.256.256.256", 80, "iface",
- "100.115.92.5", 8080));
- ASSERT_FALSE(mock_firewall.AddIpv4ForwardRule(ModifyPortRuleRequest::UDP,
- "qodpjqwpod", 80, "iface",
- "100.115.92.5", 8080));
- // Trying to delete an IPv4 forward rule with an invalid input address will
- // still trigger an explicit iptables -D command for the associated FORWARD
- // ACCEPT rule. Two such commands are expected.
- ASSERT_FALSE(mock_firewall.DeleteIpv4ForwardRule(
- ModifyPortRuleRequest::TCP, "1.1", 80, "iface", "100.115.92.5", 8080));
- ASSERT_FALSE(mock_firewall.DeleteIpv4ForwardRule(ModifyPortRuleRequest::UDP,
- "2001:db8::1", 80, "iface",
- "100.115.92.5", 8080));
- {
- std::vector<std::string> expected_commands = {
- "/sbin/iptables -t filter -D FORWARD -i iface -p tcp -d 100.115.92.5 "
- "--dport 8080 -j ACCEPT -w",
- "/sbin/iptables -t filter -D FORWARD -i iface -p udp -d 100.115.92.5 "
- "--dport 8080 -j ACCEPT -w",
- };
- std::vector<std::string> issued_commands = mock_firewall.GetAllCommands();
- EXPECT_EQ(expected_commands.size(), issued_commands.size());
- for (int i = 0; i < expected_commands.size(); i++) {
- ASSERT_EQ(expected_commands[i], issued_commands[i]);
- }
- }
- mock_firewall.ResetStoredCommands();
-
- // Invalid input dst port.
- ASSERT_FALSE(mock_firewall.AddIpv4ForwardRule(
- ModifyPortRuleRequest::TCP, "", 0, "iface", "100.115.92.5", 8080));
- ASSERT_FALSE(mock_firewall.AddIpv4ForwardRule(
- ModifyPortRuleRequest::TCP, "", 0, "iface", "100.115.92.5", 8080));
- // Trying to delete an IPv4 forward rule with an invalid input port will
- // still trigger an explicit iptables -D command for the associated FORWARD
- // ACCEPT rule. Two such commands are expected.
- ASSERT_FALSE(mock_firewall.DeleteIpv4ForwardRule(
- ModifyPortRuleRequest::TCP, "", 0, "iface", "100.115.92.5", 8080));
- ASSERT_FALSE(mock_firewall.DeleteIpv4ForwardRule(
- ModifyPortRuleRequest::UDP, "", 0, "iface", "100.115.92.5", 8080));
- {
- std::vector<std::string> expected_commands = {
- "/sbin/iptables -t filter -D FORWARD -i iface -p tcp -d 100.115.92.5 "
- "--dport 8080 -j ACCEPT -w",
- "/sbin/iptables -t filter -D FORWARD -i iface -p udp -d 100.115.92.5 "
- "--dport 8080 -j ACCEPT -w",
- };
- std::vector<std::string> issued_commands = mock_firewall.GetAllCommands();
- EXPECT_EQ(expected_commands.size(), issued_commands.size());
- for (int i = 0; i < expected_commands.size(); i++) {
- ASSERT_EQ(expected_commands[i], issued_commands[i]);
- }
- }
- mock_firewall.ResetStoredCommands();
-
- // Invalid output dst address. No iptables commands are issused.
- ASSERT_FALSE(mock_firewall.AddIpv4ForwardRule(ModifyPortRuleRequest::TCP, "",
- 80, "iface", "", 8080));
- ASSERT_FALSE(mock_firewall.AddIpv4ForwardRule(
- ModifyPortRuleRequest::UDP, "", 80, "iface", "qodpjqwpod", 8080));
- ASSERT_FALSE(mock_firewall.DeleteIpv4ForwardRule(
- ModifyPortRuleRequest::TCP, "", 80, "iface", "1.1", 8080));
- ASSERT_FALSE(mock_firewall.DeleteIpv4ForwardRule(
- ModifyPortRuleRequest::UDP, "", 80, "iface", "2001:db8::1", 8080));
- ASSERT_TRUE(mock_firewall.GetAllCommands().empty());
- mock_firewall.ResetStoredCommands();
-
- // Invalid output dst port. No iptables commands are issused.
- ASSERT_FALSE(mock_firewall.AddIpv4ForwardRule(
- ModifyPortRuleRequest::TCP, "", 80, "iface", "100.115.92.5", 0));
- ASSERT_FALSE(mock_firewall.AddIpv4ForwardRule(
- ModifyPortRuleRequest::UDP, "", 80, "iface", "100.115.92.5", 0));
- ASSERT_FALSE(mock_firewall.DeleteIpv4ForwardRule(
- ModifyPortRuleRequest::TCP, "", 80, "iface", "100.115.92.5", 0));
- ASSERT_FALSE(mock_firewall.DeleteIpv4ForwardRule(
- ModifyPortRuleRequest::UDP, "", 80, "iface", "100.115.92.5", 0));
- ASSERT_TRUE(mock_firewall.GetAllCommands().empty());
- mock_firewall.ResetStoredCommands();
-}
-
-TEST_F(FirewallTest, AddIpv4ForwardRules_IptablesFails) {
- MockFirewall mock_firewall;
- mock_firewall.SetRunInMinijailFailCriterion({}, true, false);
-
- ASSERT_FALSE(mock_firewall.AddIpv4ForwardRule(
- ModifyPortRuleRequest::TCP, "", 80, "iface", "100.115.92.6", 8080));
- ASSERT_FALSE(mock_firewall.AddIpv4ForwardRule(
- ModifyPortRuleRequest::UDP, "", 80, "iface", "100.115.92.6", 8080));
- ASSERT_FALSE(mock_firewall.DeleteIpv4ForwardRule(
- ModifyPortRuleRequest::TCP, "", 80, "iface", "100.115.92.6", 8080));
- ASSERT_FALSE(mock_firewall.DeleteIpv4ForwardRule(
- ModifyPortRuleRequest::UDP, "", 80, "iface", "100.115.92.6", 8080));
-
- // AddIpv4ForwardRule: Firewall should return at the first failure and issue
- // only a single command.
- // DeleteIpv4ForwardRule: Firewall should try to delete both the DNAT rule
- // and the FORWARD rule regardless of iptables failures.
- std::vector<std::string> expected_commands = {
- // Failed first AddIpv4ForwardRule call
- "/sbin/iptables -t nat -I PREROUTING -i iface -p tcp --dport 80 -j DNAT "
- "--to-destination 100.115.92.6:8080 -w",
- // Failed second AddIpv4ForwardRule call
- "/sbin/iptables -t nat -I PREROUTING -i iface -p udp --dport 80 -j DNAT "
- "--to-destination 100.115.92.6:8080 -w",
- // Failed first DeleteIpv4ForwardRule call
- "/sbin/iptables -t nat -D PREROUTING -i iface -p tcp --dport 80 -j DNAT "
- "--to-destination 100.115.92.6:8080 -w",
- "/sbin/iptables -t filter -D FORWARD -i iface -p tcp -d 100.115.92.6 "
- "--dport 8080 -j ACCEPT -w",
- // Failed second DeleteIpv4ForwardRule call
- "/sbin/iptables -t nat -D PREROUTING -i iface -p udp --dport 80 -j DNAT "
- "--to-destination 100.115.92.6:8080 -w",
- "/sbin/iptables -t filter -D FORWARD -i iface -p udp -d 100.115.92.6 "
- "--dport 8080 -j ACCEPT -w",
- };
- std::vector<std::string> issued_commands = mock_firewall.GetAllCommands();
- EXPECT_EQ(expected_commands.size(), issued_commands.size());
- for (int i = 0; i < expected_commands.size(); i++) {
- ASSERT_EQ(expected_commands[i], issued_commands[i]);
- }
-}
-
-TEST_F(FirewallTest, AddIpv4ForwardRules_ValidRules) {
- MockFirewall mock_firewall;
- mock_firewall.SetRunInMinijailFailCriterion({}, true, true);
-
- ASSERT_TRUE(mock_firewall.AddIpv4ForwardRule(
- ModifyPortRuleRequest::TCP, "", 80, "wlan0", "100.115.92.2", 8080));
- ASSERT_TRUE(mock_firewall.AddIpv4ForwardRule(ModifyPortRuleRequest::TCP,
- "100.115.92.2", 5555, "vmtap0",
- "127.0.0.1", 5550));
- ASSERT_TRUE(mock_firewall.AddIpv4ForwardRule(
- ModifyPortRuleRequest::UDP, "", 5353, "eth0", "192.168.1.1", 5353));
- ASSERT_TRUE(mock_firewall.DeleteIpv4ForwardRule(
- ModifyPortRuleRequest::TCP, "", 5000, "mlan0", "10.0.0.24", 5001));
- ASSERT_TRUE(mock_firewall.DeleteIpv4ForwardRule(ModifyPortRuleRequest::TCP,
- "100.115.92.2", 5555,
- "vmtap0", "127.0.0.1", 5550));
- ASSERT_TRUE(mock_firewall.DeleteIpv4ForwardRule(
- ModifyPortRuleRequest::UDP, "", 443, "eth1", "1.2.3.4", 443));
-
- std::vector<std::string> expected_commands = {
- "/sbin/iptables -t nat -I PREROUTING -i wlan0 -p tcp --dport 80 -j DNAT "
- "--to-destination 100.115.92.2:8080 -w",
- "/sbin/iptables -t filter -A FORWARD -i wlan0 -p tcp -d 100.115.92.2 "
- "--dport 8080 -j ACCEPT -w",
- "/sbin/iptables -t nat -I PREROUTING -i vmtap0 -p tcp -d 100.115.92.2 "
- "--dport 5555 -j DNAT --to-destination 127.0.0.1:5550 -w",
- "/sbin/iptables -t filter -A FORWARD -i vmtap0 -p tcp -d 127.0.0.1 "
- "--dport 5550 -j ACCEPT -w",
- "/sbin/iptables -t nat -I PREROUTING -i eth0 -p udp --dport 5353 -j DNAT "
- "--to-destination 192.168.1.1:5353 -w",
- "/sbin/iptables -t filter -A FORWARD -i eth0 -p udp -d 192.168.1.1 "
- "--dport 5353 -j ACCEPT -w",
- "/sbin/iptables -t nat -D PREROUTING -i mlan0 -p tcp --dport 5000 -j "
- "DNAT --to-destination 10.0.0.24:5001 -w",
- "/sbin/iptables -t filter -D FORWARD -i mlan0 -p tcp -d 10.0.0.24 "
- "--dport 5001 -j ACCEPT -w",
- "/sbin/iptables -t nat -D PREROUTING -i vmtap0 -p tcp -d 100.115.92.2 "
- "--dport 5555 -j DNAT --to-destination 127.0.0.1:5550 -w",
- "/sbin/iptables -t filter -D FORWARD -i vmtap0 -p tcp -d 127.0.0.1 "
- "--dport 5550 -j ACCEPT -w",
- "/sbin/iptables -t nat -D PREROUTING -i eth1 -p udp --dport 443 -j DNAT "
- "--to-destination 1.2.3.4:443 -w",
- "/sbin/iptables -t filter -D FORWARD -i eth1 -p udp -d 1.2.3.4 "
- "--dport 443 -j ACCEPT -w",
- };
- std::vector<std::string> issued_commands = mock_firewall.GetAllCommands();
- EXPECT_EQ(expected_commands.size(), issued_commands.size());
- for (int i = 0; i < expected_commands.size(); i++) {
- ASSERT_EQ(expected_commands[i], issued_commands[i]);
- }
-}
-
-TEST_F(FirewallTest, AddIpv4ForwardRules_PartialFailure) {
- MockFirewall mock_firewall;
- mock_firewall.SetRunInMinijailFailCriterion({"FORWARD"}, true, false);
-
- ASSERT_FALSE(mock_firewall.AddIpv4ForwardRule(
- ModifyPortRuleRequest::TCP, "", 80, "wlan0", "100.115.92.2", 8080));
-
- // When the second issued FORWARD command fails, expect a delete command to
- // cleanup the PREROUTING command that succeeded.
- std::vector<std::string> expected_commands = {
- "/sbin/iptables -t nat -I PREROUTING -i wlan0 -p tcp --dport 80 -j DNAT "
- "--to-destination 100.115.92.2:8080 -w",
- "/sbin/iptables -t filter -A FORWARD -i wlan0 -p tcp -d 100.115.92.2 "
- "--dport 8080 -j ACCEPT -w",
- "/sbin/iptables -t nat -D PREROUTING -i wlan0 -p tcp --dport 80 -j DNAT "
- "--to-destination 100.115.92.2:8080 -w",
- };
- std::vector<std::string> issued_commands = mock_firewall.GetAllCommands();
- ASSERT_EQ(expected_commands.size(), issued_commands.size());
- for (int i = 0; i < expected_commands.size(); i++) {
- ASSERT_EQ(expected_commands[i], issued_commands[i]);
- }
-}
-
-TEST_F(FirewallTest, DeleteIpv4ForwardRules_PartialFailure) {
- MockFirewall mock_firewall1;
- MockFirewall mock_firewall2;
-
- mock_firewall1.SetRunInMinijailFailCriterion({"FORWARD"}, false, false);
- mock_firewall2.SetRunInMinijailFailCriterion({"PREROUTING"}, false, false);
-
- ASSERT_FALSE(mock_firewall1.DeleteIpv4ForwardRule(
- ModifyPortRuleRequest::TCP, "", 80, "wlan0", "100.115.92.2", 8080));
- ASSERT_FALSE(mock_firewall2.DeleteIpv4ForwardRule(
- ModifyPortRuleRequest::TCP, "", 80, "wlan0", "100.115.92.2", 8080));
-
- // Cleanup commands for both FORWARD and PREROUTING rules are both issued
- // regardless of any iptables failures.
- std::vector<std::string> expected_commands = {
- "/sbin/iptables -t nat -D PREROUTING -i wlan0 -p tcp --dport 80 -j DNAT "
- "--to-destination 100.115.92.2:8080 -w",
- "/sbin/iptables -t filter -D FORWARD -i wlan0 -p tcp -d 100.115.92.2 "
- "--dport 8080 -j ACCEPT -w",
- };
- std::vector<std::string> issued_commands1 = mock_firewall1.GetAllCommands();
- std::vector<std::string> issued_commands2 = mock_firewall2.GetAllCommands();
- ASSERT_EQ(expected_commands.size(), issued_commands1.size());
- ASSERT_EQ(expected_commands.size(), issued_commands2.size());
- for (int i = 0; i < expected_commands.size(); i++) {
- ASSERT_EQ(expected_commands[i], issued_commands1[i]);
- ASSERT_EQ(expected_commands[i], issued_commands2[i]);
- }
-}
-} // namespace permission_broker
diff --git a/permission_broker/mock_firewall.cc b/permission_broker/mock_firewall.cc
deleted file mode 100644
index f7dd6d9..0000000
--- a/permission_broker/mock_firewall.cc
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright 2017 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "permission_broker/mock_firewall.h"
-
-#include <algorithm>
-
-namespace permission_broker {
-
-int MockFirewall::SetRunInMinijailFailCriterion(
- const std::vector<std::string>& keywords, bool repeat, bool omit_failure) {
- match_criteria_.push_back(Criterion{keywords, repeat, omit_failure, 0});
- return match_criteria_.size() - 1;
-}
-
-int MockFirewall::GetRunInMinijailCriterionMatchCount(int id) {
- if (id < 0 || id >= static_cast<int>(match_criteria_.size()))
- return -1;
- return match_criteria_[id].match_count;
-}
-
-bool MockFirewall::MatchAndUpdate(const std::vector<std::string>& argv) {
- // Make a copy of the container so that we can delete elements while
- // iterating.
- auto criteria = match_criteria_;
- for (auto& criterion : criteria) {
- bool match = true;
- // Empty criterion is a catch all -- fail on any RunInMinijail.
- for (const std::string& keyword : criterion.keywords) {
- match =
- match && (std::find(argv.begin(), argv.end(), keyword) != argv.end());
- }
- if (match) {
- criterion.match_count++;
- if (!criterion.repeat) {
- match_criteria_.erase(std::remove(match_criteria_.begin(),
- match_criteria_.end(), criterion),
- match_criteria_.end());
- }
- // If not negating, treat as fail criterion,
- // otherwise ignore (return false).
- return !criterion.omit_failure;
- }
- }
- return false;
-}
-
-std::vector<std::string> MockFirewall::GetAllCommands() {
- std::vector<std::string> commands;
- commands.reserve(commands_.size());
- for (const auto& argv : commands_) {
- std::string joined_argv = "";
- std::string separator = "";
- for (const auto& arg : argv) {
- joined_argv += separator + arg;
- separator = " ";
- }
- commands.push_back(joined_argv);
- }
- return commands;
-}
-
-int MockFirewall::RunInMinijail(const std::vector<std::string>& argv) {
- commands_.push_back(argv);
- return MatchAndUpdate(argv) ? 1 : 0;
-}
-
-// Returns the inverse of a given command. For an insert or append returns a
-// command to delete that rule, for a deletion returns a command to insert it at
-// the start. Assumes that the inverse of -D is always -I and that -I|--insert
-// is used without index arguments. This holds as of 2019-11-20 but if you start
-// using them you'll need to update this method.
-std::vector<std::string> MockFirewall::GetInverseCommand(
- const std::vector<std::string>& argv) {
- std::vector<std::string> inverse;
- if (argv.size() == 0) {
- return inverse;
- }
-
- bool isIpTablesCommand = argv[0] == kIpTablesPath;
- for (const auto& arg : argv) {
- if (isIpTablesCommand && (arg == "-I" || arg == "-A" || arg == "--insert" ||
- arg == "--append")) {
- inverse.push_back("-D");
- } else if (isIpTablesCommand && arg == "-D") {
- inverse.push_back("-I");
- } else {
- inverse.push_back(arg);
- }
- }
- return inverse;
-}
-
-// This check does not enforce ordering. It only checks
-// that for each command that adds a rule/mark with
-// ip/iptables, there is a later match command that
-// deletes that same rule/mark.
-bool MockFirewall::CheckCommandsUndone() {
- return CountActiveCommands() == 0;
-}
-
-// For each command, if it's an insert or an append it checks if there's a
-// corresponding delete later on, then it returns a count of all rules without
-// deletes. Will skip any rule that's not an append or insert e.g. delete
-// without an insert first will return 0 not -1.
-int MockFirewall::CountActiveCommands() {
- int count = 0;
- for (std::vector<std::vector<std::string>>::iterator it = commands_.begin();
- it != commands_.end(); it++) {
- // For each command that adds a rule, check that its inverse
- // exists later in the log of commands.
- if ((std::find(it->begin(), it->end(), "-A") != it->end()) ||
- (std::find(it->begin(), it->end(), "--append") != it->end()) ||
- (std::find(it->begin(), it->end(), "-I") != it->end()) ||
- (std::find(it->begin(), it->end(), "--insert") != it->end())) {
- bool found = false;
- std::vector<std::string> inverse = GetInverseCommand(*it);
- // If GetInverseCommand returns the same command, then it was
- // not an ip/iptables command that added/removed a rule/mark.
- if (std::equal(it->begin(), it->end(), inverse.begin()))
- continue;
- for (auto it_next = it + 1; it_next != commands_.end(); it_next++) {
- if (*it_next == inverse) {
- found = true;
- break;
- }
- }
- if (!found)
- count++;
- }
- }
- return count;
-}
-
-void MockFirewall::ResetStoredCommands() {
- commands_.clear();
-}
-
-} // namespace permission_broker
diff --git a/permission_broker/mock_firewall.h b/permission_broker/mock_firewall.h
deleted file mode 100644
index 97e6f76..0000000
--- a/permission_broker/mock_firewall.h
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2017 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef PERMISSION_BROKER_MOCK_FIREWALL_H_
-#define PERMISSION_BROKER_MOCK_FIREWALL_H_
-
-#include <string>
-#include <vector>
-
-#include <base/macros.h>
-#include <gmock/gmock.h>
-
-#include "permission_broker/firewall.h"
-
-namespace permission_broker {
-
-class MockFirewall : public Firewall {
- public:
- MockFirewall() = default;
- ~MockFirewall() = default;
-
- int SetRunInMinijailFailCriterion(
- const std::vector<std::string>& keywords, bool repeat, bool omit_failure);
- int GetRunInMinijailCriterionMatchCount(int id);
- bool CheckCommandsUndone();
- int CountActiveCommands();
- void ResetStoredCommands();
-
- // Check if the current command matches a failure rule,
- // if the failure rule is not a repeat rule, remove it
- // from the match criteria.
- bool MatchAndUpdate(const std::vector<std::string>& argv);
-
- // Returns all commands issued with RunInMinijail during the test.
- std::vector<std::string> GetAllCommands();
-
- private:
- struct Criterion {
- std::vector<std::string> keywords;
- // If false, remove the criterion after it's matched.
- bool repeat;
- // If false, treat matching commands as failures, otherwise,
- // omit failing.
- bool omit_failure;
- // Count the number of times the criterion is matched.
- int match_count;
-
- // Don't take into account match_count.
- bool operator==(const Criterion& c) const {
- return (std::equal(keywords.begin(), keywords.end(),
- c.keywords.begin()) &&
- (repeat == c.repeat) &&
- (c.omit_failure == omit_failure));
- }
- };
-
- // A list of collections of keywords that a command
- // must have in order for it to fail.
- std::vector<Criterion> match_criteria_;
-
- // A log of commands issued with RunInMinijail during the test.
- std::vector<std::vector<std::string>> commands_;
-
- // The mock's implementation simply logs the command issued if
- // successful.
- int RunInMinijail(const std::vector<std::string>& argv) override;
-
- // Given an ip/iptables command, return the command that undoes its effect.
- std::vector<std::string> GetInverseCommand(
- const std::vector<std::string>& command);
-
- DISALLOW_COPY_AND_ASSIGN(MockFirewall);
-};
-
-} // namespace permission_broker
-
-#endif // PERMISSION_BROKER_MOCK_FIREWALL_H_
diff --git a/permission_broker/permission_broker.cc b/permission_broker/permission_broker.cc
index 0c95417..19d0f74 100644
--- a/permission_broker/permission_broker.cc
+++ b/permission_broker/permission_broker.cc
@@ -72,7 +72,7 @@
rule_engine_(udev_run_path, poll_interval),
dbus_object_(
nullptr, bus, dbus::ObjectPath(kPermissionBrokerServicePath)),
- port_tracker_(&firewall_),
+ port_tracker_(),
usb_control_(std::make_unique<UsbDeviceManager>()),
session_manager_proxy_(
new org::chromium::SessionManagerInterfaceProxy(bus)) {
diff --git a/permission_broker/permission_broker.h b/permission_broker/permission_broker.h
index e378fa0..9c93414 100644
--- a/permission_broker/permission_broker.h
+++ b/permission_broker/permission_broker.h
@@ -19,7 +19,6 @@
#include <session_manager/dbus-proxies.h>
#include "permission_broker/dbus_adaptors/org.chromium.PermissionBroker.h"
-#include "permission_broker/firewall.h"
#include "permission_broker/port_tracker.h"
#include "permission_broker/rule_engine.h"
#include "permission_broker/usb_control.h"
@@ -97,7 +96,6 @@
RuleEngine rule_engine_;
brillo::dbus_utils::DBusObject dbus_object_;
- Firewall firewall_;
PortTracker port_tracker_;
UsbControl usb_control_;
UsbDriverTracker usb_driver_tracker_;
diff --git a/permission_broker/port_tracker.cc b/permission_broker/port_tracker.cc
index 7626d53..cf6e36e 100644
--- a/permission_broker/port_tracker.cc
+++ b/permission_broker/port_tracker.cc
@@ -59,6 +59,13 @@
constexpr const uint16_t kAdbServerPort = 5555;
constexpr const uint16_t kAdbProxyPort = 5550;
+const std::string ProtocolName(Protocol proto) {
+ if (proto == ModifyPortRuleRequest::INVALID_PROTOCOL) {
+ NOTREACHED() << "Unexpected L4 protocol value";
+ }
+ return base::ToLowerASCII(ModifyPortRuleRequest::Protocol_Name(proto));
+}
+
std::string RuleTypeName(PortTracker::PortRuleType type) {
switch (type) {
case PortTracker::kUnknownRule:
@@ -95,15 +102,13 @@
}
} // namespace
-PortTracker::PortTracker(Firewall* firewall)
+PortTracker::PortTracker()
: task_runner_{base::ThreadTaskRunnerHandle::Get()},
- epfd_{kInvalidHandle},
- firewall_{firewall} {}
+ epfd_{kInvalidHandle} {}
// Test-only.
-PortTracker::PortTracker(scoped_refptr<base::SequencedTaskRunner> task_runner,
- Firewall* firewall)
- : task_runner_{task_runner}, epfd_{kInvalidHandle}, firewall_{firewall} {}
+PortTracker::PortTracker(scoped_refptr<base::SequencedTaskRunner> task_runner)
+ : task_runner_{task_runner}, epfd_{kInvalidHandle} {}
PortTracker::~PortTracker() {
RevokeAllPortRules();
@@ -224,28 +229,7 @@
port_rules_[key].lifeline_fd = lifeline_fd;
lifeline_fds_[lifeline_fd] = key;
- bool success = false;
- switch (rule.type) {
- case kAccessRule:
- success = firewall_->AddAcceptRules(rule.proto, rule.input_dst_port,
- rule.input_ifname);
- break;
- case kLockdownRule:
- success =
- firewall_->AddLoopbackLockdownRules(rule.proto, rule.input_dst_port);
- break;
- case kForwardingRule:
- case kAdbForwardingRule:
- success = firewall_->AddIpv4ForwardRule(
- rule.proto, rule.input_dst_ip, rule.input_dst_port, rule.input_ifname,
- rule.dst_ip, rule.dst_port);
- break;
- default:
- LOG(ERROR) << "Unknown port rule type " << rule.type;
- break;
- }
-
- if (!success) {
+ if (!ModifyPortRule(ModifyPortRuleRequest::CREATE, rule)) {
// If we fail to punch the hole in the firewall, stop tracking the lifetime
// of the process.
LOG(ERROR) << "Failed to create rule " << rule;
@@ -572,22 +556,7 @@
}
port_rules_.erase(key);
lifeline_fds_.erase(rule.lifeline_fd);
- switch (rule.type) {
- case kAccessRule:
- return deleted && firewall_->DeleteAcceptRules(
- key.proto, key.input_dst_port, key.input_ifname);
- case kLockdownRule:
- return deleted && firewall_->DeleteLoopbackLockdownRules(
- key.proto, key.input_dst_port);
- case kForwardingRule:
- case kAdbForwardingRule:
- return deleted && firewall_->DeleteIpv4ForwardRule(
- rule.proto, rule.input_dst_ip, rule.input_dst_port,
- rule.input_ifname, rule.dst_ip, rule.dst_port);
- default:
- LOG(ERROR) << "Unknown port rule entry type " << rule.type;
- return false;
- }
+ return deleted && ModifyPortRule(ModifyPortRuleRequest::DELETE, rule);
}
bool PortTracker::InitializeEpollOnce() {
diff --git a/permission_broker/port_tracker.h b/permission_broker/port_tracker.h
index 2c0c510..9d50b1d 100644
--- a/permission_broker/port_tracker.h
+++ b/permission_broker/port_tracker.h
@@ -16,10 +16,13 @@
#include <base/sequenced_task_runner.h>
#include <patchpanel/proto_bindings/patchpanel_service.pb.h>
-#include "permission_broker/firewall.h"
-
namespace permission_broker {
+using patchpanel::ModifyPortRuleRequest;
+using Operation = patchpanel::ModifyPortRuleRequest::Operation;
+using Protocol = patchpanel::ModifyPortRuleRequest::Protocol;
+using RuleType = patchpanel::ModifyPortRuleRequest::RuleType;
+
class PortTracker {
public:
struct PortRuleKey {
@@ -71,7 +74,7 @@
uint16_t dst_port;
};
- explicit PortTracker(Firewall* firewall);
+ PortTracker();
virtual ~PortTracker();
bool AllowTcpPortAccess(uint16_t port, const std::string& iface, int dbus_fd);
@@ -103,8 +106,7 @@
void RevokeAllPortRules();
protected:
- PortTracker(scoped_refptr<base::SequencedTaskRunner> task_runner,
- Firewall* firewall);
+ explicit PortTracker(scoped_refptr<base::SequencedTaskRunner> task_runner);
private:
// Call patchpanel's DBus API to create or remove firewall rule.
@@ -138,10 +140,6 @@
// it requested.
std::map<int, PortRuleKey> lifeline_fds_;
- // |firewall_| is owned by the PermissionBroker object owning this instance
- // of PortTracker.
- Firewall* firewall_;
-
DISALLOW_COPY_AND_ASSIGN(PortTracker);
};
diff --git a/permission_broker/port_tracker_fuzzer.cc b/permission_broker/port_tracker_fuzzer.cc
index 5feabab..a38c7e7 100644
--- a/permission_broker/port_tracker_fuzzer.cc
+++ b/permission_broker/port_tracker_fuzzer.cc
@@ -14,24 +14,15 @@
namespace permission_broker {
-class FakeFirewall : public Firewall {
- public:
- FakeFirewall() = default;
- ~FakeFirewall() = default;
-
- private:
- // The fake's implementation always succeeds.
- int RunInMinijail(const std::vector<std::string>& argv) override { return 0; }
-
- DISALLOW_COPY_AND_ASSIGN(FakeFirewall);
-};
-
class FakePortTracker : public PortTracker {
public:
- explicit FakePortTracker(Firewall* firewall)
- : PortTracker(nullptr, firewall), next_fd_{1} {}
+ FakePortTracker() : PortTracker(nullptr), next_fd_{1} {}
~FakePortTracker() override = default;
+ bool ModifyPortRule(patchpanel::ModifyPortRuleRequest::Operation,
+ const PortRule& rule) override {
+ return true;
+ }
int AddLifelineFd(int dbus_fd) override { return next_fd_++; }
bool DeleteLifelineFd(int fd) override { return true; }
void CheckLifelineFds(bool reschedule_check) override {}
@@ -155,8 +146,7 @@
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
static Environment env;
- permission_broker::FakeFirewall firewall;
- permission_broker::FakePortTracker port_tracker(&firewall);
+ permission_broker::FakePortTracker port_tracker;
std::set<permission_broker::FuzzRequest> existing_rules;
FuzzedDataProvider provider(data, size);
diff --git a/permission_broker/port_tracker_test.cc b/permission_broker/port_tracker_test.cc
index 2fb5e13..f5a344d 100644
--- a/permission_broker/port_tracker_test.cc
+++ b/permission_broker/port_tracker_test.cc
@@ -9,8 +9,6 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
-#include "permission_broker/mock_firewall.h"
-
using ::testing::_;
using ::testing::Return;
using ::testing::SetArgPointee;
@@ -19,10 +17,14 @@
class MockPortTracker : public PortTracker {
public:
- explicit MockPortTracker(Firewall* firewall)
- : PortTracker(nullptr, firewall) {}
+ MockPortTracker() : PortTracker(nullptr) {}
~MockPortTracker() override = default;
+ MOCK_METHOD(bool,
+ ModifyPortRule,
+ (patchpanel::ModifyPortRuleRequest::Operation, const PortRule&),
+ (override));
+
MOCK_METHOD(int, AddLifelineFd, (int), (override));
MOCK_METHOD(bool, DeleteLifelineFd, (int), (override));
MOCK_METHOD(void, CheckLifelineFds, (bool), (override));
@@ -36,29 +38,10 @@
class PortTrackerTest : public testing::Test {
public:
- PortTrackerTest() : port_tracker_{&mock_firewall_} {}
+ PortTrackerTest() = default;
~PortTrackerTest() override = default;
protected:
- void SetMockExpectations(MockFirewall* firewall, bool success) {
- // Empty criterion matches all commands.
- firewall->SetRunInMinijailFailCriterion(std::vector<std::string>(), true,
- success);
- }
-
- void SetMockExpectationsPerExecutable(MockFirewall* firewall,
- bool ip4_success,
- bool ip6_success) {
- if (!ip4_success)
- firewall->SetRunInMinijailFailCriterion(
- std::vector<std::string>({kIpTablesPath}), true /* repeat */,
- false /* omit_failure */);
- if (!ip6_success)
- firewall->SetRunInMinijailFailCriterion(
- std::vector<std::string>({kIp6TablesPath}), true, false);
- }
-
- MockFirewall mock_firewall_;
MockPortTracker port_tracker_;
uint16_t tcp_port = 8080;
@@ -81,21 +64,21 @@
};
TEST_F(PortTrackerTest, AllowTcpPortAccess_Success) {
- SetMockExpectations(&mock_firewall_, true /* success */);
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _)).WillRepeatedly(Return(true));
EXPECT_CALL(port_tracker_, AddLifelineFd(dbus_fd)).WillOnce(Return(0));
ASSERT_TRUE(port_tracker_.AllowTcpPortAccess(tcp_port, interface, dbus_fd));
ASSERT_TRUE(port_tracker_.HasActiveRules());
}
TEST_F(PortTrackerTest, AllowUdpPortAccess_Success) {
- SetMockExpectations(&mock_firewall_, true /* success */);
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _)).WillRepeatedly(Return(true));
EXPECT_CALL(port_tracker_, AddLifelineFd(dbus_fd)).WillOnce(Return(0));
ASSERT_TRUE(port_tracker_.AllowUdpPortAccess(udp_port, interface, dbus_fd));
ASSERT_TRUE(port_tracker_.HasActiveRules());
}
TEST_F(PortTrackerTest, AllowTcpPortAccess_Twice) {
- SetMockExpectations(&mock_firewall_, true /* success */);
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _)).WillRepeatedly(Return(true));
EXPECT_CALL(port_tracker_, AddLifelineFd(dbus_fd)).WillOnce(Return(0));
EXPECT_CALL(port_tracker_, CheckLifelineFds(false));
ASSERT_TRUE(port_tracker_.AllowTcpPortAccess(tcp_port, interface, dbus_fd));
@@ -104,7 +87,7 @@
}
TEST_F(PortTrackerTest, AllowUdpPortAccess_Twice) {
- SetMockExpectations(&mock_firewall_, true /* success */);
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _)).WillRepeatedly(Return(true));
EXPECT_CALL(port_tracker_, AddLifelineFd(dbus_fd)).WillOnce(Return(0));
EXPECT_CALL(port_tracker_, CheckLifelineFds(false));
ASSERT_TRUE(port_tracker_.AllowUdpPortAccess(udp_port, interface, dbus_fd));
@@ -113,8 +96,9 @@
}
TEST_F(PortTrackerTest, AllowTcpPortAccess_FirewallFailure) {
- // Make 'iptables' fail.
- SetMockExpectations(&mock_firewall_, false /* success */);
+ // Make DBus call to patchpanel fail.
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _))
+ .WillRepeatedly(Return(false));
EXPECT_CALL(port_tracker_, AddLifelineFd(dbus_fd))
.WillOnce(Return(tracked_fd));
EXPECT_CALL(port_tracker_, DeleteLifelineFd(tracked_fd))
@@ -124,8 +108,9 @@
}
TEST_F(PortTrackerTest, AllowUdpPortAccess_FirewallFailure) {
- // Make 'iptables' fail.
- SetMockExpectations(&mock_firewall_, false /* success */);
+ // Make DBus call to patchpanel fail.
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _))
+ .WillRepeatedly(Return(false));
EXPECT_CALL(port_tracker_, AddLifelineFd(dbus_fd))
.WillOnce(Return(tracked_fd));
EXPECT_CALL(port_tracker_, DeleteLifelineFd(tracked_fd))
@@ -135,7 +120,7 @@
}
TEST_F(PortTrackerTest, AllowTcpPortAccess_EpollFailure) {
- SetMockExpectations(&mock_firewall_, true /* success */);
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _)).WillRepeatedly(Return(true));
// Make epoll(7) fail.
EXPECT_CALL(port_tracker_, AddLifelineFd(dbus_fd)).WillOnce(Return(-1));
ASSERT_FALSE(port_tracker_.AllowTcpPortAccess(tcp_port, interface, dbus_fd));
@@ -143,14 +128,14 @@
}
TEST_F(PortTrackerTest, AllowUdpPortAccess_EpollFailure) {
- SetMockExpectations(&mock_firewall_, true /* success */);
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _)).WillRepeatedly(Return(true));
// Make epoll(7) fail.
EXPECT_CALL(port_tracker_, AddLifelineFd(dbus_fd)).WillOnce(Return(-1));
ASSERT_FALSE(port_tracker_.AllowUdpPortAccess(udp_port, interface, dbus_fd));
}
TEST_F(PortTrackerTest, RevokeTcpPortAccess_Success) {
- SetMockExpectations(&mock_firewall_, true /* success */);
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _)).WillRepeatedly(Return(true));
EXPECT_CALL(port_tracker_, AddLifelineFd(dbus_fd))
.WillOnce(Return(tracked_fd));
ASSERT_TRUE(port_tracker_.AllowTcpPortAccess(tcp_port, interface, dbus_fd));
@@ -162,7 +147,7 @@
}
TEST_F(PortTrackerTest, RevokeUdpPortAccess_Success) {
- SetMockExpectations(&mock_firewall_, true /* success */);
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _)).WillRepeatedly(Return(true));
EXPECT_CALL(port_tracker_, AddLifelineFd(dbus_fd))
.WillOnce(Return(tracked_fd));
ASSERT_TRUE(port_tracker_.AllowUdpPortAccess(udp_port, interface, dbus_fd));
@@ -174,10 +159,10 @@
}
TEST_F(PortTrackerTest, RevokeTcpPortAccess_FirewallFailure) {
- // Make plugging the firewall hole fail.
- mock_firewall_.SetRunInMinijailFailCriterion(
- std::vector<std::string>({"-D", "-p", "tcp"}), true /* repeat */,
- false /* omit_failure */);
+ // Make revoke iptables rules DBus call fail.
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _))
+ .WillOnce(Return(true))
+ .WillOnce(Return(false));
EXPECT_CALL(port_tracker_, AddLifelineFd(dbus_fd))
.WillOnce(Return(tracked_fd));
@@ -190,10 +175,10 @@
}
TEST_F(PortTrackerTest, RevokeUdpPortAccess_DbusFailure) {
- // Make plugging the firewall hole fail.
- mock_firewall_.SetRunInMinijailFailCriterion(
- std::vector<std::string>({"-D", "-p", "udp"}), true /* repeat */,
- false /* omit_failure */);
+ // Make revoke iptables rules DBus call fail.
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _))
+ .WillOnce(Return(true))
+ .WillOnce(Return(false));
EXPECT_CALL(port_tracker_, AddLifelineFd(dbus_fd))
.WillOnce(Return(tracked_fd));
@@ -206,7 +191,7 @@
}
TEST_F(PortTrackerTest, RevokeTcpPortAccess_EpollFailure) {
- SetMockExpectations(&mock_firewall_, true /* success */);
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _)).WillRepeatedly(Return(true));
EXPECT_CALL(port_tracker_, AddLifelineFd(dbus_fd))
.WillOnce(Return(tracked_fd));
@@ -220,7 +205,7 @@
}
TEST_F(PortTrackerTest, RevokeUdpPortAccess_EpollFailure) {
- SetMockExpectations(&mock_firewall_, true /* success */);
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _)).WillRepeatedly(Return(true));
EXPECT_CALL(port_tracker_, AddLifelineFd(dbus_fd))
.WillOnce(Return(tracked_fd));
@@ -234,14 +219,14 @@
}
TEST_F(PortTrackerTest, LockDownLoopbackTcpPort_Success) {
- SetMockExpectations(&mock_firewall_, true /* success */);
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _)).WillRepeatedly(Return(true));
EXPECT_CALL(port_tracker_, AddLifelineFd(dbus_fd)).WillOnce(Return(0));
ASSERT_TRUE(port_tracker_.LockDownLoopbackTcpPort(tcp_port, dbus_fd));
ASSERT_TRUE(port_tracker_.HasActiveRules());
}
TEST_F(PortTrackerTest, LockDownLoopbackTcpPort_Twice) {
- SetMockExpectations(&mock_firewall_, true /* success */);
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _)).WillRepeatedly(Return(true));
EXPECT_CALL(port_tracker_, AddLifelineFd(dbus_fd)).WillOnce(Return(0));
EXPECT_CALL(port_tracker_, CheckLifelineFds(false));
ASSERT_TRUE(port_tracker_.LockDownLoopbackTcpPort(tcp_port, dbus_fd));
@@ -250,8 +235,9 @@
}
TEST_F(PortTrackerTest, LockDownLoopbackTcpPort_FirewallFailure) {
- // Make 'iptables' fail.
- SetMockExpectations(&mock_firewall_, false /* success */);
+ // Make DBus call to patchpanel fail.
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _))
+ .WillRepeatedly(Return(false));
EXPECT_CALL(port_tracker_, AddLifelineFd(dbus_fd))
.WillOnce(Return(tracked_fd));
EXPECT_CALL(port_tracker_, DeleteLifelineFd(tracked_fd))
@@ -261,7 +247,7 @@
}
TEST_F(PortTrackerTest, LockDownLoopbackTcpPort_EpollFailure) {
- SetMockExpectations(&mock_firewall_, true /* success */);
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _)).WillRepeatedly(Return(true));
// Make epoll(7) fail.
EXPECT_CALL(port_tracker_, AddLifelineFd(dbus_fd)).WillOnce(Return(-1));
ASSERT_FALSE(port_tracker_.LockDownLoopbackTcpPort(tcp_port, dbus_fd));
@@ -269,7 +255,7 @@
}
TEST_F(PortTrackerTest, ReleaseLoopbackTcpPort_Success) {
- SetMockExpectations(&mock_firewall_, true /* success */);
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _)).WillRepeatedly(Return(true));
EXPECT_CALL(port_tracker_, AddLifelineFd(dbus_fd))
.WillOnce(Return(tracked_fd));
ASSERT_TRUE(port_tracker_.LockDownLoopbackTcpPort(tcp_port, dbus_fd));
@@ -281,11 +267,10 @@
}
TEST_F(PortTrackerTest, ReleaseLoopbackTcpPort_FirewallFailure) {
- // Make releasing the lockdown fail.
- mock_firewall_.SetRunInMinijailFailCriterion(
- std::vector<std::string>({"-D", "-p", "tcp"}), true /* repeat */,
- false /* omit_failure */);
-
+ // Make revoke iptables rules DBus call fail.
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _))
+ .WillOnce(Return(true))
+ .WillOnce(Return(false));
EXPECT_CALL(port_tracker_, AddLifelineFd(dbus_fd))
.WillOnce(Return(tracked_fd));
ASSERT_TRUE(port_tracker_.LockDownLoopbackTcpPort(tcp_port, dbus_fd));
@@ -297,8 +282,7 @@
}
TEST_F(PortTrackerTest, ReleaseLoopbackTcpPort_EpollFailure) {
- SetMockExpectations(&mock_firewall_, true /* success */);
-
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _)).WillRepeatedly(Return(true));
EXPECT_CALL(port_tracker_, AddLifelineFd(dbus_fd))
.WillOnce(Return(tracked_fd));
ASSERT_TRUE(port_tracker_.LockDownLoopbackTcpPort(tcp_port, dbus_fd));
@@ -311,7 +295,7 @@
}
TEST_F(PortTrackerTest, StartPortForwarding_BaseSuccessCase) {
- SetMockExpectations(&mock_firewall_, true /* success */);
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _)).WillRepeatedly(Return(true));
EXPECT_CALL(port_tracker_, AddLifelineFd(dbus_fd)).WillOnce(Return(5));
ASSERT_TRUE(port_tracker_.StartTcpPortForwarding(
tcp_port, "eth0", crosvm_addr, tcp_port, dbus_fd));
@@ -329,19 +313,18 @@
udp_port, "wlan0", pluginvm_addr, udp_port, dbus_fd));
ASSERT_TRUE(port_tracker_.HasActiveRules());
- ASSERT_EQ(8, mock_firewall_.CountActiveCommands());
}
TEST_F(PortTrackerTest, StartAdbPortForwarding_BaseSuccessCase) {
- SetMockExpectations(&mock_firewall_, true /* success */);
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _)).WillRepeatedly(Return(true));
EXPECT_CALL(port_tracker_, AddLifelineFd(dbus_fd)).WillOnce(Return(7));
ASSERT_TRUE(port_tracker_.StartAdbPortForwarding("vmtap0", dbus_fd));
ASSERT_TRUE(port_tracker_.HasActiveRules());
- ASSERT_EQ(2, mock_firewall_.CountActiveCommands());
}
TEST_F(PortTrackerTest, StartPortForwarding_LifelineFdFailure) {
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _)).WillRepeatedly(Return(true));
EXPECT_CALL(port_tracker_, AddLifelineFd(dbus_fd)).WillOnce(Return(-1));
ASSERT_FALSE(port_tracker_.StartTcpPortForwarding(
tcp_port, "eth0", crosvm_addr, tcp_port, dbus_fd));
@@ -354,6 +337,7 @@
}
TEST_F(PortTrackerTest, StartAdbPortForwarding_LifelineFdFailure) {
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _)).WillRepeatedly(Return(true));
EXPECT_CALL(port_tracker_, AddLifelineFd(dbus_fd)).WillOnce(Return(-1));
ASSERT_FALSE(port_tracker_.StartAdbPortForwarding("vmtap0", dbus_fd));
@@ -361,7 +345,8 @@
}
TEST_F(PortTrackerTest, StartPortForwarding_IptablesFailure) {
- SetMockExpectations(&mock_firewall_, false /* failure */);
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _))
+ .WillRepeatedly(Return(false));
EXPECT_CALL(port_tracker_, AddLifelineFd(dbus_fd)).WillOnce(Return(5));
EXPECT_CALL(port_tracker_, DeleteLifelineFd(5)).WillOnce(Return(true));
@@ -377,7 +362,8 @@
}
TEST_F(PortTrackerTest, StartAdbPortForwarding_IptablesFailure) {
- SetMockExpectations(&mock_firewall_, false /* failure */);
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _))
+ .WillRepeatedly(Return(false));
EXPECT_CALL(port_tracker_, AddLifelineFd(dbus_fd)).WillOnce(Return(7));
EXPECT_CALL(port_tracker_, DeleteLifelineFd(7)).WillOnce(Return(true));
@@ -387,6 +373,8 @@
}
TEST_F(PortTrackerTest, StartPortForwarding_InputPortValidation) {
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _)).WillRepeatedly(Return(true));
+
ASSERT_FALSE(port_tracker_.StartTcpPortForwarding(
reserved_port, "eth0", crosvm_addr, tcp_port, dbus_fd));
ASSERT_FALSE(port_tracker_.StartUdpPortForwarding(
@@ -400,10 +388,11 @@
ASSERT_TRUE(port_tracker_.StartUdpPortForwarding(
tcp_port, "eth0", crosvm_addr, reserved_port, dbus_fd));
ASSERT_TRUE(port_tracker_.HasActiveRules());
- ASSERT_EQ(4, mock_firewall_.CountActiveCommands());
}
TEST_F(PortTrackerTest, StartPortForwarding_InputInterfaceValidation) {
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _)).WillRepeatedly(Return(true));
+
ASSERT_FALSE(port_tracker_.StartTcpPortForwarding(tcp_port, "", crosvm_addr,
tcp_port, dbus_fd));
ASSERT_FALSE(port_tracker_.StartUdpPortForwarding(tcp_port, "", crosvm_addr,
@@ -436,10 +425,11 @@
tcp_port, "mlan0", crosvm_addr, tcp_port, dbus_fd));
ASSERT_TRUE(port_tracker_.HasActiveRules());
- ASSERT_EQ(10, mock_firewall_.CountActiveCommands());
}
TEST_F(PortTrackerTest, StartAdbPortForwarding_InputInterfaceValidation) {
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _)).WillRepeatedly(Return(true));
+
ASSERT_FALSE(port_tracker_.StartAdbPortForwarding("", dbus_fd));
ASSERT_FALSE(port_tracker_.StartAdbPortForwarding("lo", dbus_fd));
ASSERT_FALSE(port_tracker_.StartAdbPortForwarding("iface0", dbus_fd));
@@ -448,10 +438,11 @@
ASSERT_TRUE(port_tracker_.StartAdbPortForwarding("vmtap1", dbus_fd));
ASSERT_TRUE(port_tracker_.HasActiveRules());
- ASSERT_EQ(4, mock_firewall_.CountActiveCommands());
}
TEST_F(PortTrackerTest, StartPortForwarding_TargetIpAddressValidation) {
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _)).WillRepeatedly(Return(true));
+
ASSERT_FALSE(port_tracker_.StartTcpPortForwarding(
tcp_port, "eth0", "not_an_ip", tcp_port, dbus_fd));
ASSERT_FALSE(port_tracker_.StartTcpPortForwarding(tcp_port, "eth0", ipv4_any,
@@ -469,6 +460,7 @@
}
TEST_F(PortTrackerTest, StopPortForwarding) {
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _)).WillRepeatedly(Return(true));
// Cannot stop before starting.
ASSERT_FALSE(port_tracker_.StopTcpPortForwarding(tcp_port, "eth0"));
ASSERT_FALSE(port_tracker_.StopUdpPortForwarding(tcp_port, "eth0"));
@@ -493,6 +485,7 @@
}
TEST_F(PortTrackerTest, StopAdbPortForwarding) {
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _)).WillRepeatedly(Return(true));
// Cannot stop before starting.
ASSERT_FALSE(port_tracker_.StopAdbPortForwarding("vmtap0"));
@@ -509,6 +502,7 @@
}
TEST_F(PortTrackerTest, StartPortForwarding_PreventOverwrite) {
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _)).WillRepeatedly(Return(true));
EXPECT_CALL(port_tracker_, AddLifelineFd(dbus_fd)).WillOnce(Return(5));
ASSERT_TRUE(port_tracker_.StartTcpPortForwarding(
tcp_port, "eth0", crosvm_addr, tcp_port, dbus_fd));
@@ -546,7 +540,7 @@
}
TEST_F(PortTrackerTest, StartPortForwarding_PreventForwardingOpenPort) {
- SetMockExpectations(&mock_firewall_, true /* success */);
+ EXPECT_CALL(port_tracker_, ModifyPortRule(_, _)).WillRepeatedly(Return(true));
// Open TCP port, that port cannot be forwarded for the same interface.
EXPECT_CALL(port_tracker_, AddLifelineFd(dbus_fd)).WillOnce(Return(5));