blob: 737656ba98524ca771d32af0157ad0a1f6e7c32b [file] [log] [blame]
Lorenzo Colitti89faa342016-02-26 11:38:47 +09001/*
2 * Copyright 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * binder_test.cpp - unit tests for netd binder RPCs.
17 */
18
19#include <cstdlib>
20#include <cstdint>
21#include <vector>
22
23#include <android-base/stringprintf.h>
24#include <gtest/gtest.h>
25#include <logwrap/logwrap.h>
26
27#include "NetdConstants.h"
28#include "android/net/INetd.h"
29#include "binder/IServiceManager.h"
30
31using namespace android;
32using namespace android::base;
33using namespace android::binder;
34using android::net::INetd;
35
36class BinderTest : public ::testing::Test {
37
38public:
39 BinderTest() {
40 sp<IServiceManager> sm = defaultServiceManager();
41 sp<IBinder> binder = sm->getService(String16("netd"));
42 if (binder != nullptr) {
43 mNetd = interface_cast<INetd>(binder);
44 }
45 }
46
47 void SetUp() {
48 ASSERT_NE(nullptr, mNetd.get());
49 }
50
51protected:
52 sp<INetd> mNetd;
53};
54
55
56class TimedOperation {
57public:
58 TimedOperation(std::string name): mStart(std::chrono::steady_clock::now()), mName(name) {}
59 virtual ~TimedOperation() {
60 using ms = std::chrono::duration<float, std::ratio<1, 1000>>;
61 fprintf(stderr, " %s: %6.1f ms\n", mName.c_str(),
62 std::chrono::duration_cast<ms>(std::chrono::steady_clock::now() - mStart).count());
63 }
64
65private:
66 std::chrono::time_point<std::chrono::steady_clock> mStart;
67 std::string mName;
68};
69
70TEST_F(BinderTest, TestIsAlive) {
71 TimedOperation t("isAlive RPC");
72 bool isAlive = false;
73 mNetd->isAlive(&isAlive);
74 ASSERT_TRUE(isAlive);
75}
76
77static int randomUid() {
78 return 100000 * arc4random_uniform(7) + 10000 + arc4random_uniform(5000);
79}
80
81static int countNewlines(FILE *f) {
82 char buf[4096];
83 int numNewlines = 0;
84 size_t bytesread;
85 while ((bytesread = fread(buf, 1, sizeof(buf), f)) > 0) {
86 for (size_t i = 0; i < bytesread; i++) {
87 if (buf[i] == '\n') {
88 numNewlines++;
89 }
90 }
91 }
92 return numNewlines;
93}
94
95static int ruleLineLength(const char *binary, const char *chainName) {
96 FILE *f;
97 std::string command = StringPrintf("%s -n -L %s", binary, chainName);
98 if ((f = popen(command.c_str(), "r")) == NULL) {
99 perror("popen");
100 return -1;
101 }
102 int numLines = countNewlines(f);
103 pclose(f);
104 return numLines;
105}
106
107
108TEST_F(BinderTest, TestFirewallReplaceUidChain) {
109 std::string chainName = StringPrintf("netd_binder_test_%u", arc4random_uniform(10000));
110 const int kNumUids = 500;
111 std::vector<int32_t> noUids(0);
112 std::vector<int32_t> uids(kNumUids);
113 for (int i = 0; i < kNumUids; i++) {
114 uids[i] = randomUid();
115 }
116
117 bool ret;
118 {
119 TimedOperation op(StringPrintf("Programming %d-UID whitelist chain", kNumUids));
120 mNetd->firewallReplaceUidChain(String16(chainName.c_str()), true, uids, &ret);
121 }
122 EXPECT_EQ(true, ret);
123 EXPECT_EQ((int) uids.size() + 4, ruleLineLength(IPTABLES_PATH, chainName.c_str()));
124 EXPECT_EQ((int) uids.size() + 4, ruleLineLength(IP6TABLES_PATH, chainName.c_str()));
125 {
126 TimedOperation op("Clearing whitelist chain");
127 mNetd->firewallReplaceUidChain(String16(chainName.c_str()), false, noUids, &ret);
128 }
129 EXPECT_EQ(true, ret);
130 EXPECT_EQ(2, ruleLineLength(IPTABLES_PATH, chainName.c_str()));
131 EXPECT_EQ(2, ruleLineLength(IP6TABLES_PATH, chainName.c_str()));
132
133 {
134 TimedOperation op(StringPrintf("Programming %d-UID blacklist chain", kNumUids));
135 mNetd->firewallReplaceUidChain(String16(chainName.c_str()), false, uids, &ret);
136 }
137 EXPECT_EQ(true, ret);
138 EXPECT_EQ((int) uids.size() + 3, ruleLineLength(IPTABLES_PATH, chainName.c_str()));
139 EXPECT_EQ((int) uids.size() + 3, ruleLineLength(IP6TABLES_PATH, chainName.c_str()));
140
141 {
142 TimedOperation op("Clearing blacklist chain");
143 mNetd->firewallReplaceUidChain(String16(chainName.c_str()), false, noUids, &ret);
144 }
145 EXPECT_EQ(true, ret);
146 EXPECT_EQ(2, ruleLineLength(IPTABLES_PATH, chainName.c_str()));
147 EXPECT_EQ(2, ruleLineLength(IP6TABLES_PATH, chainName.c_str()));
148
149 // Check that the call fails if iptables returns an error.
150 std::string veryLongStringName = "netd_binder_test_UnacceptablyLongIptablesChainName";
151 mNetd->firewallReplaceUidChain(String16(veryLongStringName.c_str()), true, noUids, &ret);
152 EXPECT_EQ(false, ret);
153}