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