1*8542734aSAndroid Build Coastguard Worker /*
2*8542734aSAndroid Build Coastguard Worker * Copyright 2017 The Android Open Source Project
3*8542734aSAndroid Build Coastguard Worker *
4*8542734aSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*8542734aSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*8542734aSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*8542734aSAndroid Build Coastguard Worker *
8*8542734aSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*8542734aSAndroid Build Coastguard Worker *
10*8542734aSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*8542734aSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*8542734aSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8542734aSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*8542734aSAndroid Build Coastguard Worker * limitations under the License.
15*8542734aSAndroid Build Coastguard Worker */
16*8542734aSAndroid Build Coastguard Worker
17*8542734aSAndroid Build Coastguard Worker #define LOG_TAG "IptablesRestoreControllerTest"
18*8542734aSAndroid Build Coastguard Worker #include "IptablesRestoreController.h"
19*8542734aSAndroid Build Coastguard Worker
20*8542734aSAndroid Build Coastguard Worker #include <fcntl.h>
21*8542734aSAndroid Build Coastguard Worker #include <gmock/gmock.h>
22*8542734aSAndroid Build Coastguard Worker #include <gtest/gtest.h>
23*8542734aSAndroid Build Coastguard Worker #include <sys/file.h>
24*8542734aSAndroid Build Coastguard Worker #include <sys/socket.h>
25*8542734aSAndroid Build Coastguard Worker #include <sys/un.h>
26*8542734aSAndroid Build Coastguard Worker
27*8542734aSAndroid Build Coastguard Worker #include <cinttypes>
28*8542734aSAndroid Build Coastguard Worker #include <iostream>
29*8542734aSAndroid Build Coastguard Worker #include <string>
30*8542734aSAndroid Build Coastguard Worker
31*8542734aSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
32*8542734aSAndroid Build Coastguard Worker #include <android-base/strings.h>
33*8542734aSAndroid Build Coastguard Worker #include <log/log.h>
34*8542734aSAndroid Build Coastguard Worker #include <netdutils/MockSyscalls.h>
35*8542734aSAndroid Build Coastguard Worker #include <netdutils/NetNativeTestBase.h>
36*8542734aSAndroid Build Coastguard Worker #include <netdutils/Stopwatch.h>
37*8542734aSAndroid Build Coastguard Worker
38*8542734aSAndroid Build Coastguard Worker #include "NetdConstants.h"
39*8542734aSAndroid Build Coastguard Worker
40*8542734aSAndroid Build Coastguard Worker #define XT_LOCK_NAME "/system/etc/xtables.lock"
41*8542734aSAndroid Build Coastguard Worker #define XT_LOCK_ATTEMPTS 10
42*8542734aSAndroid Build Coastguard Worker #define XT_LOCK_POLL_INTERVAL_MS 100
43*8542734aSAndroid Build Coastguard Worker
44*8542734aSAndroid Build Coastguard Worker #define PROC_STAT_MIN_ELEMENTS 52U
45*8542734aSAndroid Build Coastguard Worker #define PROC_STAT_RSS_INDEX 23U
46*8542734aSAndroid Build Coastguard Worker
47*8542734aSAndroid Build Coastguard Worker #define IPTABLES_COMM "(iptables-restor)"
48*8542734aSAndroid Build Coastguard Worker #define IP6TABLES_COMM "(ip6tables-resto)"
49*8542734aSAndroid Build Coastguard Worker
50*8542734aSAndroid Build Coastguard Worker using android::base::Join;
51*8542734aSAndroid Build Coastguard Worker using android::base::StringAppendF;
52*8542734aSAndroid Build Coastguard Worker using android::base::StringPrintf;
53*8542734aSAndroid Build Coastguard Worker using android::netdutils::ScopedMockSyscalls;
54*8542734aSAndroid Build Coastguard Worker using android::netdutils::Stopwatch;
55*8542734aSAndroid Build Coastguard Worker using testing::Return;
56*8542734aSAndroid Build Coastguard Worker using testing::StrictMock;
57*8542734aSAndroid Build Coastguard Worker
58*8542734aSAndroid Build Coastguard Worker class IptablesRestoreControllerTest : public NetNativeTestBase {
59*8542734aSAndroid Build Coastguard Worker public:
60*8542734aSAndroid Build Coastguard Worker IptablesRestoreController con;
61*8542734aSAndroid Build Coastguard Worker int mDefaultMaxRetries = con.MAX_RETRIES;
62*8542734aSAndroid Build Coastguard Worker int mDefaultPollTimeoutMs = con.POLL_TIMEOUT_MS;
63*8542734aSAndroid Build Coastguard Worker int mIptablesLock = -1;
64*8542734aSAndroid Build Coastguard Worker std::string mChainName;
65*8542734aSAndroid Build Coastguard Worker
SetUpTestSuite()66*8542734aSAndroid Build Coastguard Worker static void SetUpTestSuite() { blockSigpipe(); }
67*8542734aSAndroid Build Coastguard Worker
SetUp()68*8542734aSAndroid Build Coastguard Worker void SetUp() {
69*8542734aSAndroid Build Coastguard Worker ASSERT_EQ(0, createTestChain());
70*8542734aSAndroid Build Coastguard Worker }
71*8542734aSAndroid Build Coastguard Worker
TearDown()72*8542734aSAndroid Build Coastguard Worker void TearDown() {
73*8542734aSAndroid Build Coastguard Worker con.MAX_RETRIES = mDefaultMaxRetries;
74*8542734aSAndroid Build Coastguard Worker con.POLL_TIMEOUT_MS = mDefaultPollTimeoutMs;
75*8542734aSAndroid Build Coastguard Worker deleteTestChain();
76*8542734aSAndroid Build Coastguard Worker }
77*8542734aSAndroid Build Coastguard Worker
Init()78*8542734aSAndroid Build Coastguard Worker void Init() {
79*8542734aSAndroid Build Coastguard Worker con.Init();
80*8542734aSAndroid Build Coastguard Worker }
81*8542734aSAndroid Build Coastguard Worker
getIpRestorePid(const IptablesRestoreController::IptablesProcessType type)82*8542734aSAndroid Build Coastguard Worker pid_t getIpRestorePid(const IptablesRestoreController::IptablesProcessType type) {
83*8542734aSAndroid Build Coastguard Worker return con.getIpRestorePid(type);
84*8542734aSAndroid Build Coastguard Worker };
85*8542734aSAndroid Build Coastguard Worker
getProcStatPath(pid_t pid)86*8542734aSAndroid Build Coastguard Worker const std::string getProcStatPath(pid_t pid) { return StringPrintf("/proc/%d/stat", pid); }
87*8542734aSAndroid Build Coastguard Worker
parseProcStat(int fd,const std::string & path)88*8542734aSAndroid Build Coastguard Worker std::vector<std::string> parseProcStat(int fd, const std::string& path) {
89*8542734aSAndroid Build Coastguard Worker std::vector<std::string> procStat;
90*8542734aSAndroid Build Coastguard Worker
91*8542734aSAndroid Build Coastguard Worker char statBuf[1024];
92*8542734aSAndroid Build Coastguard Worker EXPECT_NE(-1, read(fd, statBuf, sizeof(statBuf)))
93*8542734aSAndroid Build Coastguard Worker << "Could not read from " << path << ": " << strerror(errno);
94*8542734aSAndroid Build Coastguard Worker
95*8542734aSAndroid Build Coastguard Worker std::stringstream stream(statBuf);
96*8542734aSAndroid Build Coastguard Worker std::string item;
97*8542734aSAndroid Build Coastguard Worker while (std::getline(stream, item, ' ')) {
98*8542734aSAndroid Build Coastguard Worker procStat.push_back(item);
99*8542734aSAndroid Build Coastguard Worker }
100*8542734aSAndroid Build Coastguard Worker
101*8542734aSAndroid Build Coastguard Worker EXPECT_LE(PROC_STAT_MIN_ELEMENTS, procStat.size()) << "Too few elements in " << path;
102*8542734aSAndroid Build Coastguard Worker return procStat;
103*8542734aSAndroid Build Coastguard Worker }
104*8542734aSAndroid Build Coastguard Worker
expectNoIptablesRestoreProcess(pid_t pid)105*8542734aSAndroid Build Coastguard Worker void expectNoIptablesRestoreProcess(pid_t pid) {
106*8542734aSAndroid Build Coastguard Worker // We can't readlink /proc/PID/exe, because zombie processes don't have it.
107*8542734aSAndroid Build Coastguard Worker // Parse /proc/PID/stat instead.
108*8542734aSAndroid Build Coastguard Worker std::string statPath = getProcStatPath(pid);
109*8542734aSAndroid Build Coastguard Worker int fd = open(statPath.c_str(), O_RDONLY | O_CLOEXEC);
110*8542734aSAndroid Build Coastguard Worker if (fd == -1) {
111*8542734aSAndroid Build Coastguard Worker // ENOENT means the process is gone (expected).
112*8542734aSAndroid Build Coastguard Worker ASSERT_EQ(errno, ENOENT)
113*8542734aSAndroid Build Coastguard Worker << "Unexpected error opening " << statPath << ": " << strerror(errno);
114*8542734aSAndroid Build Coastguard Worker return;
115*8542734aSAndroid Build Coastguard Worker }
116*8542734aSAndroid Build Coastguard Worker
117*8542734aSAndroid Build Coastguard Worker // If the PID exists, it's possible (though very unlikely) that the PID was reused. Check the
118*8542734aSAndroid Build Coastguard Worker // binary name as well, to ensure the test isn't flaky.
119*8542734aSAndroid Build Coastguard Worker std::vector<std::string> procStat = parseProcStat(fd, statPath);
120*8542734aSAndroid Build Coastguard Worker EXPECT_FALSE(procStat[1] == IPTABLES_COMM || procStat[1] == IP6TABLES_COMM)
121*8542734aSAndroid Build Coastguard Worker << "Previous iptables-restore or ip6tables-restore pid " << pid
122*8542734aSAndroid Build Coastguard Worker << " still alive: " << Join(procStat, " ");
123*8542734aSAndroid Build Coastguard Worker
124*8542734aSAndroid Build Coastguard Worker close(fd);
125*8542734aSAndroid Build Coastguard Worker }
126*8542734aSAndroid Build Coastguard Worker
getRssPages(pid_t pid)127*8542734aSAndroid Build Coastguard Worker int getRssPages(pid_t pid) {
128*8542734aSAndroid Build Coastguard Worker std::string statPath = getProcStatPath(pid);
129*8542734aSAndroid Build Coastguard Worker int fd = open(statPath.c_str(), O_RDONLY | O_CLOEXEC);
130*8542734aSAndroid Build Coastguard Worker EXPECT_NE(-1, fd) << "Unexpected error opening " << statPath << ": " << strerror(errno);
131*8542734aSAndroid Build Coastguard Worker if (fd == -1) return 0;
132*8542734aSAndroid Build Coastguard Worker
133*8542734aSAndroid Build Coastguard Worker const auto& procStat = parseProcStat(fd, statPath);
134*8542734aSAndroid Build Coastguard Worker close(fd);
135*8542734aSAndroid Build Coastguard Worker
136*8542734aSAndroid Build Coastguard Worker if (procStat.size() < PROC_STAT_MIN_ELEMENTS) return 0;
137*8542734aSAndroid Build Coastguard Worker EXPECT_TRUE(procStat[1] == IPTABLES_COMM || procStat[1] == IP6TABLES_COMM)
138*8542734aSAndroid Build Coastguard Worker << statPath << " is for unexpected process: " << procStat[1];
139*8542734aSAndroid Build Coastguard Worker
140*8542734aSAndroid Build Coastguard Worker return std::atoi(procStat[PROC_STAT_RSS_INDEX].c_str());
141*8542734aSAndroid Build Coastguard Worker }
142*8542734aSAndroid Build Coastguard Worker
createTestChain()143*8542734aSAndroid Build Coastguard Worker int createTestChain() {
144*8542734aSAndroid Build Coastguard Worker mChainName = StringPrintf("netd_unit_test_%u", arc4random_uniform(10000)).c_str();
145*8542734aSAndroid Build Coastguard Worker
146*8542734aSAndroid Build Coastguard Worker // Create a chain to list.
147*8542734aSAndroid Build Coastguard Worker std::vector<std::string> createCommands = {
148*8542734aSAndroid Build Coastguard Worker "*filter",
149*8542734aSAndroid Build Coastguard Worker StringPrintf(":%s -", mChainName.c_str()),
150*8542734aSAndroid Build Coastguard Worker StringPrintf("-A %s -j RETURN", mChainName.c_str()),
151*8542734aSAndroid Build Coastguard Worker "COMMIT",
152*8542734aSAndroid Build Coastguard Worker ""
153*8542734aSAndroid Build Coastguard Worker };
154*8542734aSAndroid Build Coastguard Worker
155*8542734aSAndroid Build Coastguard Worker int ret = con.execute(V4V6, Join(createCommands, "\n"), nullptr);
156*8542734aSAndroid Build Coastguard Worker if (ret) mChainName = "";
157*8542734aSAndroid Build Coastguard Worker return ret;
158*8542734aSAndroid Build Coastguard Worker }
159*8542734aSAndroid Build Coastguard Worker
deleteTestChain()160*8542734aSAndroid Build Coastguard Worker void deleteTestChain() {
161*8542734aSAndroid Build Coastguard Worker std::vector<std::string> deleteCommands = {
162*8542734aSAndroid Build Coastguard Worker "*filter",
163*8542734aSAndroid Build Coastguard Worker StringPrintf(":%s -", mChainName.c_str()), // Flush chain (otherwise we can't delete it).
164*8542734aSAndroid Build Coastguard Worker StringPrintf("-X %s", mChainName.c_str()), // Delete it.
165*8542734aSAndroid Build Coastguard Worker "COMMIT",
166*8542734aSAndroid Build Coastguard Worker ""
167*8542734aSAndroid Build Coastguard Worker };
168*8542734aSAndroid Build Coastguard Worker con.execute(V4V6, Join(deleteCommands, "\n"), nullptr);
169*8542734aSAndroid Build Coastguard Worker mChainName = "";
170*8542734aSAndroid Build Coastguard Worker }
171*8542734aSAndroid Build Coastguard Worker
acquireIptablesLock()172*8542734aSAndroid Build Coastguard Worker int acquireIptablesLock() {
173*8542734aSAndroid Build Coastguard Worker mIptablesLock = open(XT_LOCK_NAME, O_CREAT | O_CLOEXEC, 0600);
174*8542734aSAndroid Build Coastguard Worker if (mIptablesLock == -1) return mIptablesLock;
175*8542734aSAndroid Build Coastguard Worker int attempts;
176*8542734aSAndroid Build Coastguard Worker for (attempts = 0; attempts < XT_LOCK_ATTEMPTS; attempts++) {
177*8542734aSAndroid Build Coastguard Worker if (flock(mIptablesLock, LOCK_EX | LOCK_NB) == 0) {
178*8542734aSAndroid Build Coastguard Worker return 0;
179*8542734aSAndroid Build Coastguard Worker }
180*8542734aSAndroid Build Coastguard Worker usleep(XT_LOCK_POLL_INTERVAL_MS * 1000);
181*8542734aSAndroid Build Coastguard Worker }
182*8542734aSAndroid Build Coastguard Worker EXPECT_LT(attempts, XT_LOCK_ATTEMPTS) <<
183*8542734aSAndroid Build Coastguard Worker "Could not acquire iptables lock after " << XT_LOCK_ATTEMPTS << " attempts " <<
184*8542734aSAndroid Build Coastguard Worker XT_LOCK_POLL_INTERVAL_MS << "ms apart";
185*8542734aSAndroid Build Coastguard Worker return -1;
186*8542734aSAndroid Build Coastguard Worker }
187*8542734aSAndroid Build Coastguard Worker
releaseIptablesLock()188*8542734aSAndroid Build Coastguard Worker void releaseIptablesLock() {
189*8542734aSAndroid Build Coastguard Worker if (mIptablesLock != -1) {
190*8542734aSAndroid Build Coastguard Worker close(mIptablesLock);
191*8542734aSAndroid Build Coastguard Worker }
192*8542734aSAndroid Build Coastguard Worker }
193*8542734aSAndroid Build Coastguard Worker
setRetryParameters(int maxRetries,int pollTimeoutMs)194*8542734aSAndroid Build Coastguard Worker void setRetryParameters(int maxRetries, int pollTimeoutMs) {
195*8542734aSAndroid Build Coastguard Worker con.MAX_RETRIES = maxRetries;
196*8542734aSAndroid Build Coastguard Worker con.POLL_TIMEOUT_MS = pollTimeoutMs;
197*8542734aSAndroid Build Coastguard Worker }
198*8542734aSAndroid Build Coastguard Worker };
199*8542734aSAndroid Build Coastguard Worker
TEST_F(IptablesRestoreControllerTest,TestBasicCommand)200*8542734aSAndroid Build Coastguard Worker TEST_F(IptablesRestoreControllerTest, TestBasicCommand) {
201*8542734aSAndroid Build Coastguard Worker std::string output;
202*8542734aSAndroid Build Coastguard Worker
203*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(0, con.execute(IptablesTarget::V4V6, "#Test\n", nullptr));
204*8542734aSAndroid Build Coastguard Worker
205*8542734aSAndroid Build Coastguard Worker pid_t pid4 = getIpRestorePid(IptablesRestoreController::IPTABLES_PROCESS);
206*8542734aSAndroid Build Coastguard Worker pid_t pid6 = getIpRestorePid(IptablesRestoreController::IP6TABLES_PROCESS);
207*8542734aSAndroid Build Coastguard Worker
208*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(0, con.execute(IptablesTarget::V6, "#Test\n", nullptr));
209*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(0, con.execute(IptablesTarget::V4, "#Test\n", nullptr));
210*8542734aSAndroid Build Coastguard Worker
211*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(0, con.execute(IptablesTarget::V4V6, "#Test\n", &output));
212*8542734aSAndroid Build Coastguard Worker EXPECT_EQ("#Test\n#Test\n", output); // One for IPv4 and one for IPv6.
213*8542734aSAndroid Build Coastguard Worker
214*8542734aSAndroid Build Coastguard Worker // Check the PIDs are the same as they were before. If they're not, the child processes were
215*8542734aSAndroid Build Coastguard Worker // restarted, which causes a 30-60ms delay.
216*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(pid4, getIpRestorePid(IptablesRestoreController::IPTABLES_PROCESS));
217*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(pid6, getIpRestorePid(IptablesRestoreController::IP6TABLES_PROCESS));
218*8542734aSAndroid Build Coastguard Worker }
219*8542734aSAndroid Build Coastguard Worker
TEST_F(IptablesRestoreControllerTest,TestRestartOnMalformedCommand)220*8542734aSAndroid Build Coastguard Worker TEST_F(IptablesRestoreControllerTest, TestRestartOnMalformedCommand) {
221*8542734aSAndroid Build Coastguard Worker std::string buffer;
222*8542734aSAndroid Build Coastguard Worker for (int i = 0; i < 50; i++) {
223*8542734aSAndroid Build Coastguard Worker IptablesTarget target = (IptablesTarget) (i % 3);
224*8542734aSAndroid Build Coastguard Worker std::string *output = (i % 2) ? &buffer : nullptr;
225*8542734aSAndroid Build Coastguard Worker ASSERT_EQ(-1, con.execute(target, "malformed command\n", output)) <<
226*8542734aSAndroid Build Coastguard Worker "Malformed command did not fail at iteration " << i;
227*8542734aSAndroid Build Coastguard Worker ASSERT_EQ(0, con.execute(target, "#Test\n", output)) <<
228*8542734aSAndroid Build Coastguard Worker "No-op command did not succeed at iteration " << i;
229*8542734aSAndroid Build Coastguard Worker }
230*8542734aSAndroid Build Coastguard Worker }
231*8542734aSAndroid Build Coastguard Worker
TEST_F(IptablesRestoreControllerTest,TestRestartOnProcessDeath)232*8542734aSAndroid Build Coastguard Worker TEST_F(IptablesRestoreControllerTest, TestRestartOnProcessDeath) {
233*8542734aSAndroid Build Coastguard Worker std::string output;
234*8542734aSAndroid Build Coastguard Worker
235*8542734aSAndroid Build Coastguard Worker // Run a command to ensure that the processes are running.
236*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(0, con.execute(IptablesTarget::V4V6, "#Test\n", &output));
237*8542734aSAndroid Build Coastguard Worker
238*8542734aSAndroid Build Coastguard Worker pid_t pid4 = getIpRestorePid(IptablesRestoreController::IPTABLES_PROCESS);
239*8542734aSAndroid Build Coastguard Worker pid_t pid6 = getIpRestorePid(IptablesRestoreController::IP6TABLES_PROCESS);
240*8542734aSAndroid Build Coastguard Worker
241*8542734aSAndroid Build Coastguard Worker ASSERT_EQ(0, kill(pid4, 0)) << "iptables-restore pid " << pid4 << " does not exist";
242*8542734aSAndroid Build Coastguard Worker ASSERT_EQ(0, kill(pid6, 0)) << "ip6tables-restore pid " << pid6 << " does not exist";
243*8542734aSAndroid Build Coastguard Worker ASSERT_EQ(0, kill(pid4, SIGTERM)) << "Failed to send SIGTERM to iptables-restore pid " << pid4;
244*8542734aSAndroid Build Coastguard Worker ASSERT_EQ(0, kill(pid6, SIGTERM)) << "Failed to send SIGTERM to ip6tables-restore pid " << pid6;
245*8542734aSAndroid Build Coastguard Worker
246*8542734aSAndroid Build Coastguard Worker // Wait 100ms for processes to terminate.
247*8542734aSAndroid Build Coastguard Worker TEMP_FAILURE_RETRY(usleep(100 * 1000));
248*8542734aSAndroid Build Coastguard Worker
249*8542734aSAndroid Build Coastguard Worker // Ensure that running a new command properly restarts the processes.
250*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(0, con.execute(IptablesTarget::V4V6, "#Test\n", nullptr));
251*8542734aSAndroid Build Coastguard Worker EXPECT_NE(pid4, getIpRestorePid(IptablesRestoreController::IPTABLES_PROCESS));
252*8542734aSAndroid Build Coastguard Worker EXPECT_NE(pid6, getIpRestorePid(IptablesRestoreController::IP6TABLES_PROCESS));
253*8542734aSAndroid Build Coastguard Worker
254*8542734aSAndroid Build Coastguard Worker // Check there are no zombies.
255*8542734aSAndroid Build Coastguard Worker expectNoIptablesRestoreProcess(pid4);
256*8542734aSAndroid Build Coastguard Worker expectNoIptablesRestoreProcess(pid6);
257*8542734aSAndroid Build Coastguard Worker }
258*8542734aSAndroid Build Coastguard Worker
TEST_F(IptablesRestoreControllerTest,TestCommandTimeout)259*8542734aSAndroid Build Coastguard Worker TEST_F(IptablesRestoreControllerTest, TestCommandTimeout) {
260*8542734aSAndroid Build Coastguard Worker // Don't wait 10 seconds for this test to fail.
261*8542734aSAndroid Build Coastguard Worker setRetryParameters(3, 100);
262*8542734aSAndroid Build Coastguard Worker
263*8542734aSAndroid Build Coastguard Worker // Expected contents of the chain.
264*8542734aSAndroid Build Coastguard Worker std::vector<std::string> expectedLines = {
265*8542734aSAndroid Build Coastguard Worker StringPrintf("Chain %s (0 references)", mChainName.c_str()),
266*8542734aSAndroid Build Coastguard Worker "target prot opt source destination ",
267*8542734aSAndroid Build Coastguard Worker "RETURN all -- 0.0.0.0/0 0.0.0.0/0 ",
268*8542734aSAndroid Build Coastguard Worker StringPrintf("Chain %s (0 references)", mChainName.c_str()),
269*8542734aSAndroid Build Coastguard Worker "target prot opt source destination ",
270*8542734aSAndroid Build Coastguard Worker "RETURN all -- ::/0 ::/0 ",
271*8542734aSAndroid Build Coastguard Worker ""
272*8542734aSAndroid Build Coastguard Worker };
273*8542734aSAndroid Build Coastguard Worker std::string expected = Join(expectedLines, "\n");
274*8542734aSAndroid Build Coastguard Worker
275*8542734aSAndroid Build Coastguard Worker std::vector<std::string> listCommands = {
276*8542734aSAndroid Build Coastguard Worker "*filter",
277*8542734aSAndroid Build Coastguard Worker StringPrintf("-n -L %s", mChainName.c_str()), // List chain.
278*8542734aSAndroid Build Coastguard Worker "COMMIT",
279*8542734aSAndroid Build Coastguard Worker ""
280*8542734aSAndroid Build Coastguard Worker };
281*8542734aSAndroid Build Coastguard Worker std::string commandString = Join(listCommands, "\n");
282*8542734aSAndroid Build Coastguard Worker std::string output;
283*8542734aSAndroid Build Coastguard Worker
284*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(0, con.execute(IptablesTarget::V4V6, commandString, &output));
285*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(expected, output);
286*8542734aSAndroid Build Coastguard Worker
287*8542734aSAndroid Build Coastguard Worker ASSERT_EQ(0, acquireIptablesLock());
288*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(-1, con.execute(IptablesTarget::V4V6, commandString, &output));
289*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(-1, con.execute(IptablesTarget::V4V6, commandString, &output));
290*8542734aSAndroid Build Coastguard Worker releaseIptablesLock();
291*8542734aSAndroid Build Coastguard Worker
292*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(0, con.execute(IptablesTarget::V4V6, commandString, &output));
293*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(expected, output);
294*8542734aSAndroid Build Coastguard Worker }
295*8542734aSAndroid Build Coastguard Worker
296*8542734aSAndroid Build Coastguard Worker
TEST_F(IptablesRestoreControllerTest,TestUidRuleBenchmark)297*8542734aSAndroid Build Coastguard Worker TEST_F(IptablesRestoreControllerTest, TestUidRuleBenchmark) {
298*8542734aSAndroid Build Coastguard Worker const std::vector<int> ITERATIONS = { 1, 5, 10 };
299*8542734aSAndroid Build Coastguard Worker
300*8542734aSAndroid Build Coastguard Worker const std::string IPTABLES_RESTORE_ADD =
301*8542734aSAndroid Build Coastguard Worker StringPrintf("*filter\n-I %s -m owner --uid-owner 2000000000 -j RETURN\nCOMMIT\n",
302*8542734aSAndroid Build Coastguard Worker mChainName.c_str());
303*8542734aSAndroid Build Coastguard Worker const std::string IPTABLES_RESTORE_DEL =
304*8542734aSAndroid Build Coastguard Worker StringPrintf("*filter\n-D %s -m owner --uid-owner 2000000000 -j RETURN\nCOMMIT\n",
305*8542734aSAndroid Build Coastguard Worker mChainName.c_str());
306*8542734aSAndroid Build Coastguard Worker
307*8542734aSAndroid Build Coastguard Worker for (const int iterations : ITERATIONS) {
308*8542734aSAndroid Build Coastguard Worker Stopwatch s;
309*8542734aSAndroid Build Coastguard Worker for (int i = 0; i < iterations; i++) {
310*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(0, con.execute(V4V6, IPTABLES_RESTORE_ADD, nullptr));
311*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(0, con.execute(V4V6, IPTABLES_RESTORE_DEL, nullptr));
312*8542734aSAndroid Build Coastguard Worker }
313*8542734aSAndroid Build Coastguard Worker int64_t timeTaken = s.getTimeAndResetUs();
314*8542734aSAndroid Build Coastguard Worker std::cerr << " Add/del " << iterations << " UID rules via restore: " << timeTaken
315*8542734aSAndroid Build Coastguard Worker << "us (" << (timeTaken / 2 / iterations) << "us per operation)" << std::endl;
316*8542734aSAndroid Build Coastguard Worker }
317*8542734aSAndroid Build Coastguard Worker }
318*8542734aSAndroid Build Coastguard Worker
TEST_F(IptablesRestoreControllerTest,TestStartup)319*8542734aSAndroid Build Coastguard Worker TEST_F(IptablesRestoreControllerTest, TestStartup) {
320*8542734aSAndroid Build Coastguard Worker // Tests that IptablesRestoreController::Init never sets its processes to null pointers if
321*8542734aSAndroid Build Coastguard Worker // fork() succeeds.
322*8542734aSAndroid Build Coastguard Worker {
323*8542734aSAndroid Build Coastguard Worker // Mock fork(), and check that initializing 100 times never results in a null pointer.
324*8542734aSAndroid Build Coastguard Worker constexpr int NUM_ITERATIONS = 100; // Takes 100-150ms on angler.
325*8542734aSAndroid Build Coastguard Worker constexpr pid_t FAKE_PID = 2000000001;
326*8542734aSAndroid Build Coastguard Worker StrictMock<ScopedMockSyscalls> sys;
327*8542734aSAndroid Build Coastguard Worker
328*8542734aSAndroid Build Coastguard Worker EXPECT_CALL(sys, fork()).Times(NUM_ITERATIONS * 2).WillRepeatedly(Return(FAKE_PID));
329*8542734aSAndroid Build Coastguard Worker for (int i = 0; i < NUM_ITERATIONS; i++) {
330*8542734aSAndroid Build Coastguard Worker Init();
331*8542734aSAndroid Build Coastguard Worker EXPECT_NE(0, getIpRestorePid(IptablesRestoreController::IPTABLES_PROCESS));
332*8542734aSAndroid Build Coastguard Worker EXPECT_NE(0, getIpRestorePid(IptablesRestoreController::IP6TABLES_PROCESS));
333*8542734aSAndroid Build Coastguard Worker }
334*8542734aSAndroid Build Coastguard Worker }
335*8542734aSAndroid Build Coastguard Worker
336*8542734aSAndroid Build Coastguard Worker // The controller is now in an invalid state: the pipes are connected to working iptables
337*8542734aSAndroid Build Coastguard Worker // processes, but the PIDs are set to FAKE_PID. Send a malformed command to ensure that the
338*8542734aSAndroid Build Coastguard Worker // processes terminate and close the pipes, then send a valid command to have the controller
339*8542734aSAndroid Build Coastguard Worker // re-initialize properly now that fork() is no longer mocked.
340*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(-1, con.execute(V4V6, "malformed command\n", nullptr));
341*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(0, con.execute(V4V6, "#Test\n", nullptr));
342*8542734aSAndroid Build Coastguard Worker }
343*8542734aSAndroid Build Coastguard Worker
344*8542734aSAndroid Build Coastguard Worker // Out of SLO flakiness
TEST_F(IptablesRestoreControllerTest,DISABLED_TestMemoryLeak)345*8542734aSAndroid Build Coastguard Worker TEST_F(IptablesRestoreControllerTest, DISABLED_TestMemoryLeak) {
346*8542734aSAndroid Build Coastguard Worker std::string cmd = "*filter\n";
347*8542734aSAndroid Build Coastguard Worker
348*8542734aSAndroid Build Coastguard Worker // Keep command within PIPE_BUF (4096) just to make sure. Each line is 60 bytes including \n:
349*8542734aSAndroid Build Coastguard Worker // -I netd_unit_test_9999 -p udp -m udp --sport 12345 -j DROP
350*8542734aSAndroid Build Coastguard Worker for (int i = 0; i < 33; i++) {
351*8542734aSAndroid Build Coastguard Worker StringAppendF(&cmd, "-I %s -p udp -m udp --sport 12345 -j DROP\n", mChainName.c_str());
352*8542734aSAndroid Build Coastguard Worker StringAppendF(&cmd, "-D %s -p udp -m udp --sport 12345 -j DROP\n", mChainName.c_str());
353*8542734aSAndroid Build Coastguard Worker }
354*8542734aSAndroid Build Coastguard Worker StringAppendF(&cmd, "COMMIT\n");
355*8542734aSAndroid Build Coastguard Worker ASSERT_GE(4096U, cmd.size());
356*8542734aSAndroid Build Coastguard Worker
357*8542734aSAndroid Build Coastguard Worker // Run the command once in case it causes the first allocations for these iptables-restore
358*8542734aSAndroid Build Coastguard Worker // processes, and check they don't crash.
359*8542734aSAndroid Build Coastguard Worker pid_t pid4 = getIpRestorePid(IptablesRestoreController::IPTABLES_PROCESS);
360*8542734aSAndroid Build Coastguard Worker pid_t pid6 = getIpRestorePid(IptablesRestoreController::IP6TABLES_PROCESS);
361*8542734aSAndroid Build Coastguard Worker std::string output;
362*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(0, con.execute(IptablesTarget::V4V6, cmd, nullptr));
363*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(pid4, getIpRestorePid(IptablesRestoreController::IPTABLES_PROCESS));
364*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(pid6, getIpRestorePid(IptablesRestoreController::IP6TABLES_PROCESS));
365*8542734aSAndroid Build Coastguard Worker
366*8542734aSAndroid Build Coastguard Worker // Check how much RAM the processes are using.
367*8542734aSAndroid Build Coastguard Worker int pages4 = getRssPages(pid4);
368*8542734aSAndroid Build Coastguard Worker ASSERT_NE(0, pages4);
369*8542734aSAndroid Build Coastguard Worker int pages6 = getRssPages(pid6);
370*8542734aSAndroid Build Coastguard Worker ASSERT_NE(0, pages6);
371*8542734aSAndroid Build Coastguard Worker
372*8542734aSAndroid Build Coastguard Worker // Run the command a few times and check that it doesn't crash.
373*8542734aSAndroid Build Coastguard Worker for (int i = 0; i < 10; i++) {
374*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(0, con.execute(IptablesTarget::V4V6, cmd, nullptr));
375*8542734aSAndroid Build Coastguard Worker }
376*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(pid4, getIpRestorePid(IptablesRestoreController::IPTABLES_PROCESS));
377*8542734aSAndroid Build Coastguard Worker EXPECT_EQ(pid6, getIpRestorePid(IptablesRestoreController::IP6TABLES_PROCESS));
378*8542734aSAndroid Build Coastguard Worker
379*8542734aSAndroid Build Coastguard Worker // Don't allow a leak of more than 38 pages (~150 kiB).
380*8542734aSAndroid Build Coastguard Worker // This is more than enough for accuracy: the leak in b/162925719 fails with:
381*8542734aSAndroid Build Coastguard Worker // Expected: (38U) >= (getRssPages(pid4) - pages4), actual: 38 vs 66
382*8542734aSAndroid Build Coastguard Worker EXPECT_GE(38, getRssPages(pid4) - pages4) << "iptables-restore leaked too many pages";
383*8542734aSAndroid Build Coastguard Worker EXPECT_GE(38, getRssPages(pid6) - pages6) << "ip6tables-restore leaked too many pages";
384*8542734aSAndroid Build Coastguard Worker }
385