1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/base/address_tracker_linux.h"
6
7 #include <linux/if.h>
8 #include <linux/rtnetlink.h>
9 #include <sched.h>
10
11 #include <memory>
12 #include <unordered_set>
13 #include <vector>
14
15 #include "base/command_line.h"
16 #include "base/files/file_util.h"
17 #include "base/functional/bind.h"
18 #include "base/functional/callback_helpers.h"
19 #include "base/memory/raw_ptr.h"
20 #include "base/strings/string_number_conversions.h"
21 #include "base/synchronization/waitable_event.h"
22 #include "base/test/bind.h"
23 #include "base/test/multiprocess_test.h"
24 #include "base/test/spin_wait.h"
25 #include "base/test/task_environment.h"
26 #include "base/test/test_simple_task_runner.h"
27 #include "base/threading/simple_thread.h"
28 #include "build/build_config.h"
29 #include "net/base/address_map_cache_linux.h"
30 #include "net/base/address_map_linux.h"
31 #include "net/base/address_tracker_linux_test_util.h"
32 #include "net/base/ip_address.h"
33 #include "testing/gtest/include/gtest/gtest.h"
34 #include "testing/multiprocess_func_list.h"
35
36 #if BUILDFLAG(IS_ANDROID)
37 #include "base/android/build_info.h"
38 #endif
39
40 #ifndef IFA_F_HOMEADDRESS
41 #define IFA_F_HOMEADDRESS 0x10
42 #endif
43
44 using net::internal::AddressTrackerLinux;
45
46 namespace net::test {
47 namespace {
48
49 const int kTestInterfaceEth = 1;
50 const int kTestInterfaceWifi = 2;
51 const int kTestInterfaceTun = 123;
52 const int kTestInterfaceAp = 456;
53
54 const char kIgnoredInterfaceName[] = "uap0";
55
TestGetInterfaceName(int interface_index,char * buf)56 char* TestGetInterfaceName(int interface_index, char* buf) {
57 if (interface_index == kTestInterfaceEth) {
58 snprintf(buf, IFNAMSIZ, "%s", "eth0");
59 } else if (interface_index == kTestInterfaceTun) {
60 snprintf(buf, IFNAMSIZ, "%s", "tun0");
61 } else if (interface_index == kTestInterfaceAp) {
62 snprintf(buf, IFNAMSIZ, "%s", kIgnoredInterfaceName);
63 } else {
64 snprintf(buf, IFNAMSIZ, "%s", "");
65 }
66 return buf;
67 }
68
69 } // namespace
70
71 class AddressTrackerLinuxTest : public testing::Test {
72 protected:
73 AddressTrackerLinuxTest() = default;
74
InitializeAddressTracker(bool tracking)75 void InitializeAddressTracker(bool tracking) {
76 tracking_ = tracking;
77 if (tracking) {
78 tracker_ = std::make_unique<AddressTrackerLinux>(
79 base::DoNothing(), base::DoNothing(), base::DoNothing(),
80 ignored_interfaces_);
81 #if BUILDFLAG(IS_LINUX)
82 const auto& [address_map, online_links] =
83 tracker_->GetInitialDataAndStartRecordingDiffs();
84 address_map_cache_.SetCachedInfo(address_map, online_links);
85 #endif // BUILDFLAG(IS_LINUX)
86 } else {
87 tracker_ = std::make_unique<AddressTrackerLinux>();
88 }
89 original_get_interface_name_ = tracker_->get_interface_name_;
90 tracker_->get_interface_name_ = TestGetInterfaceName;
91 }
92
HandleAddressMessage(const NetlinkBuffer & buf)93 bool HandleAddressMessage(const NetlinkBuffer& buf) {
94 NetlinkBuffer writable_buf = buf;
95 bool address_changed = false;
96 bool link_changed = false;
97 bool tunnel_changed = false;
98 tracker_->HandleMessage(&writable_buf[0], buf.size(), &address_changed,
99 &link_changed, &tunnel_changed);
100 UpdateCache();
101 EXPECT_FALSE(link_changed);
102 return address_changed;
103 }
104
HandleLinkMessage(const NetlinkBuffer & buf)105 bool HandleLinkMessage(const NetlinkBuffer& buf) {
106 NetlinkBuffer writable_buf = buf;
107 bool address_changed = false;
108 bool link_changed = false;
109 bool tunnel_changed = false;
110 tracker_->HandleMessage(&writable_buf[0], buf.size(), &address_changed,
111 &link_changed, &tunnel_changed);
112 UpdateCache();
113 EXPECT_FALSE(address_changed);
114 return link_changed;
115 }
116
HandleTunnelMessage(const NetlinkBuffer & buf)117 bool HandleTunnelMessage(const NetlinkBuffer& buf) {
118 NetlinkBuffer writable_buf = buf;
119 bool address_changed = false;
120 bool link_changed = false;
121 bool tunnel_changed = false;
122 AddressMapOwnerLinux::AddressMapDiff address_map_diff_;
123 AddressMapOwnerLinux::OnlineLinksDiff online_links_diff_;
124 tracker_->HandleMessage(&writable_buf[0], buf.size(), &address_changed,
125 &link_changed, &tunnel_changed);
126 UpdateCache();
127 EXPECT_FALSE(address_changed);
128 return tunnel_changed;
129 }
130
GetAddressMap()131 AddressTrackerLinux::AddressMap GetAddressMap() {
132 return tracker_->GetAddressMap();
133 }
134
GetOnlineLinks() const135 const std::unordered_set<int> GetOnlineLinks() const {
136 return tracker_->GetOnlineLinks();
137 }
138
IgnoreInterface(const std::string & interface_name)139 void IgnoreInterface(const std::string& interface_name) {
140 ignored_interfaces_.insert(interface_name);
141 }
142
GetThreadsWaitingForConnectionTypeInit()143 int GetThreadsWaitingForConnectionTypeInit() {
144 return tracker_->GetThreadsWaitingForConnectionTypeInitForTesting();
145 }
146
147 std::unordered_set<std::string> ignored_interfaces_;
148 std::unique_ptr<AddressTrackerLinux> tracker_;
149 AddressTrackerLinux::GetInterfaceNameFunction original_get_interface_name_;
150
151 private:
152 // Checks that applying the generated diff to `address_map_cache_` results in
153 // the same AddressMap and set of online links that `tracker_` maintains.
UpdateCache()154 void UpdateCache() {
155 if (!tracking_) {
156 return;
157 }
158 #if BUILDFLAG(IS_LINUX)
159 address_map_cache_.ApplyDiffs(tracker_->address_map_diff_for_testing(),
160 tracker_->online_links_diff_for_testing());
161 EXPECT_EQ(address_map_cache_.GetAddressMap(), tracker_->GetAddressMap());
162 EXPECT_EQ(address_map_cache_.GetOnlineLinks(), tracker_->GetOnlineLinks());
163 tracker_->address_map_diff_for_testing().clear();
164 tracker_->online_links_diff_for_testing().clear();
165 #endif // BUILDFLAG(IS_LINUX)
166 }
167
168 #if BUILDFLAG(IS_LINUX)
169 AddressMapCacheLinux address_map_cache_;
170 #endif
171 bool tracking_;
172 };
173
174 namespace {
175
176 const unsigned char kAddress0[] = { 127, 0, 0, 1 };
177 const unsigned char kAddress1[] = { 10, 0, 0, 1 };
178 const unsigned char kAddress2[] = { 192, 168, 0, 1 };
179 const unsigned char kAddress3[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
180 0, 0, 0, 1 };
181
TEST_F(AddressTrackerLinuxTest,NewAddress)182 TEST_F(AddressTrackerLinuxTest, NewAddress) {
183 InitializeAddressTracker(true);
184
185 const IPAddress kEmpty;
186 const IPAddress kAddr0(kAddress0);
187 const IPAddress kAddr1(kAddress1);
188 const IPAddress kAddr2(kAddress2);
189 const IPAddress kAddr3(kAddress3);
190
191 NetlinkBuffer buffer;
192 MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kTestInterfaceEth,
193 kAddr0, kEmpty, &buffer);
194 EXPECT_TRUE(HandleAddressMessage(buffer));
195 AddressTrackerLinux::AddressMap map = GetAddressMap();
196 EXPECT_EQ(1u, map.size());
197 EXPECT_EQ(1u, map.count(kAddr0));
198 EXPECT_EQ(IFA_F_TEMPORARY, map[kAddr0].ifa_flags);
199
200 buffer.clear();
201 MakeAddrMessage(RTM_NEWADDR, IFA_F_HOMEADDRESS, AF_INET, kTestInterfaceEth,
202 kAddr1, kAddr2, &buffer);
203 EXPECT_TRUE(HandleAddressMessage(buffer));
204 map = GetAddressMap();
205 EXPECT_EQ(2u, map.size());
206 EXPECT_EQ(1u, map.count(kAddr0));
207 EXPECT_EQ(1u, map.count(kAddr2));
208 EXPECT_EQ(IFA_F_HOMEADDRESS, map[kAddr2].ifa_flags);
209
210 buffer.clear();
211 MakeAddrMessage(RTM_NEWADDR, 0, AF_INET6, kTestInterfaceEth, kEmpty, kAddr3,
212 &buffer);
213 EXPECT_TRUE(HandleAddressMessage(buffer));
214 map = GetAddressMap();
215 EXPECT_EQ(3u, map.size());
216 EXPECT_EQ(1u, map.count(kAddr3));
217 }
218
TEST_F(AddressTrackerLinuxTest,NewAddressChange)219 TEST_F(AddressTrackerLinuxTest, NewAddressChange) {
220 InitializeAddressTracker(true);
221
222 const IPAddress kEmpty;
223 const IPAddress kAddr0(kAddress0);
224
225 NetlinkBuffer buffer;
226 MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kTestInterfaceEth,
227 kAddr0, kEmpty, &buffer);
228 EXPECT_TRUE(HandleAddressMessage(buffer));
229 AddressTrackerLinux::AddressMap map = GetAddressMap();
230 EXPECT_EQ(1u, map.size());
231 EXPECT_EQ(1u, map.count(kAddr0));
232 EXPECT_EQ(IFA_F_TEMPORARY, map[kAddr0].ifa_flags);
233
234 buffer.clear();
235 MakeAddrMessage(RTM_NEWADDR, IFA_F_HOMEADDRESS, AF_INET, kTestInterfaceEth,
236 kAddr0, kEmpty, &buffer);
237 EXPECT_TRUE(HandleAddressMessage(buffer));
238 map = GetAddressMap();
239 EXPECT_EQ(1u, map.size());
240 EXPECT_EQ(1u, map.count(kAddr0));
241 EXPECT_EQ(IFA_F_HOMEADDRESS, map[kAddr0].ifa_flags);
242
243 // Both messages in one buffer.
244 buffer.clear();
245 MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kTestInterfaceEth,
246 kAddr0, kEmpty, &buffer);
247 MakeAddrMessage(RTM_NEWADDR, IFA_F_HOMEADDRESS, AF_INET, kTestInterfaceEth,
248 kAddr0, kEmpty, &buffer);
249 EXPECT_TRUE(HandleAddressMessage(buffer));
250 map = GetAddressMap();
251 EXPECT_EQ(1u, map.size());
252 EXPECT_EQ(IFA_F_HOMEADDRESS, map[kAddr0].ifa_flags);
253 }
254
TEST_F(AddressTrackerLinuxTest,NewAddressDuplicate)255 TEST_F(AddressTrackerLinuxTest, NewAddressDuplicate) {
256 InitializeAddressTracker(true);
257
258 const IPAddress kAddr0(kAddress0);
259
260 NetlinkBuffer buffer;
261 MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kTestInterfaceEth,
262 kAddr0, kAddr0, &buffer);
263 EXPECT_TRUE(HandleAddressMessage(buffer));
264 AddressTrackerLinux::AddressMap map = GetAddressMap();
265 EXPECT_EQ(1u, map.size());
266 EXPECT_EQ(1u, map.count(kAddr0));
267 EXPECT_EQ(IFA_F_TEMPORARY, map[kAddr0].ifa_flags);
268
269 EXPECT_FALSE(HandleAddressMessage(buffer));
270 map = GetAddressMap();
271 EXPECT_EQ(1u, map.size());
272 EXPECT_EQ(IFA_F_TEMPORARY, map[kAddr0].ifa_flags);
273 }
274
TEST_F(AddressTrackerLinuxTest,DeleteAddress)275 TEST_F(AddressTrackerLinuxTest, DeleteAddress) {
276 InitializeAddressTracker(true);
277
278 const IPAddress kEmpty;
279 const IPAddress kAddr0(kAddress0);
280 const IPAddress kAddr1(kAddress1);
281 const IPAddress kAddr2(kAddress2);
282
283 NetlinkBuffer buffer;
284 MakeAddrMessage(RTM_NEWADDR, 0, AF_INET, kTestInterfaceEth, kAddr0, kEmpty,
285 &buffer);
286 MakeAddrMessage(RTM_NEWADDR, 0, AF_INET, kTestInterfaceEth, kAddr1, kAddr2,
287 &buffer);
288 EXPECT_TRUE(HandleAddressMessage(buffer));
289 AddressTrackerLinux::AddressMap map = GetAddressMap();
290 EXPECT_EQ(2u, map.size());
291
292 buffer.clear();
293 MakeAddrMessage(RTM_DELADDR, 0, AF_INET, kTestInterfaceEth, kEmpty, kAddr0,
294 &buffer);
295 EXPECT_TRUE(HandleAddressMessage(buffer));
296 map = GetAddressMap();
297 EXPECT_EQ(1u, map.size());
298 EXPECT_EQ(0u, map.count(kAddr0));
299 EXPECT_EQ(1u, map.count(kAddr2));
300
301 buffer.clear();
302 MakeAddrMessage(RTM_DELADDR, 0, AF_INET, kTestInterfaceEth, kAddr2, kAddr1,
303 &buffer);
304 // kAddr1 does not exist in the map.
305 EXPECT_FALSE(HandleAddressMessage(buffer));
306 map = GetAddressMap();
307 EXPECT_EQ(1u, map.size());
308
309 buffer.clear();
310 MakeAddrMessage(RTM_DELADDR, 0, AF_INET, kTestInterfaceEth, kAddr2, kEmpty,
311 &buffer);
312 EXPECT_TRUE(HandleAddressMessage(buffer));
313 map = GetAddressMap();
314 EXPECT_EQ(0u, map.size());
315 }
316
TEST_F(AddressTrackerLinuxTest,DeprecatedLifetime)317 TEST_F(AddressTrackerLinuxTest, DeprecatedLifetime) {
318 InitializeAddressTracker(true);
319
320 const IPAddress kEmpty;
321 const IPAddress kAddr3(kAddress3);
322
323 NetlinkBuffer buffer;
324 MakeAddrMessage(RTM_NEWADDR, 0, AF_INET6, kTestInterfaceEth, kEmpty, kAddr3,
325 &buffer);
326 EXPECT_TRUE(HandleAddressMessage(buffer));
327 AddressTrackerLinux::AddressMap map = GetAddressMap();
328 EXPECT_EQ(1u, map.size());
329 EXPECT_EQ(1u, map.count(kAddr3));
330 EXPECT_EQ(0, map[kAddr3].ifa_flags);
331
332 // Verify 0 preferred lifetime implies deprecated.
333 buffer.clear();
334 MakeAddrMessageWithCacheInfo(RTM_NEWADDR, 0, AF_INET6, kTestInterfaceEth,
335 kEmpty, kAddr3, 0, &buffer);
336 EXPECT_TRUE(HandleAddressMessage(buffer));
337 map = GetAddressMap();
338 EXPECT_EQ(1u, map.size());
339 EXPECT_EQ(IFA_F_DEPRECATED, map[kAddr3].ifa_flags);
340
341 // Verify properly flagged message doesn't imply change.
342 buffer.clear();
343 MakeAddrMessageWithCacheInfo(RTM_NEWADDR, IFA_F_DEPRECATED, AF_INET6,
344 kTestInterfaceEth, kEmpty, kAddr3, 0, &buffer);
345 EXPECT_FALSE(HandleAddressMessage(buffer));
346 map = GetAddressMap();
347 EXPECT_EQ(1u, map.size());
348 EXPECT_EQ(IFA_F_DEPRECATED, map[kAddr3].ifa_flags);
349
350 // Verify implied deprecated doesn't imply change.
351 buffer.clear();
352 MakeAddrMessageWithCacheInfo(RTM_NEWADDR, 0, AF_INET6, kTestInterfaceEth,
353 kEmpty, kAddr3, 0, &buffer);
354 EXPECT_FALSE(HandleAddressMessage(buffer));
355 map = GetAddressMap();
356 EXPECT_EQ(1u, map.size());
357 EXPECT_EQ(IFA_F_DEPRECATED, map[kAddr3].ifa_flags);
358 }
359
TEST_F(AddressTrackerLinuxTest,IgnoredMessage)360 TEST_F(AddressTrackerLinuxTest, IgnoredMessage) {
361 InitializeAddressTracker(true);
362
363 const IPAddress kEmpty;
364 const IPAddress kAddr0(kAddress0);
365 const IPAddress kAddr3(kAddress3);
366
367 NetlinkBuffer buffer;
368 // Ignored family.
369 MakeAddrMessage(RTM_NEWADDR, 0, AF_UNSPEC, kTestInterfaceEth, kAddr3, kAddr0,
370 &buffer);
371 // No address.
372 MakeAddrMessage(RTM_NEWADDR, 0, AF_INET, kTestInterfaceEth, kEmpty, kEmpty,
373 &buffer);
374 // Ignored type.
375 MakeAddrMessage(RTM_DELROUTE, 0, AF_INET6, kTestInterfaceEth, kAddr3, kEmpty,
376 &buffer);
377 EXPECT_FALSE(HandleAddressMessage(buffer));
378 EXPECT_TRUE(GetAddressMap().empty());
379
380 // Valid message after ignored messages.
381 NetlinkMessage nlmsg(RTM_NEWADDR);
382 struct ifaddrmsg msg = {};
383 msg.ifa_family = AF_INET;
384 nlmsg.AddPayload(msg);
385 // Ignored attribute.
386 struct ifa_cacheinfo cache_info = {};
387 nlmsg.AddAttribute(IFA_CACHEINFO, &cache_info, sizeof(cache_info));
388 nlmsg.AddAttribute(IFA_ADDRESS, kAddr0.bytes().data(), kAddr0.size());
389 nlmsg.AppendTo(&buffer);
390
391 EXPECT_TRUE(HandleAddressMessage(buffer));
392 EXPECT_EQ(1u, GetAddressMap().size());
393 }
394
TEST_F(AddressTrackerLinuxTest,AddInterface)395 TEST_F(AddressTrackerLinuxTest, AddInterface) {
396 InitializeAddressTracker(true);
397
398 NetlinkBuffer buffer;
399
400 // Ignores loopback.
401 MakeLinkMessage(RTM_NEWLINK,
402 IFF_LOOPBACK | IFF_UP | IFF_LOWER_UP | IFF_RUNNING,
403 kTestInterfaceEth, &buffer);
404 EXPECT_FALSE(HandleLinkMessage(buffer));
405 EXPECT_TRUE(GetOnlineLinks().empty());
406
407 // Ignores not IFF_LOWER_UP.
408 MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_RUNNING, kTestInterfaceEth,
409 &buffer);
410 EXPECT_FALSE(HandleLinkMessage(buffer));
411 EXPECT_TRUE(GetOnlineLinks().empty());
412
413 // Ignores deletion.
414 MakeLinkMessage(RTM_DELLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING,
415 kTestInterfaceEth, &buffer);
416 EXPECT_FALSE(HandleLinkMessage(buffer));
417 EXPECT_TRUE(GetOnlineLinks().empty());
418
419 // Verify success.
420 MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING,
421 kTestInterfaceEth, &buffer);
422 EXPECT_TRUE(HandleLinkMessage(buffer));
423 EXPECT_EQ(1u, GetOnlineLinks().count(kTestInterfaceEth));
424 EXPECT_EQ(1u, GetOnlineLinks().size());
425
426 // Ignores redundant enables.
427 MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING,
428 kTestInterfaceEth, &buffer);
429 EXPECT_FALSE(HandleLinkMessage(buffer));
430 EXPECT_EQ(1u, GetOnlineLinks().count(kTestInterfaceEth));
431 EXPECT_EQ(1u, GetOnlineLinks().size());
432
433 // Ignores messages from wireless_send_event.
434 MakeWirelessLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING,
435 kTestInterfaceWifi, &buffer);
436 EXPECT_FALSE(HandleLinkMessage(buffer));
437 EXPECT_EQ(0u, GetOnlineLinks().count(kTestInterfaceWifi));
438 EXPECT_EQ(1u, GetOnlineLinks().size());
439
440 // Verify adding another online device (e.g. VPN) is considered a change.
441 MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 2, &buffer);
442 EXPECT_TRUE(HandleLinkMessage(buffer));
443 EXPECT_EQ(1u, GetOnlineLinks().count(kTestInterfaceEth));
444 EXPECT_EQ(1u, GetOnlineLinks().count(2));
445 EXPECT_EQ(2u, GetOnlineLinks().size());
446 }
447
TEST_F(AddressTrackerLinuxTest,RemoveInterface)448 TEST_F(AddressTrackerLinuxTest, RemoveInterface) {
449 InitializeAddressTracker(true);
450
451 NetlinkBuffer buffer;
452
453 // Should disappear when not IFF_LOWER_UP.
454 MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING,
455 kTestInterfaceEth, &buffer);
456 EXPECT_TRUE(HandleLinkMessage(buffer));
457 EXPECT_FALSE(GetOnlineLinks().empty());
458 MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_RUNNING, kTestInterfaceEth,
459 &buffer);
460 EXPECT_TRUE(HandleLinkMessage(buffer));
461 EXPECT_TRUE(GetOnlineLinks().empty());
462
463 // Ignores redundant disables.
464 MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_RUNNING, kTestInterfaceEth,
465 &buffer);
466 EXPECT_FALSE(HandleLinkMessage(buffer));
467 EXPECT_TRUE(GetOnlineLinks().empty());
468
469 // Ignores deleting down interfaces.
470 MakeLinkMessage(RTM_DELLINK, IFF_UP | IFF_RUNNING, kTestInterfaceEth,
471 &buffer);
472 EXPECT_FALSE(HandleLinkMessage(buffer));
473 EXPECT_TRUE(GetOnlineLinks().empty());
474
475 // Should disappear when deleted.
476 MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING,
477 kTestInterfaceEth, &buffer);
478 EXPECT_TRUE(HandleLinkMessage(buffer));
479 EXPECT_FALSE(GetOnlineLinks().empty());
480 MakeLinkMessage(RTM_DELLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING,
481 kTestInterfaceEth, &buffer);
482 EXPECT_TRUE(HandleLinkMessage(buffer));
483 EXPECT_TRUE(GetOnlineLinks().empty());
484
485 // Ignores messages from wireless_send_event.
486 MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING,
487 kTestInterfaceWifi, &buffer);
488 EXPECT_TRUE(HandleLinkMessage(buffer));
489 EXPECT_FALSE(GetOnlineLinks().empty());
490 MakeWirelessLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP,
491 kTestInterfaceWifi, &buffer);
492 EXPECT_FALSE(HandleLinkMessage(buffer));
493 EXPECT_FALSE(GetOnlineLinks().empty());
494 MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_RUNNING, kTestInterfaceWifi,
495 &buffer);
496 EXPECT_TRUE(HandleLinkMessage(buffer));
497 EXPECT_TRUE(GetOnlineLinks().empty());
498 }
499
TEST_F(AddressTrackerLinuxTest,IgnoreInterface)500 TEST_F(AddressTrackerLinuxTest, IgnoreInterface) {
501 IgnoreInterface(kIgnoredInterfaceName);
502 InitializeAddressTracker(true);
503
504 NetlinkBuffer buffer;
505 const IPAddress kEmpty;
506 const IPAddress kAddr0(kAddress0);
507
508 // Verify online links and address map has been not been updated
509 MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kTestInterfaceAp,
510 kAddr0, kEmpty, &buffer);
511 EXPECT_FALSE(HandleAddressMessage(buffer));
512 AddressTrackerLinux::AddressMap map = GetAddressMap();
513 EXPECT_EQ(0u, map.size());
514 EXPECT_EQ(0u, map.count(kAddr0));
515 MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING,
516 kTestInterfaceAp, &buffer);
517 EXPECT_FALSE(HandleLinkMessage(buffer));
518 EXPECT_EQ(0u, GetOnlineLinks().count(kTestInterfaceAp));
519 EXPECT_EQ(0u, GetOnlineLinks().size());
520 }
521
TEST_F(AddressTrackerLinuxTest,IgnoreInterface_NonIgnoredInterface)522 TEST_F(AddressTrackerLinuxTest, IgnoreInterface_NonIgnoredInterface) {
523 IgnoreInterface(kIgnoredInterfaceName);
524 InitializeAddressTracker(true);
525
526 NetlinkBuffer buffer;
527 const IPAddress kEmpty;
528 const IPAddress kAddr0(kAddress0);
529
530 // Verify eth0 is not ignored when only uap0 is ignored
531 MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kTestInterfaceEth,
532 kAddr0, kEmpty, &buffer);
533 EXPECT_TRUE(HandleAddressMessage(buffer));
534 AddressTrackerLinux::AddressMap map = GetAddressMap();
535 EXPECT_EQ(1u, map.size());
536 EXPECT_EQ(1u, map.count(kAddr0));
537 MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING,
538 kTestInterfaceEth, &buffer);
539 EXPECT_TRUE(HandleLinkMessage(buffer));
540 EXPECT_EQ(1u, GetOnlineLinks().count(kTestInterfaceEth));
541 EXPECT_EQ(1u, GetOnlineLinks().size());
542 }
543
TEST_F(AddressTrackerLinuxTest,TunnelInterface)544 TEST_F(AddressTrackerLinuxTest, TunnelInterface) {
545 InitializeAddressTracker(true);
546
547 NetlinkBuffer buffer;
548
549 // Ignores without "tun" prefixed name.
550 MakeLinkMessage(RTM_NEWLINK,
551 IFF_UP | IFF_LOWER_UP | IFF_RUNNING | IFF_POINTOPOINT,
552 kTestInterfaceEth, &buffer);
553 EXPECT_FALSE(HandleTunnelMessage(buffer));
554
555 // Verify success.
556 MakeLinkMessage(RTM_NEWLINK,
557 IFF_UP | IFF_LOWER_UP | IFF_RUNNING | IFF_POINTOPOINT,
558 kTestInterfaceTun, &buffer);
559 EXPECT_TRUE(HandleTunnelMessage(buffer));
560
561 // Ignores redundant enables.
562 MakeLinkMessage(RTM_NEWLINK,
563 IFF_UP | IFF_LOWER_UP | IFF_RUNNING | IFF_POINTOPOINT,
564 kTestInterfaceTun, &buffer);
565 EXPECT_FALSE(HandleTunnelMessage(buffer));
566
567 // Ignores deleting without "tun" prefixed name.
568 MakeLinkMessage(RTM_DELLINK,
569 IFF_UP | IFF_LOWER_UP | IFF_RUNNING | IFF_POINTOPOINT,
570 0, &buffer);
571 EXPECT_FALSE(HandleTunnelMessage(buffer));
572
573 // Verify successful deletion
574 MakeLinkMessage(RTM_DELLINK,
575 IFF_UP | IFF_LOWER_UP | IFF_RUNNING | IFF_POINTOPOINT,
576 kTestInterfaceTun, &buffer);
577 EXPECT_TRUE(HandleTunnelMessage(buffer));
578
579 // Ignores redundant deletions.
580 MakeLinkMessage(RTM_DELLINK,
581 IFF_UP | IFF_LOWER_UP | IFF_RUNNING | IFF_POINTOPOINT,
582 kTestInterfaceTun, &buffer);
583 EXPECT_FALSE(HandleTunnelMessage(buffer));
584 }
585
586 // Check AddressTrackerLinux::get_interface_name_ original implementation
587 // doesn't crash or return NULL.
TEST_F(AddressTrackerLinuxTest,GetInterfaceName)588 TEST_F(AddressTrackerLinuxTest, GetInterfaceName) {
589 InitializeAddressTracker(true);
590
591 for (int i = 0; i < 10; i++) {
592 char buf[IFNAMSIZ] = {0};
593 EXPECT_NE((const char*)nullptr, original_get_interface_name_(i, buf));
594 }
595 }
596
TEST_F(AddressTrackerLinuxTest,NonTrackingMode)597 TEST_F(AddressTrackerLinuxTest, NonTrackingMode) {
598 InitializeAddressTracker(false);
599
600 const IPAddress kEmpty;
601 const IPAddress kAddr0(kAddress0);
602
603 NetlinkBuffer buffer;
604 MakeAddrMessage(RTM_NEWADDR, IFA_F_TEMPORARY, AF_INET, kTestInterfaceEth,
605 kAddr0, kEmpty, &buffer);
606 EXPECT_TRUE(HandleAddressMessage(buffer));
607 AddressTrackerLinux::AddressMap map = GetAddressMap();
608 EXPECT_EQ(1u, map.size());
609 EXPECT_EQ(1u, map.count(kAddr0));
610 EXPECT_EQ(IFA_F_TEMPORARY, map[kAddr0].ifa_flags);
611
612 MakeLinkMessage(RTM_NEWLINK, IFF_UP | IFF_LOWER_UP | IFF_RUNNING, 1, &buffer);
613 EXPECT_TRUE(HandleLinkMessage(buffer));
614 EXPECT_EQ(1u, GetOnlineLinks().count(1));
615 EXPECT_EQ(1u, GetOnlineLinks().size());
616 }
617
TEST_F(AddressTrackerLinuxTest,NonTrackingModeInit)618 TEST_F(AddressTrackerLinuxTest, NonTrackingModeInit) {
619 #if BUILDFLAG(IS_ANDROID)
620 // Calling Init() on Android P+ isn't supported.
621 if (base::android::BuildInfo::GetInstance()->sdk_int() >=
622 base::android::SDK_VERSION_P)
623 return;
624 #endif
625 AddressTrackerLinux tracker;
626 tracker.Init();
627 }
628
629 class GetCurrentConnectionTypeRunner
630 : public base::DelegateSimpleThread::Delegate {
631 public:
GetCurrentConnectionTypeRunner(AddressTrackerLinux * tracker,const std::string & thread_name)632 explicit GetCurrentConnectionTypeRunner(AddressTrackerLinux* tracker,
633 const std::string& thread_name)
634 : tracker_(tracker),
635 done_(base::WaitableEvent::ResetPolicy::MANUAL,
636 base::WaitableEvent::InitialState::NOT_SIGNALED),
637 thread_(this, thread_name) {}
638 ~GetCurrentConnectionTypeRunner() override = default;
639
Run()640 void Run() override {
641 tracker_->GetCurrentConnectionType();
642 done_.Signal();
643 }
644
Start()645 void Start() {
646 thread_.Start();
647 }
648
VerifyCompletes()649 void VerifyCompletes() {
650 EXPECT_TRUE(done_.TimedWait(base::Seconds(5)));
651 thread_.Join();
652 }
653
654 private:
655 const raw_ptr<AddressTrackerLinux> tracker_;
656 base::WaitableEvent done_;
657 base::DelegateSimpleThread thread_;
658 };
659
TEST_F(AddressTrackerLinuxTest,BroadcastInit)660 TEST_F(AddressTrackerLinuxTest, BroadcastInit) {
661 #if BUILDFLAG(IS_ANDROID)
662 // Calling Init() on Android P+ isn't supported.
663 if (base::android::BuildInfo::GetInstance()->sdk_int() >=
664 base::android::SDK_VERSION_P)
665 return;
666 #endif
667 base::test::TaskEnvironment task_environment(
668 base::test::TaskEnvironment::MainThreadType::IO);
669 InitializeAddressTracker(true);
670
671 GetCurrentConnectionTypeRunner runner1(tracker_.get(), "waiter_thread_1");
672 GetCurrentConnectionTypeRunner runner2(tracker_.get(), "waiter_thread_2");
673
674 runner1.Start();
675 runner2.Start();
676
677 SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(
678 GetThreadsWaitingForConnectionTypeInit() == 2);
679
680 tracker_->Init();
681
682 runner1.VerifyCompletes();
683 runner2.VerifyCompletes();
684 }
685
TEST_F(AddressTrackerLinuxTest,TunnelInterfaceName)686 TEST_F(AddressTrackerLinuxTest, TunnelInterfaceName) {
687 EXPECT_TRUE(AddressTrackerLinux::IsTunnelInterfaceName("tun0"));
688 EXPECT_FALSE(AddressTrackerLinux::IsTunnelInterfaceName("wlan0"));
689 }
690
691 } // namespace
692 } // namespace net::test
693
694 namespace net::internal {
695
696 // This is a regression test for https://crbug.com/1224428.
697 //
698 // This test initializes two instances of `AddressTrackerLinux` in the same
699 // process. The test will fail if the implementation reuses the value of
700 // `sockaddr_nl::nl_pid`.
701 //
702 // Note: consumers generally should not need to create two tracking instances of
703 // `AddressTrackerLinux` in the same process.
TEST(AddressTrackerLinuxNetlinkTest,TestInitializeTwoTrackers)704 TEST(AddressTrackerLinuxNetlinkTest, TestInitializeTwoTrackers) {
705 #if BUILDFLAG(IS_ANDROID)
706 // Calling Init() on Android P+ isn't supported.
707 if (base::android::BuildInfo::GetInstance()->sdk_int() >=
708 base::android::SDK_VERSION_P)
709 return;
710 #endif
711 base::test::TaskEnvironment task_env(
712 base::test::TaskEnvironment::MainThreadType::IO);
713 AddressTrackerLinux tracker1(base::DoNothing(), base::DoNothing(),
714 base::DoNothing(), {});
715 AddressTrackerLinux tracker2(base::DoNothing(), base::DoNothing(),
716 base::DoNothing(), {});
717 tracker1.Init();
718 tracker2.Init();
719 EXPECT_TRUE(tracker1.DidTrackingInitSucceedForTesting());
720 EXPECT_TRUE(tracker2.DidTrackingInitSucceedForTesting());
721 }
722
723 // These tests use `base::LaunchOptions::clone_flags` for fine-grained control
724 // over the clone syscall, but the field is only defined on Linux and ChromeOS.
725 // Unfortunately, this means these tests do not have coverage on Android.
726 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
727 // These tests require specific flag values defined in <sched.h>.
728 #if defined(CLONE_NEWUSER) && defined(CLONE_NEWPID)
729
730 namespace {
731 const char* const kSwitchParentWriteFd = "addresstrackerlinux_parent_write_fd";
732 const char* const kSwitchReadFd = "addresstrackerlinux_read_fd";
733
734 enum IPCMessage {
735 // Sent from child to parent once the child has initialized its tracker.
736 kChildInitializedAndWaiting,
737 // Sent from child to parent when it was unable to initialize its tracker.
738 kChildFailed,
739 // Sent from parent to child when all children are permitted to exit.
740 kChildMayExit,
741 };
742
GetSwitchValueFile(const base::CommandLine * command_line,std::string_view name)743 base::File GetSwitchValueFile(const base::CommandLine* command_line,
744 std::string_view name) {
745 std::string value = command_line->GetSwitchValueASCII(name);
746 int fd;
747 CHECK(base::StringToInt(value, &fd));
748 return base::File(fd);
749 }
750 } // namespace
751
752 // This is a regression test for https://crbug.com/1224428.
753 //
754 // This test creates multiple concurrent `AddressTrackerLinux` instances in
755 // separate processes, each in their own PID namespaces.
TEST(AddressTrackerLinuxNetlinkTest,TestInitializeTwoTrackersInPidNamespaces)756 TEST(AddressTrackerLinuxNetlinkTest, TestInitializeTwoTrackersInPidNamespaces) {
757 // This test initializes `kNumChildren` instances of `AddressTrackerLinux` in
758 // tracking mode, each in their own child process running in a PID namespace.
759 // The test will fail if the implementation reuses the value of
760 // `sockaddr_nl::nl_pid`.
761 //
762 // The child processes use pipes to synchronize. Each child initializes a
763 // tracker, sends a message to the parent, and waits for the parent to
764 // respond, indicating that all children are done setting up. This ensures
765 // that the tracker objects have overlapping lifetimes, and thus that the
766 // underlying netlink sockets have overlapping lifetimes. This coexistence is
767 // necessary, but not sufficient, for a `sockaddr_nl::nl_pid` value collision.
768 constexpr size_t kNumChildren = 2;
769
770 base::ScopedFD parent_read_fd, parent_write_fd;
771 ASSERT_TRUE(base::CreatePipe(&parent_read_fd, &parent_write_fd));
772
773 struct Child {
774 base::ScopedFD read_fd;
775 base::ScopedFD write_fd;
776 base::Process process;
777 } children[kNumChildren];
778
779 for (Child& child : children) {
780 ASSERT_TRUE(base::CreatePipe(&child.read_fd, &child.write_fd));
781
782 // Since the child process will wipe its address space by calling execvp, we
783 // must share the file descriptors via its command line.
784 base::CommandLine command_line(
785 base::GetMultiProcessTestChildBaseCommandLine());
786 command_line.AppendSwitchASCII(kSwitchParentWriteFd,
787 base::NumberToString(parent_write_fd.get()));
788 command_line.AppendSwitchASCII(kSwitchReadFd,
789 base::NumberToString(child.read_fd.get()));
790
791 base::LaunchOptions options;
792 // Indicate that the child process requires these file descriptors.
793 // Otherwise, they will be closed. See `base::CloseSuperfluousFds`.
794 options.fds_to_remap = {{child.read_fd.get(), child.read_fd.get()},
795 {parent_write_fd.get(), parent_write_fd.get()}};
796 // Clone into a new PID namespace. Making it a new user namespace as well to
797 // skirt the CAP_SYS_ADMIN requirement.
798 options.clone_flags = CLONE_NEWPID | CLONE_NEWUSER;
799
800 child.process = base::SpawnMultiProcessTestChild(
801 "ChildProcessInitializeTrackerForTesting", command_line, options);
802 }
803
804 // Wait for all children to finish initializing their tracking
805 // AddressTrackerLinuxes.
806 base::File parent_reader(std::move(parent_read_fd));
807 for (const Child& child : children) {
808 ASSERT_TRUE(child.process.IsValid());
809
810 uint8_t message[] = {0};
811 ASSERT_TRUE(parent_reader.ReadAtCurrentPosAndCheck(message));
812 ASSERT_EQ(message[0], kChildInitializedAndWaiting);
813 }
814
815 // Tell children to exit and wait for them to exit.
816 for (Child& child : children) {
817 base::File child_writer(std::move(child.write_fd));
818 const uint8_t kMessage[] = {kChildMayExit};
819 ASSERT_TRUE(child_writer.WriteAtCurrentPosAndCheck(kMessage));
820
821 int exit_code = 0;
822 ASSERT_TRUE(child.process.WaitForExit(&exit_code));
823 ASSERT_EQ(exit_code, 0);
824 }
825 }
826
MULTIPROCESS_TEST_MAIN(ChildProcessInitializeTrackerForTesting)827 MULTIPROCESS_TEST_MAIN(ChildProcessInitializeTrackerForTesting) {
828 base::test::TaskEnvironment task_env(
829 base::test::TaskEnvironment::MainThreadType::IO);
830
831 const base::CommandLine* command_line =
832 base::CommandLine::ForCurrentProcess();
833 base::File reader = GetSwitchValueFile(command_line, kSwitchReadFd);
834 base::File parent_writer =
835 GetSwitchValueFile(command_line, kSwitchParentWriteFd);
836
837 // Initialize an `AddressTrackerLinux` in tracking mode and ensure that it
838 // created a netlink socket.
839 AddressTrackerLinux tracker(base::DoNothing(), base::DoNothing(),
840 base::DoNothing(), {});
841 tracker.Init();
842 if (!tracker.DidTrackingInitSucceedForTesting()) {
843 const uint8_t kMessage[] = {kChildFailed};
844 parent_writer.WriteAtCurrentPosAndCheck(kMessage);
845 return 1;
846 }
847
848 // Signal to the parent that we have initialized the tracker.
849 const uint8_t kMessage[] = {kChildInitializedAndWaiting};
850 if (!parent_writer.WriteAtCurrentPosAndCheck(kMessage))
851 return 1;
852
853 // Block until the parent says all children have initialized their trackers.
854 uint8_t message[] = {0};
855 if (!reader.ReadAtCurrentPosAndCheck(message) || message[0] != kChildMayExit)
856 return 1;
857 return 0;
858 }
859
860 #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
861 #endif // defined(CLONE_NEWUSER) && defined(CLONE_NEWPID)
862
863 } // namespace net::internal
864