1 /*
2 * Copyright (C) 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 */
17
18 #include <arpa/inet.h>
19 #include <errno.h>
20 #include <linux/if_packet.h>
21 #include <linux/if_tun.h>
22 #include <net/if.h>
23 #include <poll.h>
24 #include <sched.h>
25 #include <sys/capability.h>
26 #include <sys/ioctl.h>
27 #include <sys/socket.h>
28 #include <sys/types.h>
29
30 #include <gtest/gtest.h>
31
32 #include <android-base/unique_fd.h>
33
34 #define LOG_TAG "NetdTest"
35 #include "bpf/BpfMap.h"
36 #include "netdbpf/bpf_shared.h"
37
38 #include "OffloadUtils.h"
39
40 namespace android {
41 namespace net {
42
43 using base::unique_fd;
44
TEST(NetUtilsWrapperTest,TestFileCapabilities)45 TEST(NetUtilsWrapperTest, TestFileCapabilities) {
46 errno = 0;
47 ASSERT_EQ(NULL, cap_get_file("/system/bin/netutils-wrapper-1.0"));
48 ASSERT_EQ(ENODATA, errno);
49 }
50
TEST(NetdSELinuxTest,CheckProperMTULabels)51 TEST(NetdSELinuxTest, CheckProperMTULabels) {
52 // Since we expect the egrep regexp to filter everything out,
53 // we thus expect no matches and thus a return code of 1
54 // NOLINTNEXTLINE(cert-env33-c)
55 ASSERT_EQ(W_EXITCODE(1, 0), system("ls -Z /sys/class/net/*/mtu | egrep -q -v "
56 "'^u:object_r:sysfs_net:s0 /sys/class/net/'"));
57 }
58
59 // Trivial thread function that simply immediately terminates successfully.
thread(void *)60 static int thread(void*) {
61 return 0;
62 }
63
64 typedef int (*thread_t)(void*);
65
nsTest(int flags,bool success,thread_t newThread)66 static void nsTest(int flags, bool success, thread_t newThread) {
67 // We need a minimal stack, but not clear if it will grow up or down,
68 // So allocate 2 pages and give a pointer to the middle.
69 static char stack[PAGE_SIZE * 2];
70 errno = 0;
71 // VFORK: if thread is successfully created, then kernel will wait for it
72 // to terminate before we resume -> hence static stack is safe to reuse.
73 int tid = clone(newThread, &stack[PAGE_SIZE], flags | CLONE_VFORK, NULL);
74 if (success) {
75 ASSERT_EQ(errno, 0);
76 ASSERT_GE(tid, 0);
77 } else {
78 ASSERT_EQ(errno, EINVAL);
79 ASSERT_EQ(tid, -1);
80 }
81 }
82
83 // Test kernel configuration option CONFIG_NAMESPACES=y
TEST(NetdNamespaceTest,CheckMountNamespaceSupport)84 TEST(NetdNamespaceTest, CheckMountNamespaceSupport) {
85 nsTest(CLONE_NEWNS, true, thread);
86 }
87
88 // Test kernel configuration option CONFIG_UTS_NS=y
TEST(NetdNamespaceTest,CheckUTSNamespaceSupport)89 TEST(NetdNamespaceTest, CheckUTSNamespaceSupport) {
90 nsTest(CLONE_NEWUTS, true, thread);
91 }
92
93 // Test kernel configuration option CONFIG_NET_NS=y
TEST(NetdNamespaceTest,CheckNetworkNamespaceSupport)94 TEST(NetdNamespaceTest, CheckNetworkNamespaceSupport) {
95 nsTest(CLONE_NEWNET, true, thread);
96 }
97
98 // Test kernel configuration option CONFIG_USER_NS=n
TEST(NetdNamespaceTest,CheckNoUserNamespaceSupport)99 TEST(NetdNamespaceTest, /*DISABLED_*/ CheckNoUserNamespaceSupport) {
100 nsTest(CLONE_NEWUSER, false, thread);
101 }
102
103 // Test for all of the above
TEST(NetdNamespaceTest,CheckFullNamespaceSupport)104 TEST(NetdNamespaceTest, CheckFullNamespaceSupport) {
105 nsTest(CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWNET, true, thread);
106 }
107
108 // Test for presence of kernel patch:
109 // ANDROID: net: bpf: permit redirect from ingress L3 to egress L2 devices at near max mtu
110 // on 4.14+ kernels.
TEST(NetdBpfTest,testBpfSkbChangeHeadAboveMTU)111 TEST(NetdBpfTest, testBpfSkbChangeHeadAboveMTU) {
112 SKIP_IF_EXTENDED_BPF_NOT_SUPPORTED;
113
114 constexpr int mtu = 1500;
115
116 errno = 0;
117
118 // Amusingly can't use SIOC... on tun/tap fds.
119 int rv = socket(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0);
120 ASSERT_EQ(errno, 0);
121 ASSERT_GE(rv, 3);
122 unique_fd unixfd(rv);
123
124 rv = open("/dev/net/tun", O_RDWR | O_NONBLOCK);
125 ASSERT_EQ(errno, 0);
126 ASSERT_GE(rv, 3);
127 unique_fd tun(rv);
128
129 rv = open("/dev/net/tun", O_RDWR | O_NONBLOCK);
130 ASSERT_EQ(errno, 0);
131 ASSERT_GE(rv, 3);
132 unique_fd tap(rv);
133
134 struct ifreq tun_ifr = {
135 .ifr_flags = IFF_TUN | IFF_NO_PI,
136 .ifr_name = "tun_bpftest",
137 };
138
139 struct ifreq tap_ifr = {
140 .ifr_flags = IFF_TAP | IFF_NO_PI,
141 .ifr_name = "tap_bpftest",
142 };
143
144 rv = ioctl(tun, TUNSETIFF, &tun_ifr);
145 ASSERT_EQ(errno, 0);
146 ASSERT_EQ(rv, 0);
147
148 rv = ioctl(tap, TUNSETIFF, &tap_ifr);
149 ASSERT_EQ(errno, 0);
150 ASSERT_EQ(rv, 0);
151
152 // prevents kernel from sending us spurious ipv6 packets
153 rv = open("/proc/sys/net/ipv6/conf/tap_bpftest/disable_ipv6", O_WRONLY);
154 ASSERT_EQ(errno, 0);
155 ASSERT_GE(rv, 3);
156 unique_fd f(rv);
157
158 rv = write(f, "1\n", 2);
159 ASSERT_EQ(errno, 0);
160 ASSERT_EQ(rv, 2);
161
162 rv = close(f.release());
163 ASSERT_EQ(errno, 0);
164 ASSERT_EQ(rv, 0);
165
166 int tunif = if_nametoindex(tun_ifr.ifr_name);
167 ASSERT_GE(tunif, 2);
168
169 int tapif = if_nametoindex(tap_ifr.ifr_name);
170 ASSERT_GE(tapif, 2);
171
172 tun_ifr.ifr_mtu = mtu;
173 rv = ioctl(unixfd, SIOCSIFMTU, &tun_ifr);
174 ASSERT_EQ(errno, 0);
175 ASSERT_EQ(rv, 0);
176
177 tap_ifr.ifr_mtu = mtu;
178 rv = ioctl(unixfd, SIOCSIFMTU, &tap_ifr);
179 ASSERT_EQ(errno, 0);
180 ASSERT_EQ(rv, 0);
181
182 rv = ioctl(unixfd, SIOCGIFFLAGS, &tun_ifr);
183 ASSERT_EQ(errno, 0);
184 ASSERT_EQ(rv, 0);
185
186 rv = ioctl(unixfd, SIOCGIFFLAGS, &tap_ifr);
187 ASSERT_EQ(errno, 0);
188 ASSERT_EQ(rv, 0);
189
190 tun_ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
191
192 tap_ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
193
194 rv = ioctl(unixfd, SIOCSIFFLAGS, &tun_ifr);
195 ASSERT_EQ(errno, 0);
196 ASSERT_EQ(rv, 0);
197
198 rv = ioctl(unixfd, SIOCSIFFLAGS, &tap_ifr);
199 ASSERT_EQ(errno, 0);
200 ASSERT_EQ(rv, 0);
201
202 rv = tcQdiscAddDevClsact(tunif);
203 ASSERT_EQ(rv, 0);
204
205 int bpfFd = getTetherIngressProgFd(/* ethernet */ false);
206 ASSERT_EQ(errno, 0);
207 ASSERT_GE(bpfFd, 3);
208
209 rv = tcFilterAddDevIngressTether(tunif, bpfFd, /* ethernet*/ false);
210 ASSERT_EQ(rv, 0);
211
212 bpf::BpfMap<TetherIngressKey, TetherIngressValue> bpfIngressMap;
213 bpf::BpfMap<uint32_t, TetherStatsValue> bpfStatsMap;
214 bpf::BpfMap<uint32_t, uint64_t> bpfLimitMap;
215
216 rv = getTetherIngressMapFd();
217 ASSERT_GE(rv, 3);
218 bpfIngressMap.reset(rv);
219
220 rv = getTetherStatsMapFd();
221 ASSERT_GE(rv, 3);
222 bpfStatsMap.reset(rv);
223
224 rv = getTetherLimitMapFd();
225 ASSERT_GE(rv, 3);
226 bpfLimitMap.reset(rv);
227
228 TetherIngressKey key = {
229 .iif = static_cast<uint32_t>(tunif),
230 //.neigh6 = ,
231 };
232
233 ethhdr hdr = {
234 .h_proto = htons(ETH_P_IPV6),
235 };
236
237 TetherIngressValue value = {
238 .oif = static_cast<uint32_t>(tapif),
239 .macHeader = hdr,
240 .pmtu = mtu,
241 };
242
243 #define ASSERT_OK(status) ASSERT_TRUE((status).ok())
244
245 ASSERT_OK(bpfIngressMap.writeValue(key, value, BPF_ANY));
246
247 uint32_t k = tunif;
248 TetherStatsValue stats = {};
249 ASSERT_OK(bpfStatsMap.writeValue(k, stats, BPF_NOEXIST));
250
251 uint64_t limit = ~0uLL;
252 ASSERT_OK(bpfLimitMap.writeValue(k, limit, BPF_NOEXIST));
253
254 // minimal 'acceptable' 40-byte hoplimit 255 IPv6 packet, src ip 2000::
255 uint8_t pkt[mtu] = {
256 0x60, 0, 0, 0, 0, 40, 0, 255, 0x20,
257 };
258
259 // Iterate over all packet sizes from minimal ipv6 packet to mtu.
260 // Tethering ebpf program should forward the packet from tun to tap interface.
261 // TUN is L3, TAP is L2, so it will add a 14 byte ethernet header.
262 for (int pkt_size = 40; pkt_size <= mtu; ++pkt_size) {
263 rv = write(tun, pkt, pkt_size);
264 ASSERT_EQ(errno, 0);
265 ASSERT_EQ(rv, pkt_size);
266
267 struct pollfd p = {
268 .fd = tap,
269 .events = POLLIN,
270 };
271
272 rv = poll(&p, 1, 1000 /*milliseconds*/);
273 if (rv == 0) {
274 // we hit a timeout at this packet size, log it
275 EXPECT_EQ(pkt_size, -1);
276 // this particular packet size is where it fails without the oneline kernel fix
277 if (pkt_size + ETH_HLEN == mtu + 1) EXPECT_EQ("detected missing kernel patch", "");
278 break;
279 }
280 EXPECT_EQ(errno, 0);
281 EXPECT_EQ(rv, 1);
282 EXPECT_EQ(p.revents, POLLIN);
283
284 // use a buffer 1 byte larger then what we expect so we don't simply get truncated down
285 uint8_t buf[ETH_HLEN + mtu + 1];
286 rv = read(tap, buf, sizeof(buf));
287 EXPECT_EQ(errno, 0);
288 EXPECT_EQ(rv, ETH_HLEN + pkt_size);
289 errno = 0;
290 if (rv < 0) break;
291 }
292
293 ASSERT_OK(bpfIngressMap.deleteValue(key));
294 ASSERT_OK(bpfStatsMap.deleteValue(k));
295 ASSERT_OK(bpfLimitMap.deleteValue(k));
296 }
297
298 } // namespace net
299 } // namespace android
300