[automerger skipped] Add test coverage for VPN local exclusion am: 7c9888cb0b -s ours
am skip reason: Merged-In Ibd47718b4e64048f815bd49737e362e6360bcd98 with SHA-1 d73826d98c is already in history
Original change: https://googleplex-android-review.googlesource.com/c/platform/system/netd/+/19997517
Change-Id: I0e80d82c4cfcd9896cab1f25ee37ab350828c507
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/Android.bp b/Android.bp
index b654f76..8771237 100644
--- a/Android.bp
+++ b/Android.bp
@@ -85,14 +85,13 @@
"-performance-noexcept-move-constructor",
"-performance-unnecessary-value-param",
],
- tidy_flags: [
- "-warnings-as-errors="
- + "android-*,"
- + "bugprone-*,"
- + "cert-*,"
- + "clang-analyzer-security*,"
- + "google-*,"
- + "misc-*,"
- + "performance-*"
+ tidy_checks_as_errors: [
+ "android-*",
+ "bugprone-*",
+ "cert-*",
+ "clang-analyzer-security*",
+ "google-*",
+ "misc-*",
+ "performance-*",
],
}
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 4a9fa19..5e200e9 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -14,8 +14,10 @@
"imports": [
{ "path": "packages/modules/DnsResolver" }
],
- "hwasan-postsubmit": [
+ "hwasan-presubmit": [
{ "name": "netd_integration_test" },
- { "name": "netd_unit_test" }
+ { "name": "netd_unit_test" },
+ { "name": "netdclient_test" },
+ { "name": "netdutils_test" }
]
}
diff --git a/server/Android.bp b/server/Android.bp
index 06ea0ba..615e740 100644
--- a/server/Android.bp
+++ b/server/Android.bp
@@ -97,6 +97,7 @@
"system/netd/include",
],
init_rc: ["netd.rc"],
+ vintf_fragments: ["android.system.net.netd-service.xml"],
required: [
"bpfloader",
],
@@ -104,8 +105,10 @@
shared_libs: [
"android.system.net.netd@1.0",
"android.system.net.netd@1.1",
+ "android.system.net.netd-V1-ndk",
"libbase",
"libbinder",
+ "libbinder_ndk",
"libcutils",
"libdl",
"libhidlbase",
@@ -138,6 +141,7 @@
"MDnsSdListener.cpp",
"MDnsService.cpp",
"NetdCommand.cpp",
+ "NetdHwAidlService.cpp",
"NetdHwService.cpp",
"NetdNativeService.cpp",
"NetlinkHandler.cpp",
diff --git a/server/Controllers.cpp b/server/Controllers.cpp
index 00ee186..43a2d1e 100644
--- a/server/Controllers.cpp
+++ b/server/Controllers.cpp
@@ -131,7 +131,7 @@
std::string command = StringPrintf("*%s\n-S %s\nCOMMIT\n", table, parentChain);
std::string output;
if (Controllers::execIptablesRestoreWithOutput(target, command, &output) == -1) {
- ALOGE("Error listing chain %s in table %s\n", parentChain, table);
+ ALOGE("Error listing chain %s in table %s", parentChain, table);
return existing;
}
diff --git a/server/FirewallController.h b/server/FirewallController.h
index 6d6f48f..1bff064 100644
--- a/server/FirewallController.h
+++ b/server/FirewallController.h
@@ -52,8 +52,6 @@
/* Match traffic owned by given UID. This is specific to a particular chain. */
int setUidRule(ChildChain, int, FirewallRule);
- int enableChildChains(ChildChain, bool);
-
static std::string makeCriticalCommands(IptablesTarget target, const char* chainName);
static const char* TABLE;
diff --git a/server/InterfaceControllerTest.cpp b/server/InterfaceControllerTest.cpp
index 006018d..8075431 100644
--- a/server/InterfaceControllerTest.cpp
+++ b/server/InterfaceControllerTest.cpp
@@ -22,6 +22,7 @@
#include <gtest/gtest.h>
#include <netdutils/MockSyscalls.h>
+#include <netdutils/NetNativeTestBase.h>
#include <netdutils/Utils.h>
#include "InterfaceController.h"
@@ -66,7 +67,7 @@
} // namespace
-class StablePrivacyTest : public testing::Test {
+class StablePrivacyTest : public NetNativeTestBase {
protected:
void expectOpenFile(const std::string& path, const Fd fd, int err) {
if (err == 0) {
@@ -179,7 +180,7 @@
EXPECT_NE(ok, enableStablePrivacyAddresses(kTestIface));
}
-class GetIfaceListTest : public testing::Test {};
+class GetIfaceListTest : public NetNativeTestBase {};
TEST_F(GetIfaceListTest, IfaceNames) {
StatusOr<std::vector<std::string>> ifaceNames = getIfaceNames();
diff --git a/server/IptablesBaseTest.cpp b/server/IptablesBaseTest.cpp
index ef4d743..dc70ae7 100644
--- a/server/IptablesBaseTest.cpp
+++ b/server/IptablesBaseTest.cpp
@@ -105,7 +105,7 @@
}
void IptablesBaseTest::expectIptablesRestoreCommands(const ExpectedIptablesCommands& expectedCmds) {
- EXPECT_EQ(expectedCmds.size(), sRestoreCmds.size());
+ ASSERT_EQ(expectedCmds.size(), sRestoreCmds.size());
for (size_t i = 0; i < expectedCmds.size(); i++) {
EXPECT_EQ(expectedCmds[i], sRestoreCmds[i]) <<
"iptables-restore command " << i << " differs";
diff --git a/server/IptablesBaseTest.h b/server/IptablesBaseTest.h
index abe3f84..bfcc71a 100644
--- a/server/IptablesBaseTest.h
+++ b/server/IptablesBaseTest.h
@@ -18,9 +18,11 @@
#include <deque>
+#include <netdutils/NetNativeTestBase.h>
+
#include "NetdConstants.h"
-class IptablesBaseTest : public ::testing::Test {
+class IptablesBaseTest : public NetNativeTestBase {
public:
IptablesBaseTest();
diff --git a/server/IptablesRestoreController.cpp b/server/IptablesRestoreController.cpp
index f7ba200..dc71830 100644
--- a/server/IptablesRestoreController.cpp
+++ b/server/IptablesRestoreController.cpp
@@ -241,12 +241,12 @@
return;
}
- ALOGE("iptables error:\n");
- ALOGE("------- COMMAND -------\n");
- ALOGE("%s\n", command.c_str());
- ALOGE("------- ERROR -------\n");
+ ALOGE("iptables error:");
+ ALOGE("------- COMMAND -------");
+ ALOGE("%s", command.c_str());
+ ALOGE("------- ERROR -------");
ALOGE("%s", process->errBuf.c_str());
- ALOGE("----------------------\n");
+ ALOGE("----------------------");
process->errBuf.clear();
}
diff --git a/server/IptablesRestoreControllerTest.cpp b/server/IptablesRestoreControllerTest.cpp
index a05c76d..cecdf4d 100644
--- a/server/IptablesRestoreControllerTest.cpp
+++ b/server/IptablesRestoreControllerTest.cpp
@@ -32,6 +32,7 @@
#include <android-base/strings.h>
#include <log/log.h>
#include <netdutils/MockSyscalls.h>
+#include <netdutils/NetNativeTestBase.h>
#include <netdutils/Stopwatch.h>
#include "NetdConstants.h"
@@ -55,7 +56,7 @@
using testing::Return;
using testing::StrictMock;
-class IptablesRestoreControllerTest : public ::testing::Test {
+class IptablesRestoreControllerTest : public NetNativeTestBase {
public:
IptablesRestoreController con;
int mDefaultMaxRetries = con.MAX_RETRIES;
diff --git a/server/NFLogListenerTest.cpp b/server/NFLogListenerTest.cpp
index 88ab2c6..878c988 100644
--- a/server/NFLogListenerTest.cpp
+++ b/server/NFLogListenerTest.cpp
@@ -25,6 +25,7 @@
#include <linux/netfilter/nfnetlink_log.h>
#include <netdutils/MockSyscalls.h>
+#include <netdutils/NetNativeTestBase.h>
#include "NFLogListener.h"
using ::testing::_;
@@ -58,7 +59,7 @@
MOCK_METHOD1(registerSkErrorHandler, void(const SkErrorHandler& handler));
};
-class NFLogListenerTest : public testing::Test {
+class NFLogListenerTest : public NetNativeTestBase {
protected:
NFLogListenerTest() {
EXPECT_CALL(*mNLListener, subscribe(kNFLogPacketMsgType, _))
diff --git a/server/NetdConstants.cpp b/server/NetdConstants.cpp
index 6de164f..fa21f44 100644
--- a/server/NetdConstants.cpp
+++ b/server/NetdConstants.cpp
@@ -155,8 +155,7 @@
sigemptyset(&mask);
sigaddset(&mask, SIGPIPE);
- if (sigprocmask(SIG_BLOCK, &mask, nullptr) != 0)
- ALOGW("WARNING: SIGPIPE not blocked\n");
+ if (sigprocmask(SIG_BLOCK, &mask, nullptr) != 0) ALOGW("WARNING: SIGPIPE not blocked");
}
void setCloseOnExec(const char *sock) {
diff --git a/server/NetdHwAidlService.cpp b/server/NetdHwAidlService.cpp
new file mode 100644
index 0000000..4258153
--- /dev/null
+++ b/server/NetdHwAidlService.cpp
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "NetdHwAidlService.h"
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include "Controllers.h"
+#include "Fwmark.h"
+#include "RouteController.h"
+#include "TetherController.h"
+
+// Tells TetherController::enableForwarding who is requesting forwarding, so that TetherController
+// can manage/refcount requests to enable forwarding by multiple parties such as the framework, this
+// binder interface, and the legacy "ndc ipfwd enable <requester>" commands.
+namespace {
+constexpr const char* FORWARDING_REQUESTER = "NetdHwAidlService";
+}
+
+namespace android {
+namespace net {
+namespace aidl {
+
+static int toHalStatus(int ret) {
+ switch (ret) {
+ case 0:
+ return 0;
+ case -EINVAL:
+ return NetdHwAidlService::STATUS_INVALID_ARGUMENTS;
+ case -EEXIST:
+ return NetdHwAidlService::STATUS_ALREADY_EXISTS;
+ case -ENONET:
+ return NetdHwAidlService::STATUS_NO_NETWORK;
+ case -EPERM:
+ return NetdHwAidlService::STATUS_PERMISSION_DENIED;
+ default:
+ ALOGE("HAL service error=%d", ret);
+ return NetdHwAidlService::STATUS_UNKNOWN_ERROR;
+ }
+}
+
+void NetdHwAidlService::run() {
+ std::shared_ptr<NetdHwAidlService> service = ndk::SharedRefBase::make<NetdHwAidlService>();
+
+ const std::string instance = std::string() + NetdHwAidlService::descriptor + "/default";
+ binder_status_t status =
+ AServiceManager_addService(service->asBinder().get(), instance.c_str());
+ if (status != STATUS_OK) {
+ ALOGE("Failed to register AIDL INetd service. Status: %d.", status);
+ return;
+ }
+
+ ABinderProcess_joinThreadPool();
+}
+
+ScopedAStatus NetdHwAidlService::createOemNetwork(OemNetwork* network) {
+ unsigned netId;
+ Permission permission = PERMISSION_SYSTEM;
+
+ int ret = gCtls->netCtrl.createPhysicalOemNetwork(permission, &netId);
+
+ Fwmark fwmark;
+ fwmark.netId = netId;
+ fwmark.explicitlySelected = true;
+ fwmark.protectedFromVpn = true;
+ fwmark.permission = PERMISSION_SYSTEM;
+ network->networkHandle = netIdToNetHandle(netId);
+ network->packetMark = fwmark.intValue;
+ if (ret != 0) {
+ return ScopedAStatus::fromServiceSpecificError(toHalStatus(ret));
+ } else {
+ return ScopedAStatus::ok();
+ }
+}
+
+// Vendor code can only modify OEM networks. All other networks are managed by ConnectivityService.
+#define RETURN_IF_NOT_OEM_NETWORK(netId) \
+ if (((netId) < NetworkController::MIN_OEM_ID) || ((netId) > NetworkController::MAX_OEM_ID)) { \
+ return ScopedAStatus::fromServiceSpecificError(STATUS_INVALID_ARGUMENTS); \
+ }
+
+ScopedAStatus NetdHwAidlService::destroyOemNetwork(int64_t netHandle) {
+ unsigned netId = netHandleToNetId(netHandle);
+ RETURN_IF_NOT_OEM_NETWORK(netId);
+
+ auto ret = toHalStatus(gCtls->netCtrl.destroyNetwork(netId));
+ if (ret != 0) {
+ return ScopedAStatus::fromServiceSpecificError(toHalStatus(ret));
+ } else {
+ return ScopedAStatus::ok();
+ }
+}
+
+const char* maybeNullString(const std::string& nexthop) {
+ // std::strings can't be null, but RouteController wants null instead of an empty string.
+ const char* nh = nexthop.c_str();
+ if (nh && !*nh) {
+ nh = nullptr;
+ }
+ return nh;
+}
+
+ScopedAStatus NetdHwAidlService::addRouteToOemNetwork(int64_t networkHandle,
+ const std::string& ifname,
+ const std::string& destination,
+ const std::string& nexthop) {
+ unsigned netId = netHandleToNetId(networkHandle);
+ RETURN_IF_NOT_OEM_NETWORK(netId);
+
+ auto ret = gCtls->netCtrl.addRoute(netId, ifname.c_str(), destination.c_str(),
+ maybeNullString(nexthop), false, INVALID_UID, 0 /* mtu */);
+ if (ret != 0) {
+ return ScopedAStatus::fromServiceSpecificError(toHalStatus(ret));
+ } else {
+ return ScopedAStatus::ok();
+ }
+}
+
+ScopedAStatus NetdHwAidlService::removeRouteFromOemNetwork(int64_t networkHandle,
+ const std::string& ifname,
+ const std::string& destination,
+ const std::string& nexthop) {
+ unsigned netId = netHandleToNetId(networkHandle);
+ RETURN_IF_NOT_OEM_NETWORK(netId);
+
+ auto ret = gCtls->netCtrl.removeRoute(netId, ifname.c_str(), destination.c_str(),
+ maybeNullString(nexthop), false, INVALID_UID);
+ if (ret != 0) {
+ return ScopedAStatus::fromServiceSpecificError(toHalStatus(ret));
+ } else {
+ return ScopedAStatus::ok();
+ }
+}
+
+ScopedAStatus NetdHwAidlService::addInterfaceToOemNetwork(int64_t networkHandle,
+ const std::string& ifname) {
+ unsigned netId = netHandleToNetId(networkHandle);
+ RETURN_IF_NOT_OEM_NETWORK(netId);
+
+ auto ret = gCtls->netCtrl.addInterfaceToNetwork(netId, ifname.c_str());
+ if (ret != 0) {
+ return ScopedAStatus::fromServiceSpecificError(toHalStatus(ret));
+ } else {
+ return ScopedAStatus::ok();
+ }
+}
+
+ScopedAStatus NetdHwAidlService::removeInterfaceFromOemNetwork(int64_t networkHandle,
+ const std::string& ifname) {
+ unsigned netId = netHandleToNetId(networkHandle);
+ RETURN_IF_NOT_OEM_NETWORK(netId);
+
+ auto ret = gCtls->netCtrl.removeInterfaceFromNetwork(netId, ifname.c_str());
+ if (ret != 0) {
+ return ScopedAStatus::fromServiceSpecificError(toHalStatus(ret));
+ } else {
+ return ScopedAStatus::ok();
+ }
+}
+
+ScopedAStatus NetdHwAidlService::setIpForwardEnable(bool enable) {
+ std::lock_guard _lock(gCtls->tetherCtrl.lock);
+
+ bool success = enable ? gCtls->tetherCtrl.enableForwarding(FORWARDING_REQUESTER)
+ : gCtls->tetherCtrl.disableForwarding(FORWARDING_REQUESTER);
+
+ if (!success) {
+ return ScopedAStatus::fromServiceSpecificError(STATUS_UNKNOWN_ERROR);
+ } else {
+ return ScopedAStatus::ok();
+ }
+}
+
+ScopedAStatus NetdHwAidlService::setForwardingBetweenInterfaces(const std::string& inputIfName,
+ const std::string& outputIfName,
+ bool enable) {
+ std::lock_guard _lock(gCtls->tetherCtrl.lock);
+
+ // TODO: check that one interface is an OEM interface and the other is another OEM interface, an
+ // IPsec interface or a dummy interface.
+ int ret = enable ? RouteController::enableTethering(inputIfName.c_str(), outputIfName.c_str())
+ : RouteController::disableTethering(inputIfName.c_str(), outputIfName.c_str());
+ if (ret != 0) {
+ return ScopedAStatus::fromServiceSpecificError(toHalStatus(ret));
+ } else {
+ return ScopedAStatus::ok();
+ }
+}
+
+} // namespace aidl
+} // namespace net
+} // namespace android
diff --git a/server/NetdHwAidlService.h b/server/NetdHwAidlService.h
new file mode 100644
index 0000000..5cc5b6f
--- /dev/null
+++ b/server/NetdHwAidlService.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <aidl/android/system/net/netd/BnNetd.h>
+
+namespace android {
+namespace net {
+namespace aidl {
+using NetdHw = ::aidl::android::system::net::netd::BnNetd;
+using OemNetwork = ::aidl::android::system::net::netd::INetd::OemNetwork;
+using ScopedAStatus = ::ndk::ScopedAStatus;
+
+class NetdHwAidlService : public NetdHw {
+ public:
+ // Start and run the AIDL service.
+ // This blocks when joining the threadpool so start this in a separate thread.
+ static void run();
+ ScopedAStatus createOemNetwork(OemNetwork* network) override;
+ ScopedAStatus destroyOemNetwork(int64_t netHandle) override;
+ ScopedAStatus addRouteToOemNetwork(int64_t networkHandle, const std::string& ifname,
+ const std::string& destination,
+ const std::string& nexthop) override;
+ ScopedAStatus removeRouteFromOemNetwork(int64_t networkHandle, const std::string& ifname,
+ const std::string& destination,
+ const std::string& nexthop) override;
+ ScopedAStatus addInterfaceToOemNetwork(int64_t networkHandle,
+ const std::string& ifname) override;
+ ScopedAStatus removeInterfaceFromOemNetwork(int64_t networkHandle,
+ const std::string& ifname) override;
+ ScopedAStatus setIpForwardEnable(bool enable) override;
+ ScopedAStatus setForwardingBetweenInterfaces(const std::string& inputIfName,
+ const std::string& outputIfName,
+ bool enable) override;
+};
+
+} // namespace aidl
+} // namespace net
+} // namespace android
diff --git a/server/NetdHwService.cpp b/server/NetdHwService.cpp
index 15855da..d4a0e58 100644
--- a/server/NetdHwService.cpp
+++ b/server/NetdHwService.cpp
@@ -14,15 +14,13 @@
* limitations under the License.
*/
+#include "NetdHwService.h"
#include <binder/IPCThreadState.h>
-#include <hidl/HidlTransportSupport.h>
#include "Controllers.h"
#include "Fwmark.h"
-#include "NetdHwService.h"
#include "RouteController.h"
#include "TetherController.h"
-using android::hardware::configureRpcThreadpool;
using android::hardware::Void;
// Tells TetherController::enableForwarding who is requesting forwarding, so that TetherController
@@ -55,9 +53,6 @@
// Minimal service start.
status_t NetdHwService::start() {
- IPCThreadState::self()->disableBackgroundScheduling(true);
- // Usage of this HAL is anticipated to be thin; one thread should suffice.
- configureRpcThreadpool(1, false /* callerWillNotJoin */);
// Register hardware service with ServiceManager.
return INetd::registerAsService();
}
diff --git a/server/NetlinkHandler.cpp b/server/NetlinkHandler.cpp
index a4e05b0..9e63a8c 100644
--- a/server/NetlinkHandler.cpp
+++ b/server/NetlinkHandler.cpp
@@ -106,7 +106,7 @@
if (!strcmp(subsys, "net")) {
NetlinkEvent::Action action = evt->getAction();
- const char *iface = evt->findParam("INTERFACE");
+ const char *iface = evt->findParam("INTERFACE") ?: "";
if (action == NetlinkEvent::Action::kAdd) {
notifyInterfaceAdded(iface);
} else if (action == NetlinkEvent::Action::kRemove) {
diff --git a/server/Network.cpp b/server/Network.cpp
index 85f942f..156cfb3 100644
--- a/server/Network.cpp
+++ b/server/Network.cpp
@@ -117,18 +117,12 @@
}
}
-bool Network::canAddUidRanges(const UidRanges& uidRanges, int32_t subPriority) const {
+bool Network::canAddUidRanges(const UidRanges& uidRanges) const {
if (uidRanges.overlapsSelf()) {
ALOGE("uid range %s overlaps self", uidRanges.toString().c_str());
return false;
}
- auto iter = mUidRangeMap.find(subPriority);
- if (iter != mUidRangeMap.end() && uidRanges.overlaps(iter->second)) {
- ALOGE("uid range %s overlaps priority %d %s", uidRanges.toString().c_str(), subPriority,
- iter->second.toString().c_str());
- return false;
- }
return true;
}
diff --git a/server/Network.h b/server/Network.h
index e18e1cd..dfead17 100644
--- a/server/Network.h
+++ b/server/Network.h
@@ -65,7 +65,7 @@
protected:
explicit Network(unsigned netId, bool secure = false);
- bool canAddUidRanges(const UidRanges& uidRanges, int32_t subPriority) const;
+ bool canAddUidRanges(const UidRanges& uidRanges) const;
const unsigned mNetId;
std::set<std::string> mInterfaces;
diff --git a/server/PhysicalNetwork.cpp b/server/PhysicalNetwork.cpp
index bb3f653..6813064 100644
--- a/server/PhysicalNetwork.cpp
+++ b/server/PhysicalNetwork.cpp
@@ -165,7 +165,7 @@
}
int PhysicalNetwork::addUsers(const UidRanges& uidRanges, int32_t subPriority) {
- if (!isValidSubPriority(subPriority) || !canAddUidRanges(uidRanges, subPriority)) {
+ if (!isValidSubPriority(subPriority) || !canAddUidRanges(uidRanges)) {
return -EINVAL;
}
diff --git a/server/Process.cpp b/server/Process.cpp
index f43e82d..fa14587 100644
--- a/server/Process.cpp
+++ b/server/Process.cpp
@@ -85,7 +85,7 @@
sigemptyset(&mask);
sigaddset(&mask, SIGPIPE);
if (sigprocmask(SIG_BLOCK, &mask, nullptr) != 0) {
- ALOGW("WARNING: SIGPIPE not blocked\n");
+ ALOGW("WARNING: SIGPIPE not blocked");
}
}
diff --git a/server/RouteController.cpp b/server/RouteController.cpp
index d2af9a3..dca6bd9 100644
--- a/server/RouteController.cpp
+++ b/server/RouteController.cpp
@@ -64,7 +64,7 @@
const char* const RouteController::LOCAL_MANGLE_INPUT = "routectrl_mangle_INPUT";
-const IPPrefix V4_LOCAL_ADDR[] = {
+const IPPrefix V4_LOCAL_PREFIXES[] = {
IPPrefix::forString("169.254.0.0/16"), // Link Local
IPPrefix::forString("100.64.0.0/10"), // CGNAT
IPPrefix::forString("10.0.0.0/8"), // RFC1918
@@ -1392,8 +1392,8 @@
return modifyDefaultNetwork(RTM_DELRULE, interface, permission);
}
-bool RouteController::isTargetV4LocalRange(const char* dst) {
- for (IPPrefix addr : V4_LOCAL_ADDR) {
+bool RouteController::isWithinIpv4LocalPrefix(const char* dst) {
+ for (IPPrefix addr : V4_LOCAL_PREFIXES) {
if (addr.contains(IPPrefix::forString(dst))) {
return true;
}
@@ -1401,14 +1401,14 @@
return false;
}
-bool RouteController::isLocalAddress(TableType tableType, const char* destination,
- const char* nexthop) {
+bool RouteController::isLocalRoute(TableType tableType, const char* destination,
+ const char* nexthop) {
IPPrefix prefix = IPPrefix::forString(destination);
return nexthop == nullptr && tableType == RouteController::INTERFACE &&
// Skip default route to prevent network being modeled as point-to-point interfaces.
((prefix.family() == AF_INET6 && prefix != IPPrefix::forString("::/0")) ||
// Skip adding non-target local network range.
- (prefix.family() == AF_INET && isTargetV4LocalRange(destination)));
+ (prefix.family() == AF_INET && isWithinIpv4LocalPrefix(destination)));
}
int RouteController::addRoute(const char* interface, const char* destination, const char* nexthop,
@@ -1418,7 +1418,7 @@
return ret;
}
- if (isLocalAddress(tableType, destination, nexthop)) {
+ if (isLocalRoute(tableType, destination, nexthop)) {
return modifyRoute(RTM_NEWROUTE, NETLINK_ROUTE_CREATE_FLAGS, interface, destination,
nexthop, tableType, mtu, priority, true /* isLocal */);
}
@@ -1433,7 +1433,7 @@
return ret;
}
- if (isLocalAddress(tableType, destination, nexthop)) {
+ if (isLocalRoute(tableType, destination, nexthop)) {
return modifyRoute(RTM_DELROUTE, NETLINK_REQUEST_FLAGS, interface, destination, nexthop,
tableType, 0 /* mtu */, priority, true /* isLocal */);
}
@@ -1447,7 +1447,7 @@
return ret;
}
- if (isLocalAddress(tableType, destination, nexthop)) {
+ if (isLocalRoute(tableType, destination, nexthop)) {
return modifyRoute(RTM_NEWROUTE, NETLINK_ROUTE_REPLACE_FLAGS, interface, destination,
nexthop, tableType, mtu, 0 /* priority */, true /* isLocal */);
}
diff --git a/server/RouteController.h b/server/RouteController.h
index ff41678..f57bc24 100644
--- a/server/RouteController.h
+++ b/server/RouteController.h
@@ -230,8 +230,8 @@
static int modifyUidLocalNetworkRule(const char* interface, uid_t uidStart, uid_t uidEnd,
bool add);
- static bool isLocalAddress(TableType tableType, const char* destination, const char* nexthop);
- static bool isTargetV4LocalRange(const char* addrstr);
+ static bool isLocalRoute(TableType tableType, const char* destination, const char* nexthop);
+ static bool isWithinIpv4LocalPrefix(const char* addrstr);
};
// Public because they are called by by RouteControllerTest.cpp.
diff --git a/server/SockDiagTest.cpp b/server/SockDiagTest.cpp
index 49601aa..864d08d 100644
--- a/server/SockDiagTest.cpp
+++ b/server/SockDiagTest.cpp
@@ -24,6 +24,7 @@
#include <linux/inet_diag.h>
#include <gtest/gtest.h>
+#include <netdutils/NetNativeTestBase.h>
#include "Fwmark.h"
#include "NetdConstants.h"
@@ -33,7 +34,7 @@
namespace android {
namespace net {
-class SockDiagTest : public ::testing::Test {
+class SockDiagTest : public NetNativeTestBase {
protected:
static bool isLoopbackSocket(const inet_diag_msg *msg) {
return SockDiag::isLoopbackSocket(msg);
diff --git a/server/UidRanges.cpp b/server/UidRanges.cpp
index c90f30b..765df32 100644
--- a/server/UidRanges.cpp
+++ b/server/UidRanges.cpp
@@ -145,25 +145,6 @@
return false;
}
-// std::binary_search cannot do partial match. For example, an uid range x-y not only overlaps with
-// x-y, but also w-x, y-z, w-z, ...etc. Therefore, we need a specialized binary search.
-bool UidRanges::overlaps(const UidRanges& other) const {
- for (const auto& target : other.getRanges()) {
- int first = 0;
- int end = mRanges.size() - 1;
-
- while (first <= end) {
- int middle = (first + end) / 2;
- if (isOverlapped(mRanges[middle], target)) return true;
- if (compUidRangeParcel(mRanges[middle], target))
- first = middle + 1;
- else
- end = middle - 1;
- }
- }
- return false;
-}
-
std::string UidRanges::toString() const {
std::string s("uids{ ");
for (const auto &range : mRanges) {
diff --git a/server/UidRanges.h b/server/UidRanges.h
index 9123eb1..f20dc44 100644
--- a/server/UidRanges.h
+++ b/server/UidRanges.h
@@ -51,12 +51,10 @@
// check if 'mRanges' has uid overlap between elements.
bool overlapsSelf() const;
- // check if this object has uid overlap with the input object.
- bool overlaps(const UidRanges& other) const;
+
bool empty() const { return mRanges.empty(); }
private:
- // Keep it sorted. The overlaps() implements binary search, which requires a sorted data.
std::vector<UidRangeParcel> mRanges;
};
diff --git a/server/UnreachableNetwork.cpp b/server/UnreachableNetwork.cpp
index 6880225..dd6318c 100644
--- a/server/UnreachableNetwork.cpp
+++ b/server/UnreachableNetwork.cpp
@@ -27,7 +27,7 @@
UnreachableNetwork::UnreachableNetwork(unsigned netId) : Network(netId) {}
int UnreachableNetwork::addUsers(const UidRanges& uidRanges, int32_t subPriority) {
- if (!isValidSubPriority(subPriority) || !canAddUidRanges(uidRanges, subPriority)) {
+ if (!isValidSubPriority(subPriority) || !canAddUidRanges(uidRanges)) {
return -EINVAL;
}
diff --git a/server/VirtualNetwork.cpp b/server/VirtualNetwork.cpp
index 495fd16..e0f6040 100644
--- a/server/VirtualNetwork.cpp
+++ b/server/VirtualNetwork.cpp
@@ -33,7 +33,7 @@
VirtualNetwork::~VirtualNetwork() {}
int VirtualNetwork::addUsers(const UidRanges& uidRanges, int32_t subPriority) {
- if (!isValidSubPriority(subPriority) || !canAddUidRanges(uidRanges, subPriority)) {
+ if (!isValidSubPriority(subPriority) || !canAddUidRanges(uidRanges)) {
return -EINVAL;
}
diff --git a/server/XfrmControllerTest.cpp b/server/XfrmControllerTest.cpp
index e7f5cfc..f1c3807 100644
--- a/server/XfrmControllerTest.cpp
+++ b/server/XfrmControllerTest.cpp
@@ -41,6 +41,7 @@
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <gtest/gtest.h>
+#include <netdutils/NetNativeTestBase.h>
#include "Fwmark.h"
#include "NetdConstants.h"
@@ -127,7 +128,7 @@
EXPECT_EQ(expected, actualStr);
}
-class XfrmControllerTest : public ::testing::Test {
+class XfrmControllerTest : public NetNativeTestBase {
public:
testing::StrictMock<netdutils::ScopedMockSyscalls> mockSyscalls;
};
diff --git a/server/android.system.net.netd-service.xml b/server/android.system.net.netd-service.xml
new file mode 100644
index 0000000..7152da1
--- /dev/null
+++ b/server/android.system.net.netd-service.xml
@@ -0,0 +1,7 @@
+<manifest version="1.0" type="framework">
+ <hal format="aidl">
+ <name>android.system.net.netd</name>
+ <version>1</version>
+ <fqname>INetd/default</fqname>
+ </hal>
+</manifest>
diff --git a/server/main.cpp b/server/main.cpp
index 0e81d4e..35c53de 100644
--- a/server/main.cpp
+++ b/server/main.cpp
@@ -32,8 +32,11 @@
#include "log/log.h"
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
+#include <hidl/HidlTransportSupport.h>
#include <netdutils/Stopwatch.h>
#include <processgroup/processgroup.h>
@@ -43,6 +46,7 @@
#include "MDnsService.h"
#include "NFLogListener.h"
#include "NetdConstants.h"
+#include "NetdHwAidlService.h"
#include "NetdHwService.h"
#include "NetdNativeService.h"
#include "NetlinkManager.h"
@@ -64,6 +68,7 @@
using android::net::NetdNativeService;
using android::net::NetlinkManager;
using android::net::NFLogListener;
+using android::net::aidl::NetdHwAidlService;
using android::netdutils::Stopwatch;
const char* const PID_FILE_PATH = "/data/misc/net/netd_pid";
@@ -162,8 +167,8 @@
}
logListener = std::move(result.value());
auto status = gCtls->wakeupCtrl.init(logListener.get());
- if (!isOk(result)) {
- gLog.error("Unable to init WakeupController: %s", toString(result).c_str());
+ if (!isOk(status)) {
+ gLog.error("Unable to init WakeupController: %s", toString(status).c_str());
// We can still continue without wakeup packet logging.
}
}
@@ -202,16 +207,26 @@
android::net::process::ScopedPidFile pidFile(PID_FILE_PATH);
// Now that netd is ready to process commands, advertise service availability for HAL clients.
+ // Usage of this HAL is anticipated to be thin; one thread per HAL service should suffice,
+ // AIDL and HIDL.
+ android::hardware::configureRpcThreadpool(2, true /* callerWillJoin */);
+ IPCThreadState::self()->disableBackgroundScheduling(true);
+
+ std::thread aidlService = std::thread(NetdHwAidlService::run);
+
sp<NetdHwService> mHwSvc(new NetdHwService());
+ bool startedHidlService = true;
if ((ret = mHwSvc->start()) != android::OK) {
- ALOGE("Unable to start NetdHwService: %d", ret);
- exit(1);
+ ALOGE("Unable to start HIDL NetdHwService: %d", ret);
+ startedHidlService = false;
}
+
gLog.info("Registering NetdHwService: %" PRId64 "us", subTime.getTimeAndResetUs());
gLog.info("Netd started in %" PRId64 "us", s.timeTakenUs());
-
- IPCThreadState::self()->joinThreadPool();
-
+ if (startedHidlService) {
+ IPCThreadState::self()->joinThreadPool();
+ }
+ aidlService.join();
gLog.info("netd exiting");
exit(0);
diff --git a/tests/Android.bp b/tests/Android.bp
index ff918cc..3b27300 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -75,6 +75,7 @@
"device-tests",
"vts"
],
+ isolated: false,
require_root: true,
defaults: [
"netd_aidl_interface_lateststable_cpp_static",
diff --git a/tests/benchmarks/bpf_benchmark.cpp b/tests/benchmarks/bpf_benchmark.cpp
index bf4bd54..4de8066 100644
--- a/tests/benchmarks/bpf_benchmark.cpp
+++ b/tests/benchmarks/bpf_benchmark.cpp
@@ -18,6 +18,7 @@
#include <android-base/stringprintf.h>
#include <benchmark/benchmark.h>
+#define BPF_MAP_MAKE_VISIBLE_FOR_TESTING
#include "bpf/BpfMap.h"
#include "bpf/BpfUtils.h"
diff --git a/tests/benchmarks/dns_benchmark.cpp b/tests/benchmarks/dns_benchmark.cpp
index b8f626e..060e40a 100644
--- a/tests/benchmarks/dns_benchmark.cpp
+++ b/tests/benchmarks/dns_benchmark.cpp
@@ -65,11 +65,12 @@
std::vector<std::string> domains = { "example.com" };
std::vector<std::string> servers;
dns.SetupMappings(num_hosts, domains, &mappings);
-
dns.SetupDNSServers(MAXNS, mappings, &mDns, &servers);
-
- const std::vector<int> mDefaultParams_Binder = {300, 25, 8, 8, 1000};
- dns.SetResolversForNetwork(servers, domains, mDefaultParams_Binder);
+ dns.SetResolversFromParcel(ResolverParams::Builder()
+ .setDnsServers(servers)
+ .setDotServers({})
+ .setDomains(domains)
+ .build());
}
}
diff --git a/tests/binder_test.cpp b/tests/binder_test.cpp
index dae1af3..52608f9 100644
--- a/tests/binder_test.cpp
+++ b/tests/binder_test.cpp
@@ -58,6 +58,7 @@
#include <com/android/internal/net/IOemNetd.h>
#include <cutils/multiuser.h>
#include <gtest/gtest.h>
+#include <netdutils/NetNativeTestBase.h>
#include <netutils/ifc.h>
#include <utils/Errors.h>
#include "Fwmark.h"
@@ -176,7 +177,7 @@
{// 2001:db8:cafe::8888
.u6_addr8 = {0x20, 0x01, 0x0d, 0xb8, 0xca, 0xfe, 0, 0, 0, 0, 0, 0, 0, 0, 0x88, 0x88}}};
-class NetdBinderTest : public ::testing::Test {
+class NetdBinderTest : public NetNativeTestBase {
public:
NetdBinderTest() {
sp<IServiceManager> sm = android::defaultServiceManager();
@@ -645,7 +646,7 @@
int32_t subPriority) {
NativeUidRangeConfig res;
res.netId = netId;
- res.uidRanges = move(uidRanges);
+ res.uidRanges = std::move(uidRanges);
res.subPriority = subPriority;
return res;
@@ -1241,7 +1242,7 @@
for (const auto& path : { IPTABLES_PATH, IP6TABLES_PATH }) {
delTetherCounterValues(path, intIface1, extIface1);
delTetherCounterValues(path, intIface2, extIface2);
- if (path == IP6TABLES_PATH) {
+ if (strcmp(path, IP6TABLES_PATH) == 0) {
delTetherCounterValues(path, intIface3, extIface2);
}
}
@@ -3910,7 +3911,7 @@
void verifyAppUidRules(std::vector<bool>&& expectedResults, NativeUidRangeConfig& uidRangeConfig,
const std::string& iface) {
- verifyAppUidRules(move(expectedResults), uidRangeConfig.uidRanges, iface,
+ verifyAppUidRules(std::move(expectedResults), uidRangeConfig.uidRanges, iface,
uidRangeConfig.subPriority);
}
@@ -3999,7 +4000,7 @@
} // namespace
-// Verify whether API reject overlapped UID ranges
+// Verify how the API handle overlapped UID ranges
TEST_F(NetdBinderTest, PerAppDefaultNetwork_OverlappedUidRanges) {
const auto& config = makeNativeNetworkConfig(APP_DEFAULT_NETID, NativeNetworkType::PHYSICAL,
INetd::PERMISSION_NONE, false, false);
@@ -4013,28 +4014,23 @@
binder::Status status;
status = mNetd->networkAddUidRanges(APP_DEFAULT_NETID,
{makeUidRangeParcel(BASE_UID + 1, BASE_UID + 1)});
- EXPECT_FALSE(status.isOk());
- EXPECT_EQ(EINVAL, status.serviceSpecificErrorCode());
+ EXPECT_TRUE(status.isOk());
status = mNetd->networkAddUidRanges(APP_DEFAULT_NETID,
{makeUidRangeParcel(BASE_UID + 9, BASE_UID + 10)});
- EXPECT_FALSE(status.isOk());
- EXPECT_EQ(EINVAL, status.serviceSpecificErrorCode());
+ EXPECT_TRUE(status.isOk());
status = mNetd->networkAddUidRanges(APP_DEFAULT_NETID,
{makeUidRangeParcel(BASE_UID + 11, BASE_UID + 11)});
- EXPECT_FALSE(status.isOk());
- EXPECT_EQ(EINVAL, status.serviceSpecificErrorCode());
+ EXPECT_TRUE(status.isOk());
status = mNetd->networkAddUidRanges(APP_DEFAULT_NETID,
{makeUidRangeParcel(BASE_UID + 12, BASE_UID + 13)});
- EXPECT_FALSE(status.isOk());
- EXPECT_EQ(EINVAL, status.serviceSpecificErrorCode());
+ EXPECT_TRUE(status.isOk());
status = mNetd->networkAddUidRanges(APP_DEFAULT_NETID,
{makeUidRangeParcel(BASE_UID + 9, BASE_UID + 13)});
- EXPECT_FALSE(status.isOk());
- EXPECT_EQ(EINVAL, status.serviceSpecificErrorCode());
+ EXPECT_TRUE(status.isOk());
std::vector<UidRangeParcel> selfOverlappedUidRanges = {
makeUidRangeParcel(BASE_UID + 20, BASE_UID + 20),
@@ -4730,11 +4726,6 @@
uidRangeConfig.subPriority = SUB_PRIORITY_2;
EXPECT_TRUE(mNetd->networkAddUidRangesParcel(uidRangeConfig).isOk());
- // For a single network, identical UID ranges with the same priority is invalid.
- status = mNetd->networkAddUidRangesParcel(uidRangeConfig);
- EXPECT_FALSE(status.isOk());
- EXPECT_EQ(EINVAL, status.serviceSpecificErrorCode());
-
// Overlapping ranges is invalid.
uidRangeConfig.uidRanges = {makeUidRangeParcel(BASE_UID + 1, BASE_UID + 1),
makeUidRangeParcel(BASE_UID + 1, BASE_UID + 1)};
@@ -5112,8 +5103,39 @@
}
}
-class MDnsBinderTest : public ::testing::Test {
+class MDnsBinderTest : public NetNativeTestBase {
public:
+ class TestMDnsListener : public android::net::mdns::aidl::BnMDnsEventListener {
+ public:
+ Status onServiceRegistrationStatus(const RegistrationInfo& /*status*/) override {
+ // no-op
+ return Status::ok();
+ }
+ Status onServiceDiscoveryStatus(const DiscoveryInfo& /*status*/) override {
+ // no-op
+ return Status::ok();
+ }
+ Status onServiceResolutionStatus(const ResolutionInfo& /*status*/) override {
+ // no-op
+ return Status::ok();
+ }
+ Status onGettingServiceAddressStatus(const GetAddressInfo& status) override {
+ if (status.id == mOperationId) {
+ std::lock_guard lock(mCvMutex);
+ mCv.notify_one();
+ }
+ return Status::ok();
+ }
+ std::condition_variable& getCv() { return mCv; }
+ std::mutex& getCvMutex() { return mCvMutex; }
+ void setOperationId(int operationId) { mOperationId = operationId; }
+
+ private:
+ std::mutex mCvMutex;
+ std::condition_variable mCv;
+ int mOperationId;
+ };
+
MDnsBinderTest() {
sp<IServiceManager> sm = android::defaultServiceManager();
sp<IBinder> binder = sm->getService(String16("mdns"));
@@ -5122,31 +5144,45 @@
}
}
- void SetUp() override { ASSERT_NE(nullptr, mMDns.get()); }
+ void SetUp() override {
+ ASSERT_NE(nullptr, mMDns.get());
+ // Start the daemon for mdns operations.
+ mDaemonStarted = mMDns->startDaemon().isOk();
+ }
- void TearDown() override {}
+ void TearDown() override {
+ if (mDaemonStarted) mMDns->stopDaemon();
+ }
+
+ std::cv_status getServiceAddress(int operationId, const sp<TestMDnsListener>& listener);
protected:
sp<IMDns> mMDns;
+
+ private:
+ bool mDaemonStarted = false;
};
-class TestMDnsListener : public android::net::mdns::aidl::BnMDnsEventListener {
- public:
- Status onServiceRegistrationStatus(const RegistrationInfo& /* status */) override {
- return Status::ok();
- }
- Status onServiceDiscoveryStatus(const DiscoveryInfo& /* status */) override {
- return Status::ok();
- }
- Status onServiceResolutionStatus(const ResolutionInfo& /* status */) override {
- return Status::ok();
- }
- Status onGettingServiceAddressStatus(const GetAddressInfo& /* status */) override {
- return Status::ok();
- }
-};
+std::cv_status MDnsBinderTest::getServiceAddress(int operationId,
+ const sp<TestMDnsListener>& listener) {
+ GetAddressInfo info;
+ info.id = operationId;
+ info.hostname = "Android.local";
+ info.interfaceIdx = 0;
+ binder::Status status = mMDns->getServiceAddress(info);
+ EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
+
+ auto& cv = listener->getCv();
+ auto& cvMutex = listener->getCvMutex();
+ std::unique_lock lock(cvMutex);
+ // Wait for a long time to prevent test flaky.
+ return cv.wait_for(lock, std::chrono::milliseconds(2500));
+}
TEST_F(MDnsBinderTest, EventListenerTest) {
+ // Start the Binder thread pool.
+ android::ProcessState::self()->startThreadPool();
+
// Register a null listener.
binder::Status status = mMDns->registerEventListener(nullptr);
EXPECT_FALSE(status.isOk());
@@ -5155,8 +5191,8 @@
status = mMDns->unregisterEventListener(nullptr);
EXPECT_FALSE(status.isOk());
- // Register the test listener.
- android::sp<TestMDnsListener> testListener = new TestMDnsListener();
+ // Register a test listener
+ auto testListener = android::sp<TestMDnsListener>::make();
status = mMDns->registerEventListener(testListener);
EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
@@ -5164,7 +5200,28 @@
status = mMDns->registerEventListener(testListener);
EXPECT_FALSE(status.isOk());
+ // Verify the listener can receive callback.
+ int id = arc4random_uniform(10000); // use random number
+ testListener->setOperationId(id);
+ EXPECT_EQ(std::cv_status::no_timeout, getServiceAddress(id, testListener));
+ // Stop getting address operation to release the service reference on MDnsSd
+ status = mMDns->stopOperation(id);
+ EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
+
// Unregister the test listener
status = mMDns->unregisterEventListener(testListener);
EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
+
+ // Verify the listener can not receive callback.
+ testListener->setOperationId(id + 1);
+ EXPECT_EQ(std::cv_status::timeout, getServiceAddress(id + 1, testListener));
+ // Stop getting address operation to release the service reference on MDnsSd
+ status = mMDns->stopOperation(id + 1);
+ EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
+
+ // Registering and unregistering the listener again should work.
+ status = mMDns->registerEventListener(testListener);
+ EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
+ status = mMDns->unregisterEventListener(testListener);
+ EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
}
diff --git a/tests/bpf_base_test.cpp b/tests/bpf_base_test.cpp
index e402e08..8a21506 100644
--- a/tests/bpf_base_test.cpp
+++ b/tests/bpf_base_test.cpp
@@ -33,6 +33,7 @@
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
+#include <netdutils/NetNativeTestBase.h>
#include "bpf/BpfMap.h"
#include "bpf/BpfUtils.h"
@@ -48,7 +49,7 @@
constexpr uid_t TEST_UID = UID_MAX - 1;
constexpr uint32_t TEST_TAG = 42;
-class BpfBasicTest : public testing::Test {
+class BpfBasicTest : public NetNativeTestBase {
protected:
BpfBasicTest() {}
};
@@ -84,7 +85,7 @@
TEST_F(BpfBasicTest, TestTagSocket) {
BpfMap<uint64_t, UidTagValue> cookieTagMap(COOKIE_TAG_MAP_PATH);
- ASSERT_LE(0, cookieTagMap.getMap());
+ ASSERT_TRUE(cookieTagMap.isValid());
int sock = socket(AF_INET6, SOCK_STREAM | SOCK_CLOEXEC, 0);
ASSERT_LE(0, sock);
uint64_t cookie = getSocketCookie(sock);
@@ -102,7 +103,7 @@
TEST_F(BpfBasicTest, TestCloseSocketWithoutUntag) {
BpfMap<uint64_t, UidTagValue> cookieTagMap(COOKIE_TAG_MAP_PATH);
- ASSERT_LE(0, cookieTagMap.getMap());
+ ASSERT_TRUE(cookieTagMap.isValid());
int sock = socket(AF_INET6, SOCK_STREAM | SOCK_CLOEXEC, 0);
ASSERT_LE(0, sock);
uint64_t cookie = getSocketCookie(sock);
diff --git a/tests/netd_test.cpp b/tests/netd_test.cpp
index 8d5d8bc..169fa2b 100644
--- a/tests/netd_test.cpp
+++ b/tests/netd_test.cpp
@@ -29,6 +29,7 @@
#include <gtest/gtest.h>
+#include <android-base/stringprintf.h>
#include <android-base/unique_fd.h>
#define LOG_TAG "NetdTest"
@@ -70,6 +71,44 @@
"'^u:object_r:sysfs_net:s0 /sys/class/net/'"));
}
+static void assertBpfContext(const char* const target, const char* const label) {
+ // Use 'ls' cli utility to print the selinux context of the target directory or file.
+ // egrep -q will return 0 if it matches, ie. if the selinux context is as expected
+ std::string cmd = android::base::StringPrintf("ls -dZ %s | egrep -q '^u:object_r:%s:s0 %s$'",
+ target, label, target);
+
+ // NOLINTNEXTLINE(cert-env33-c)
+ ASSERT_EQ(W_EXITCODE(0, 0), system(cmd.c_str())) << cmd << " - did not return success(0)";
+}
+
+// This test will fail if kernel is missing:
+// https://android-review.googlesource.com/c/kernel/common/+/1831252
+// UPSTREAM: security: selinux: allow per-file labeling for bpffs
+TEST(NetdSELinuxTest, CheckProperBpfLabels) {
+ assertBpfContext("/sys/fs/bpf", "fs_bpf");
+ assertBpfContext("/sys/fs/bpf/net_private", "fs_bpf_net_private");
+ assertBpfContext("/sys/fs/bpf/net_shared", "fs_bpf_net_shared");
+ assertBpfContext("/sys/fs/bpf/netd_readonly", "fs_bpf_netd_readonly");
+ assertBpfContext("/sys/fs/bpf/netd_shared", "fs_bpf_netd_shared");
+ assertBpfContext("/sys/fs/bpf/vendor", "fs_bpf_vendor");
+}
+
+bool isTetheringInProcess() {
+ int v = access("/apex/com.android.tethering/etc/flag/in-process", F_OK);
+ if (!v) return true;
+ EXPECT_EQ(v, -1) << "expected return of found(0) or notfound(-1/ENOENT)";
+ EXPECT_EQ(errno, ENOENT) << "expected return of found(0) or notfound(-1/ENOENT)";
+ return false;
+}
+
+TEST(NetdSELinuxTest, CheckProperBpfTetheringLabels) {
+ if (isTetheringInProcess()) {
+ assertBpfContext("/sys/fs/bpf/net_shared/tethering", "fs_bpf_net_shared");
+ } else {
+ assertBpfContext("/sys/fs/bpf/tethering", "fs_bpf_tethering");
+ }
+}
+
// Trivial thread function that simply immediately terminates successfully.
static int thread(void*) {
return 0;
diff --git a/tests/sock_diag_test.cpp b/tests/sock_diag_test.cpp
index 8ee9908..5d142dc 100644
--- a/tests/sock_diag_test.cpp
+++ b/tests/sock_diag_test.cpp
@@ -21,6 +21,7 @@
#include <linux/inet_diag.h>
#include <gtest/gtest.h>
+#include <netdutils/NetNativeTestBase.h>
#include "NetdConstants.h"
#include "SockDiag.h"
@@ -29,7 +30,7 @@
#define NUM_SOCKETS 500
-class SockDiagTest : public ::testing::Test {
+class SockDiagTest : public NetNativeTestBase {
};
uint16_t bindAndListen(int s) {