Make the socketDestroy tests use a fake tun interface.
On real devices, we often don't want to destroy sockets that
are on loopback. This CL makes our integration tests use
sockets that don't look like they're on loopback, making it
possible to test code that does not destroy sockets that are
on loopback.
Bug: 30186506
(cherry picked from commit 549a0f705849d0a1dcf9de38cbe54edad4a83cd9)
Change-Id: Ic4b8a7cb684010576f0c9c40a037906c7ba4d93d
diff --git a/tests/binder_test.cpp b/tests/binder_test.cpp
index 42d01a5..0fe6d5f 100644
--- a/tests/binder_test.cpp
+++ b/tests/binder_test.cpp
@@ -24,20 +24,28 @@
#include <set>
#include <vector>
+#include <fcntl.h>
+#include <netdb.h>
#include <sys/socket.h>
+#include <sys/types.h>
#include <netinet/in.h>
+#include <linux/if.h>
+#include <linux/if_tun.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <cutils/multiuser.h>
#include <gtest/gtest.h>
#include <logwrap/logwrap.h>
+#include <netutils/ifc.h>
#include "NetdConstants.h"
#include "android/net/INetd.h"
#include "android/net/UidRange.h"
#include "binder/IServiceManager.h"
+#define TUN_DEV "/dev/tun"
+
using namespace android;
using namespace android::base;
using namespace android::binder;
@@ -58,14 +66,36 @@
}
}
- void SetUp() {
+ void SetUp() override {
ASSERT_NE(nullptr, mNetd.get());
}
+ // Static because setting up the tun interface takes about 40ms.
+ static void SetUpTestCase() {
+ sTunFd = createTunInterface();
+ ASSERT_NE(-1, sTunFd);
+ }
+
+ static void TearDownTestCase() {
+ // Closing the socket removes the interface and IP addresses.
+ close(sTunFd);
+ }
+
+ static void fakeRemoteSocketPair(int *clientSocket, int *serverSocket, int *acceptedSocket);
+ static int createTunInterface();
+
protected:
sp<INetd> mNetd;
+ static int sTunFd;
+ static in6_addr sSrcAddr, sDstAddr;
+ static char sSrcStr[], sDstStr[];
};
+int BinderTest::sTunFd;
+in6_addr BinderTest::sSrcAddr;
+in6_addr BinderTest::sDstAddr;
+char BinderTest::sSrcStr[INET6_ADDRSTRLEN];
+char BinderTest::sDstStr[INET6_ADDRSTRLEN];
class TimedOperation : public Stopwatch {
public:
@@ -296,9 +326,51 @@
EXPECT_EQ(initialRulesV6, listIpRules(IP_RULE_V6));
}
-void socketpair(int *clientSocket, int *serverSocket, int *acceptedSocket) {
+int BinderTest::createTunInterface() {
+ // Generate a random ULA address pair.
+ arc4random_buf(&sSrcAddr, sizeof(sSrcAddr));
+ sSrcAddr.s6_addr[0] = 0xfd;
+ memcpy(&sDstAddr, &sSrcAddr, sizeof(sDstAddr));
+ sDstAddr.s6_addr[15] ^= 1;
+
+ // Convert the addresses to strings because that's what ifc_add_address takes.
+ sockaddr_in6 src6 = { .sin6_family = AF_INET6, .sin6_addr = sSrcAddr, };
+ sockaddr_in6 dst6 = { .sin6_family = AF_INET6, .sin6_addr = sDstAddr, };
+ int flags = NI_NUMERICHOST;
+ if (getnameinfo((sockaddr *) &src6, sizeof(src6), sSrcStr, sizeof(sSrcStr), NULL, 0, flags) ||
+ getnameinfo((sockaddr *) &dst6, sizeof(dst6), sDstStr, sizeof(sDstStr), NULL, 0, flags)) {
+ return -1;
+ }
+
+ // Create a tun interface with a name based on our PID.
+ struct ifreq ifr = {
+ .ifr_ifru = { .ifru_flags = IFF_TUN },
+ };
+ snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "netdtest%u", getpid());
+
+ int fd = open(TUN_DEV, O_RDWR | O_NONBLOCK | O_CLOEXEC);
+ EXPECT_NE(-1, fd) << TUN_DEV << ": " << strerror(errno);
+ if (fd == -1) return fd;
+
+ int ret = ioctl(fd, TUNSETIFF, &ifr, sizeof(ifr));
+ EXPECT_EQ(0, ret) << "TUNSETIFF: " << strerror(errno);
+ if (ret) {
+ close(fd);
+ return -1;
+ }
+
+ if (ifc_add_address(ifr.ifr_name, sSrcStr, 64) ||
+ ifc_add_address(ifr.ifr_name, sDstStr, 64)) {
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+// Create a socket pair that isLoopbackSocket won't think is local.
+void BinderTest::fakeRemoteSocketPair(int *clientSocket, int *serverSocket, int *acceptedSocket) {
*serverSocket = socket(AF_INET6, SOCK_STREAM, 0);
- struct sockaddr_in6 server6 = { .sin6_family = AF_INET6 };
+ struct sockaddr_in6 server6 = { .sin6_family = AF_INET6, .sin6_addr = sDstAddr };
ASSERT_EQ(0, bind(*serverSocket, (struct sockaddr *) &server6, sizeof(server6)));
socklen_t addrlen = sizeof(server6);
@@ -306,7 +378,8 @@
ASSERT_EQ(0, listen(*serverSocket, 10));
*clientSocket = socket(AF_INET6, SOCK_STREAM, 0);
- struct sockaddr_in6 client6;
+ struct sockaddr_in6 client6 = { .sin6_family = AF_INET6, .sin6_addr = sSrcAddr };
+ ASSERT_EQ(0, bind(*clientSocket, (struct sockaddr *) &client6, sizeof(client6)));
ASSERT_EQ(0, connect(*clientSocket, (struct sockaddr *) &server6, sizeof(server6)));
ASSERT_EQ(0, getsockname(*clientSocket, (struct sockaddr *) &client6, &addrlen));
@@ -339,7 +412,7 @@
TEST_F(BinderTest, TestSocketDestroy) {
int clientSocket, serverSocket, acceptedSocket;
- ASSERT_NO_FATAL_FAILURE(socketpair(&clientSocket, &serverSocket, &acceptedSocket));
+ ASSERT_NO_FATAL_FAILURE(fakeRemoteSocketPair(&clientSocket, &serverSocket, &acceptedSocket));
// Pick a random UID in the system UID range.
constexpr int baseUid = AID_APP - 2000;