diff options
author | Nathan Harold <nharold@google.com> | 2018-04-25 00:42:39 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2018-04-25 00:42:39 +0000 |
commit | 7c36c990943039386e40d218264d7a1d3cef4243 (patch) | |
tree | ed20ca2278efb6a85606f7e2397d1ec7fab786a9 | |
parent | 883abcef8e2ea0612e2226c8e2d05ddc1fb00592 (diff) | |
parent | f5646cde551de44ba10b61c2d5cecb414847d454 (diff) | |
download | netd-7c36c990943039386e40d218264d7a1d3cef4243.tar.gz |
Merge changes from topic "netd-restart" into pi-dev
* changes:
Add Functions to flush SADB, Policy DB, and Ifaces
Factor getIfaceNames() from getIfaceList()
Restart main when netd restarts
-rw-r--r-- | server/Controllers.cpp | 7 | ||||
-rw-r--r-- | server/InterfaceController.cpp | 24 | ||||
-rw-r--r-- | server/InterfaceController.h | 1 | ||||
-rw-r--r-- | server/InterfaceControllerTest.cpp | 13 | ||||
-rw-r--r-- | server/NetdNativeService.cpp | 1 | ||||
-rw-r--r-- | server/XfrmController.cpp | 44 | ||||
-rw-r--r-- | server/XfrmController.h | 82 | ||||
-rw-r--r-- | server/netd.rc | 2 | ||||
-rw-r--r-- | tests/Android.mk | 4 | ||||
-rw-r--r-- | tests/binder_test.cpp | 69 |
10 files changed, 197 insertions, 50 deletions
diff --git a/server/Controllers.cpp b/server/Controllers.cpp index b0b1925b..221a20a3 100644 --- a/server/Controllers.cpp +++ b/server/Controllers.cpp @@ -30,6 +30,7 @@ #include "RouteController.h" #include "Stopwatch.h" #include "oem_iptables_hook.h" +#include "XfrmController.h" namespace android { namespace net { @@ -279,6 +280,12 @@ void Controllers::init() { ALOGE("failed to initialize RouteController (%s)", strerror(-ret)); } ALOGI("Initializing RouteController: %.1fms", s.getTimeAndReset()); + + netdutils::Status xStatus = XfrmController::Init(); + if (!isOk(xStatus)) { + ALOGE("Failed to initialize XfrmController (%s)", netdutils::toString(xStatus).c_str()); + }; + ALOGI("Initializing XfrmController: %.1fms", s.getTimeAndReset()); } Controllers* gCtls = nullptr; diff --git a/server/InterfaceController.cpp b/server/InterfaceController.cpp index 5a630255..c0210d7b 100644 --- a/server/InterfaceController.cpp +++ b/server/InterfaceController.cpp @@ -43,6 +43,7 @@ using android::base::StringPrintf; using android::base::WriteStringToFile; using android::net::INetd; using android::net::RouteController; +using android::netdutils::isOk; using android::netdutils::Status; using android::netdutils::StatusOr; using android::netdutils::makeSlice; @@ -388,8 +389,8 @@ void InterfaceController::setIPv6OptimisticMode(const char *value) { setOnAllInterfaces(ipv6_proc_path, "use_optimistic", value); } -StatusOr<std::map<std::string, uint32_t>> InterfaceController::getIfaceList() { - std::map<std::string, uint32_t> ifacePairs; +StatusOr<std::vector<std::string>> InterfaceController::getIfaceNames() { + std::vector<std::string> ifaceNames; DIR* d; struct dirent* de; @@ -398,11 +399,22 @@ StatusOr<std::map<std::string, uint32_t>> InterfaceController::getIfaceList() { } while ((de = readdir(d))) { if (de->d_name[0] == '.') continue; - uint32_t ifaceIndex = if_nametoindex(de->d_name); - if (ifaceIndex) { - ifacePairs.insert(std::pair<std::string, uint32_t>(de->d_name, ifaceIndex)); - } + ifaceNames.push_back(std::string(de->d_name)); } closedir(d); + return ifaceNames; +} + +StatusOr<std::map<std::string, uint32_t>> InterfaceController::getIfaceList() { + std::map<std::string, uint32_t> ifacePairs; + + ASSIGN_OR_RETURN(auto ifaceNames, getIfaceNames()); + + for (const auto& name : ifaceNames) { + uint32_t ifaceIndex = if_nametoindex(name.c_str()); + if (ifaceIndex) { + ifacePairs.insert(std::pair<std::string, uint32_t>(name, ifaceIndex)); + } + } return ifacePairs; } diff --git a/server/InterfaceController.h b/server/InterfaceController.h index 9a2e5e44..cd6f0eb2 100644 --- a/server/InterfaceController.h +++ b/server/InterfaceController.h @@ -53,6 +53,7 @@ public: const char *family, const char *which, const char *interface, const char *parameter, const char *value); + static android::netdutils::StatusOr<std::vector<std::string>> getIfaceNames(); static android::netdutils::StatusOr<std::map<std::string, uint32_t>> getIfaceList(); private: diff --git a/server/InterfaceControllerTest.cpp b/server/InterfaceControllerTest.cpp index 0cf7cfc1..fc5dce12 100644 --- a/server/InterfaceControllerTest.cpp +++ b/server/InterfaceControllerTest.cpp @@ -178,6 +178,19 @@ TEST_F(StablePrivacyTest, ExistingPropertyWriteFail) { class GetIfaceListTest : public testing::Test {}; +TEST_F(GetIfaceListTest, IfaceNames) { + StatusOr<std::vector<std::string>> ifaceNames = InterfaceController::getIfaceNames(); + EXPECT_EQ(ok, ifaceNames.status()); + struct ifaddrs *ifaddr, *ifa; + EXPECT_EQ(0, getifaddrs(&ifaddr)); + for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { + const auto val = std::find( + ifaceNames.value().begin(), ifaceNames.value().end(), ifa->ifa_name); + EXPECT_NE(ifaceNames.value().end(), val); + } + freeifaddrs(ifaddr); +} + TEST_F(GetIfaceListTest, IfaceExist) { StatusOr<std::map<std::string, uint32_t>> ifaceMap = InterfaceController::getIfaceList(); EXPECT_EQ(ok, ifaceMap.status()); diff --git a/server/NetdNativeService.cpp b/server/NetdNativeService.cpp index d953f3a2..c1e3ffa3 100644 --- a/server/NetdNativeService.cpp +++ b/server/NetdNativeService.cpp @@ -475,7 +475,6 @@ binder::Status NetdNativeService::ipSecSetEncapSocketOwner(const android::base:: return asBinderStatus(gCtls->xfrmCtrl.ipSecSetEncapSocketOwner(socket, newUid, callerUid)); } - binder::Status NetdNativeService::ipSecAllocateSpi( int32_t transformId, const std::string& sourceAddress, diff --git a/server/XfrmController.cpp b/server/XfrmController.cpp index 744728a6..adc02b78 100644 --- a/server/XfrmController.cpp +++ b/server/XfrmController.cpp @@ -39,6 +39,7 @@ #include <sys/wait.h> #include <linux/in.h> +#include <linux/ipsec.h> #include <linux/netlink.h> #include <linux/xfrm.h> @@ -47,6 +48,7 @@ #include "android-base/unique_fd.h" #include <log/log_properties.h> #define LOG_TAG "XfrmController" +#include "InterfaceController.h" #include "NetdConstants.h" #include "NetlinkCommands.h" #include "ResponseCode.h" @@ -83,6 +85,9 @@ constexpr uint32_t RAND_SPI_MAX = 0xFFFFFFFE; constexpr uint32_t INVALID_SPI = 0; +// Must match TUNNEL_INTERFACE_PREFIX in IpSecService.java +constexpr char const* TUNNEL_INTERFACE_PREFIX = "ipsec"; + #define XFRM_MSG_TRANS(x) \ case x: \ return #x; @@ -370,6 +375,45 @@ private: // XfrmController::XfrmController(void) {} +netdutils::Status XfrmController::Init() { + RETURN_IF_NOT_OK(flushInterfaces()); + XfrmSocketImpl sock; + RETURN_IF_NOT_OK(sock.open()); + RETURN_IF_NOT_OK(flushSaDb(sock)); + return flushPolicyDb(sock); +} + +netdutils::Status XfrmController::flushInterfaces() { + const auto& ifaces = InterfaceController::getIfaceNames(); + RETURN_IF_NOT_OK(ifaces); + + for (const std::string& iface : ifaces.value()) { + int status = 0; + // Look for the reserved interface prefix, which must be in the name at position 0 + if (iface.find(TUNNEL_INTERFACE_PREFIX) == 0 && + (status = removeVirtualTunnelInterface(iface)) < 0) { + ALOGE("Failed to delete ipsec tunnel %s.", iface.c_str()); + return netdutils::statusFromErrno(status, "Failed to remove ipsec tunnel."); + } + } + return netdutils::status::ok; +} + +netdutils::Status XfrmController::flushSaDb(const XfrmSocket& s) { + struct xfrm_usersa_flush flushUserSa = {.proto = IPSEC_PROTO_ANY}; + + std::vector<iovec> iov = {{NULL, 0}, // reserved for the eventual addition of a NLMSG_HDR + {&flushUserSa, sizeof(flushUserSa)}, // xfrm_usersa_flush structure + {kPadBytes, NLMSG_ALIGN(sizeof(flushUserSa)) - sizeof(flushUserSa)}}; + + return s.sendMessage(XFRM_MSG_FLUSHSA, NETLINK_REQUEST_FLAGS, 0, &iov); +} + +netdutils::Status XfrmController::flushPolicyDb(const XfrmSocket& s) { + std::vector<iovec> iov = {{NULL, 0}}; // reserved for the eventual addition of a NLMSG_HDR + return s.sendMessage(XFRM_MSG_FLUSHPOLICY, NETLINK_REQUEST_FLAGS, 0, &iov); +} + netdutils::Status XfrmController::ipSecSetEncapSocketOwner(const android::base::unique_fd& socket, int newUid, uid_t callerUid) { ALOGD("XfrmController:%s, line=%d", __FUNCTION__, __LINE__); diff --git a/server/XfrmController.h b/server/XfrmController.h index 298fae66..f21dfa1c 100644 --- a/server/XfrmController.h +++ b/server/XfrmController.h @@ -125,14 +125,16 @@ class XfrmController { public: XfrmController(); - netdutils::Status ipSecSetEncapSocketOwner(const android::base::unique_fd& socket, int newUid, - uid_t callerUid); + static netdutils::Status Init(); - netdutils::Status ipSecAllocateSpi(int32_t transformId, const std::string& localAddress, - const std::string& remoteAddress, int32_t inSpi, - int32_t* outSpi); + static netdutils::Status ipSecSetEncapSocketOwner(const android::base::unique_fd& socket, + int newUid, uid_t callerUid); - netdutils::Status ipSecAddSecurityAssociation( + static netdutils::Status ipSecAllocateSpi(int32_t transformId, const std::string& localAddress, + const std::string& remoteAddress, int32_t inSpi, + int32_t* outSpi); + + static netdutils::Status ipSecAddSecurityAssociation( int32_t transformId, int32_t mode, const std::string& sourceAddress, const std::string& destinationAddress, int32_t underlyingNetId, int32_t spi, int32_t markValue, int32_t markMask, const std::string& authAlgo, @@ -141,41 +143,43 @@ public: const std::vector<uint8_t>& aeadKey, int32_t aeadIcvBits, int32_t encapType, int32_t encapLocalPort, int32_t encapRemotePort); - netdutils::Status ipSecDeleteSecurityAssociation(int32_t transformId, - const std::string& sourceAddress, - const std::string& destinationAddress, - int32_t spi, int32_t markValue, - int32_t markMask); + static netdutils::Status ipSecDeleteSecurityAssociation(int32_t transformId, + const std::string& sourceAddress, + const std::string& destinationAddress, + int32_t spi, int32_t markValue, + int32_t markMask); - netdutils::Status ipSecApplyTransportModeTransform(const android::base::unique_fd& socket, - int32_t transformId, int32_t direction, - const std::string& localAddress, - const std::string& remoteAddress, - int32_t spi); + static netdutils::Status + ipSecApplyTransportModeTransform(const android::base::unique_fd& socket, int32_t transformId, + int32_t direction, const std::string& localAddress, + const std::string& remoteAddress, int32_t spi); - netdutils::Status ipSecRemoveTransportModeTransform(const android::base::unique_fd& socket); + static netdutils::Status + ipSecRemoveTransportModeTransform(const android::base::unique_fd& socket); - netdutils::Status ipSecAddSecurityPolicy(int32_t transformId, int32_t direction, - const std::string& sourceAddress, - const std::string& destinationAddress, int32_t spi, - int32_t markValue, int32_t markMask); + static netdutils::Status ipSecAddSecurityPolicy(int32_t transformId, int32_t direction, + const std::string& sourceAddress, + const std::string& destinationAddress, + int32_t spi, int32_t markValue, + int32_t markMask); - netdutils::Status ipSecUpdateSecurityPolicy(int32_t transformId, int32_t direction, - const std::string& sourceAddress, - const std::string& destinationAddress, int32_t spi, - int32_t markValue, int32_t markMask); + static netdutils::Status ipSecUpdateSecurityPolicy(int32_t transformId, int32_t direction, + const std::string& sourceAddress, + const std::string& destinationAddress, + int32_t spi, int32_t markValue, + int32_t markMask); - netdutils::Status ipSecDeleteSecurityPolicy(int32_t transformId, int32_t direction, - const std::string& sourceAddress, - const std::string& destinationAddress, - int32_t markValue, int32_t markMask); + static netdutils::Status ipSecDeleteSecurityPolicy(int32_t transformId, int32_t direction, + const std::string& sourceAddress, + const std::string& destinationAddress, + int32_t markValue, int32_t markMask); - int addVirtualTunnelInterface(const std::string& deviceName, - const std::string& localAddress, - const std::string& remoteAddress, - int32_t ikey, int32_t okey, bool isUpdate); + static int addVirtualTunnelInterface(const std::string& deviceName, + const std::string& localAddress, + const std::string& remoteAddress, int32_t ikey, + int32_t okey, bool isUpdate); - int removeVirtualTunnelInterface(const std::string& deviceName); + static int removeVirtualTunnelInterface(const std::string& deviceName); // Some XFRM netlink attributes comprise a header, a struct, and some data // after the struct. We wrap all of those in one struct for easier @@ -323,9 +327,9 @@ private: static netdutils::Status processSecurityPolicy(int32_t transformId, int32_t direction, const std::string& localAddress, - const std::string& remoteAddress, - int32_t spi, int32_t markValue, - int32_t markMask, int32_t msgType); + const std::string& remoteAddress, int32_t spi, + int32_t markValue, int32_t markMask, + int32_t msgType); static netdutils::Status updateTunnelModeSecurityPolicy(const XfrmSaInfo& record, const XfrmSocket& sock, XfrmDirection direction, @@ -333,6 +337,10 @@ private: static netdutils::Status deleteTunnelModeSecurityPolicy(const XfrmSaInfo& record, const XfrmSocket& sock, XfrmDirection direction); + static netdutils::Status flushInterfaces(); + static netdutils::Status flushSaDb(const XfrmSocket& s); + static netdutils::Status flushPolicyDb(const XfrmSocket& s); + // END TODO(messagerefactor) }; diff --git a/server/netd.rc b/server/netd.rc index 4fc6fd8c..81006369 100644 --- a/server/netd.rc +++ b/server/netd.rc @@ -4,3 +4,5 @@ service netd /system/bin/netd socket dnsproxyd stream 0660 root inet socket mdns stream 0660 root system socket fwmarkd stream 0660 root inet + onrestart restart zygote + onrestart restart zygote_secondary diff --git a/tests/Android.mk b/tests/Android.mk index a6fd308e..a2440ea3 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -49,7 +49,9 @@ LOCAL_SRC_FILES := binder_test.cpp \ ../server/dns/DnsTlsServer.cpp \ ../server/dns/DnsTlsSessionCache.cpp \ ../server/dns/DnsTlsSocket.cpp \ - + ../server/InterfaceController.cpp \ + ../server/NetlinkCommands.cpp \ + ../server/XfrmController.cpp LOCAL_MODULE_TAGS := eng tests include $(BUILD_NATIVE_TEST) diff --git a/tests/binder_test.cpp b/tests/binder_test.cpp index 51314f52..0913aa5f 100644 --- a/tests/binder_test.cpp +++ b/tests/binder_test.cpp @@ -42,12 +42,15 @@ #include <logwrap/logwrap.h> #include <netutils/ifc.h> +#include "InterfaceController.h" #include "NetdConstants.h" #include "Stopwatch.h" +#include "XfrmController.h" #include "tun_interface.h" #include "android/net/INetd.h" #include "android/net/UidRange.h" #include "binder/IServiceManager.h" +#include "netdutils/Syscalls.h" #define IP_PATH "/system/bin/ip" #define IP6TABLES_PATH "/system/bin/ip6tables" @@ -61,6 +64,8 @@ using android::base::StartsWith; using android::net::INetd; using android::net::TunInterface; using android::net::UidRange; +using android::net::XfrmController; +using android::netdutils::sSyscalls; using android::os::PersistableBundle; static const char* IP_RULE_V4 = "-4"; @@ -92,6 +97,8 @@ public: mNetd->networkDestroy(TEST_NETID2); } + bool allocateIpSecResources(bool expectOk, int32_t *spi); + // Static because setting up the tun interface takes about 40ms. static void SetUpTestCase() { ASSERT_EQ(0, sTun.init()); @@ -252,18 +259,18 @@ TEST_F(BinderTest, TestVirtualTunnelInterface) { int32_t iKey; int32_t oKey; } kTestData[] = { - { "IPV4", "test_vti", "127.0.0.1", "8.8.8.8", 0x1234 + 53, 0x1234 + 53 }, - { "IPV6", "test_vti6", "::1", "2001:4860:4860::8888", 0x1234 + 50, 0x1234 + 50 }, + {"IPV4", "test_vti", "127.0.0.1", "8.8.8.8", 0x1234 + 53, 0x1234 + 53}, + {"IPV6", "test_vti6", "::1", "2001:4860:4860::8888", 0x1234 + 50, 0x1234 + 50}, }; for (unsigned int i = 0; i < arraysize(kTestData); i++) { - const auto &td = kTestData[i]; + const auto& td = kTestData[i]; binder::Status status; // Create Virtual Tunnel Interface. - status = mNetd->addVirtualTunnelInterface(td.deviceName, td.localAddress, - td.remoteAddress, td.iKey, td.oKey); + status = mNetd->addVirtualTunnelInterface(td.deviceName, td.localAddress, td.remoteAddress, + td.iKey, td.oKey); EXPECT_TRUE(status.isOk()) << td.family << status.exceptionMessage(); // Update Virtual Tunnel Interface. @@ -277,6 +284,58 @@ TEST_F(BinderTest, TestVirtualTunnelInterface) { } } +#define RETURN_FALSE_IF_NEQ(_expect_, _ret_) \ + do { if ((_expect_) != (_ret_)) return false; } while(false) +bool BinderTest::allocateIpSecResources(bool expectOk, int32_t *spi) { + netdutils::Status status = XfrmController::ipSecAllocateSpi(0, "::", "::1", 123, spi); + SCOPED_TRACE(status); + RETURN_FALSE_IF_NEQ(status.ok(), expectOk); + + // Add a policy + status = XfrmController::ipSecAddSecurityPolicy(0, 0, "::", "::1", 123, 0, 0); + SCOPED_TRACE(status); + RETURN_FALSE_IF_NEQ(status.ok(), expectOk); + + // Add an ipsec interface + status = netdutils::statusFromErrno( + XfrmController::addVirtualTunnelInterface( + "ipsec_test", "::", "::1", 0xF00D, 0xD00D, false), + "addVirtualTunnelInterface"); + return (status.ok() == expectOk); +} + + +TEST_F(BinderTest, TestXfrmControllerInit) { + netdutils::Status status; + status = XfrmController::Init(); + SCOPED_TRACE(status); + ASSERT_TRUE(status.ok()); + + int32_t spi = 0; + + ASSERT_TRUE(allocateIpSecResources(true, &spi)); + ASSERT_TRUE(allocateIpSecResources(false, &spi)); + + status = XfrmController::Init(); + ASSERT_TRUE(allocateIpSecResources(true, &spi)); + + // Clean up + status = XfrmController::ipSecDeleteSecurityAssociation(0, "::", "::1", 123, spi, 0); + SCOPED_TRACE(status); + ASSERT_TRUE(status.ok()); + + status = XfrmController::ipSecDeleteSecurityPolicy(0, 0, "::", "::1", 0, 0); + SCOPED_TRACE(status); + ASSERT_TRUE(status.ok()); + + // Remove Virtual Tunnel Interface. + status = netdutils::statusFromErrno( + XfrmController::removeVirtualTunnelInterface("ipsec_test"), + "removeVirtualTunnelInterface"); + + ASSERT_TRUE(status.ok()); +} + static int bandwidthDataSaverEnabled(const char *binary) { std::vector<std::string> lines = listIptablesRule(binary, "bw_data_saver"); |