github.com/pwn-term/docker@v0.0.0-20210616085119-6e977cce2565/libnetwork/osl/sandbox_linux_test.go (about) 1 package osl 2 3 import ( 4 "crypto/rand" 5 "encoding/hex" 6 "io" 7 "net" 8 "os" 9 "path/filepath" 10 "runtime" 11 "strings" 12 "syscall" 13 "testing" 14 "time" 15 16 "github.com/docker/libnetwork/testutils" 17 "github.com/docker/libnetwork/types" 18 "github.com/vishvananda/netlink" 19 "github.com/vishvananda/netlink/nl" 20 "github.com/vishvananda/netns" 21 ) 22 23 const ( 24 vethName1 = "wierdlongname1" 25 vethName2 = "wierdlongname2" 26 vethName3 = "wierdlongname3" 27 vethName4 = "wierdlongname4" 28 sboxIfaceName = "containername" 29 ) 30 31 func generateRandomName(prefix string, size int) (string, error) { 32 id := make([]byte, 32) 33 if _, err := io.ReadFull(rand.Reader, id); err != nil { 34 return "", err 35 } 36 return prefix + hex.EncodeToString(id)[:size], nil 37 } 38 39 func newKey(t *testing.T) (string, error) { 40 name, err := generateRandomName("netns", 12) 41 if err != nil { 42 return "", err 43 } 44 45 name = filepath.Join("/tmp", name) 46 if _, err := os.Create(name); err != nil { 47 return "", err 48 } 49 50 // Set the rpmCleanupPeriod to be low to make the test run quicker 51 gpmLock.Lock() 52 gpmCleanupPeriod = 2 * time.Second 53 gpmLock.Unlock() 54 55 return name, nil 56 } 57 58 func newInfo(hnd *netlink.Handle, t *testing.T) (Sandbox, error) { 59 veth := &netlink.Veth{ 60 LinkAttrs: netlink.LinkAttrs{Name: vethName1, TxQLen: 0}, 61 PeerName: vethName2} 62 if err := hnd.LinkAdd(veth); err != nil { 63 return nil, err 64 } 65 66 // Store the sandbox side pipe interface 67 // This is needed for cleanup on DeleteEndpoint() 68 intf1 := &nwIface{} 69 intf1.srcName = vethName2 70 intf1.dstName = sboxIfaceName 71 72 ip4, addr, err := net.ParseCIDR("192.168.1.100/24") 73 if err != nil { 74 return nil, err 75 } 76 intf1.address = addr 77 intf1.address.IP = ip4 78 79 ip6, addrv6, err := net.ParseCIDR("fe80::2/64") 80 if err != nil { 81 return nil, err 82 } 83 intf1.addressIPv6 = addrv6 84 intf1.addressIPv6.IP = ip6 85 86 _, route, err := net.ParseCIDR("192.168.2.1/32") 87 if err != nil { 88 return nil, err 89 } 90 91 intf1.routes = []*net.IPNet{route} 92 93 intf2 := &nwIface{} 94 intf2.srcName = "testbridge" 95 intf2.dstName = sboxIfaceName 96 intf2.bridge = true 97 98 veth = &netlink.Veth{ 99 LinkAttrs: netlink.LinkAttrs{Name: vethName3, TxQLen: 0}, 100 PeerName: vethName4} 101 102 if err := hnd.LinkAdd(veth); err != nil { 103 return nil, err 104 } 105 106 intf3 := &nwIface{} 107 intf3.srcName = vethName4 108 intf3.dstName = sboxIfaceName 109 intf3.master = "testbridge" 110 111 info := &networkNamespace{iFaces: []*nwIface{intf1, intf2, intf3}} 112 113 info.gw = net.ParseIP("192.168.1.1") 114 info.gwv6 = net.ParseIP("fe80::1") 115 116 return info, nil 117 } 118 119 func verifySandbox(t *testing.T, s Sandbox, ifaceSuffixes []string) { 120 _, ok := s.(*networkNamespace) 121 if !ok { 122 t.Fatalf("The sandbox interface returned is not of type networkNamespace") 123 } 124 125 sbNs, err := netns.GetFromPath(s.Key()) 126 if err != nil { 127 t.Fatalf("Failed top open network namespace path %q: %v", s.Key(), err) 128 } 129 defer sbNs.Close() 130 131 nh, err := netlink.NewHandleAt(sbNs) 132 if err != nil { 133 t.Fatal(err) 134 } 135 defer nh.Delete() 136 137 for _, suffix := range ifaceSuffixes { 138 _, err = nh.LinkByName(sboxIfaceName + suffix) 139 if err != nil { 140 t.Fatalf("Could not find the interface %s inside the sandbox: %v", 141 sboxIfaceName+suffix, err) 142 } 143 } 144 } 145 146 func verifyCleanup(t *testing.T, s Sandbox, wait bool) { 147 if wait { 148 time.Sleep(time.Duration(gpmCleanupPeriod * 2)) 149 } 150 151 if _, err := os.Stat(s.Key()); err == nil { 152 if wait { 153 t.Fatalf("The sandbox path %s is not getting cleaned up even after twice the cleanup period", s.Key()) 154 } else { 155 t.Fatalf("The sandbox path %s is not cleaned up after running gc", s.Key()) 156 } 157 } 158 } 159 160 func TestScanStatistics(t *testing.T) { 161 data := 162 "Inter-| Receive | Transmit\n" + 163 " face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed\n" + 164 " eth0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" + 165 " wlan0: 7787685 11141 0 0 0 0 0 0 1681390 7220 0 0 0 0 0 0\n" + 166 " lo: 783782 1853 0 0 0 0 0 0 783782 1853 0 0 0 0 0 0\n" + 167 "lxcbr0: 0 0 0 0 0 0 0 0 9006 61 0 0 0 0 0 0\n" 168 169 i := &types.InterfaceStatistics{} 170 171 if err := scanInterfaceStats(data, "wlan0", i); err != nil { 172 t.Fatal(err) 173 } 174 if i.TxBytes != 1681390 || i.TxPackets != 7220 || i.RxBytes != 7787685 || i.RxPackets != 11141 { 175 t.Fatalf("Error scanning the statistics") 176 } 177 178 if err := scanInterfaceStats(data, "lxcbr0", i); err != nil { 179 t.Fatal(err) 180 } 181 if i.TxBytes != 9006 || i.TxPackets != 61 || i.RxBytes != 0 || i.RxPackets != 0 { 182 t.Fatalf("Error scanning the statistics") 183 } 184 } 185 186 func TestDisableIPv6DAD(t *testing.T) { 187 if testutils.RunningOnCircleCI() { 188 t.Skipf("Skipping as not supported on CIRCLE CI kernel") 189 } 190 191 defer testutils.SetupTestOSContext(t)() 192 193 key, err := newKey(t) 194 if err != nil { 195 t.Fatalf("Failed to obtain a key: %v", err) 196 } 197 198 s, err := NewSandbox(key, true, false) 199 if err != nil { 200 t.Fatalf("Failed to create a new sandbox: %v", err) 201 } 202 runtime.LockOSThread() 203 defer s.Destroy() 204 205 n, ok := s.(*networkNamespace) 206 if !ok { 207 t.Fatal(ok) 208 } 209 nlh := n.nlHandle 210 211 ipv6, _ := types.ParseCIDR("2001:db8::44/64") 212 iface := &nwIface{addressIPv6: ipv6, ns: n, dstName: "sideA"} 213 214 veth := &netlink.Veth{ 215 LinkAttrs: netlink.LinkAttrs{Name: "sideA"}, 216 PeerName: "sideB", 217 } 218 219 err = nlh.LinkAdd(veth) 220 if err != nil { 221 t.Fatal(err) 222 } 223 224 link, err := nlh.LinkByName("sideA") 225 if err != nil { 226 t.Fatal(err) 227 } 228 229 err = setInterfaceIPv6(nlh, link, iface) 230 if err != nil { 231 t.Fatal(err) 232 } 233 234 addrList, err := nlh.AddrList(link, nl.FAMILY_V6) 235 if err != nil { 236 t.Fatal(err) 237 } 238 239 if addrList[0].Flags&syscall.IFA_F_NODAD == 0 { 240 t.Fatalf("Unexpected interface flags: 0x%x. Expected to contain 0x%x", addrList[0].Flags, syscall.IFA_F_NODAD) 241 } 242 } 243 244 func TestSetInterfaceIP(t *testing.T) { 245 defer testutils.SetupTestOSContext(t)() 246 247 key, err := newKey(t) 248 if err != nil { 249 t.Fatalf("Failed to obtain a key: %v", err) 250 } 251 252 s, err := NewSandbox(key, true, false) 253 if err != nil { 254 t.Fatalf("Failed to create a new sandbox: %v", err) 255 } 256 runtime.LockOSThread() 257 defer s.Destroy() 258 259 n, ok := s.(*networkNamespace) 260 if !ok { 261 t.Fatal(ok) 262 } 263 nlh := n.nlHandle 264 265 ipv4, _ := types.ParseCIDR("172.30.0.33/24") 266 ipv6, _ := types.ParseCIDR("2001:db8::44/64") 267 iface := &nwIface{address: ipv4, addressIPv6: ipv6, ns: n, dstName: "sideA"} 268 269 if err := nlh.LinkAdd(&netlink.Veth{ 270 LinkAttrs: netlink.LinkAttrs{Name: "sideA"}, 271 PeerName: "sideB", 272 }); err != nil { 273 t.Fatal(err) 274 } 275 276 linkA, err := nlh.LinkByName("sideA") 277 if err != nil { 278 t.Fatal(err) 279 } 280 281 linkB, err := nlh.LinkByName("sideB") 282 if err != nil { 283 t.Fatal(err) 284 } 285 286 if err := nlh.LinkSetUp(linkA); err != nil { 287 t.Fatal(err) 288 } 289 290 if err := nlh.LinkSetUp(linkB); err != nil { 291 t.Fatal(err) 292 } 293 294 if err := setInterfaceIP(nlh, linkA, iface); err != nil { 295 t.Fatal(err) 296 } 297 298 if err := setInterfaceIPv6(nlh, linkA, iface); err != nil { 299 t.Fatal(err) 300 } 301 302 err = setInterfaceIP(nlh, linkB, iface) 303 if err == nil { 304 t.Fatalf("Expected route conflict error, but succeeded") 305 } 306 if !strings.Contains(err.Error(), "conflicts with existing route") { 307 t.Fatalf("Unexpected error: %v", err) 308 } 309 310 err = setInterfaceIPv6(nlh, linkB, iface) 311 if err == nil { 312 t.Fatalf("Expected route conflict error, but succeeded") 313 } 314 if !strings.Contains(err.Error(), "conflicts with existing route") { 315 t.Fatalf("Unexpected error: %v", err) 316 } 317 } 318 319 func TestLiveRestore(t *testing.T) { 320 321 defer testutils.SetupTestOSContext(t)() 322 323 key, err := newKey(t) 324 if err != nil { 325 t.Fatalf("Failed to obtain a key: %v", err) 326 } 327 328 s, err := NewSandbox(key, true, false) 329 if err != nil { 330 t.Fatalf("Failed to create a new sandbox: %v", err) 331 } 332 runtime.LockOSThread() 333 defer s.Destroy() 334 335 n, ok := s.(*networkNamespace) 336 if !ok { 337 t.Fatal(ok) 338 } 339 nlh := n.nlHandle 340 341 ipv4, _ := types.ParseCIDR("172.30.0.33/24") 342 ipv6, _ := types.ParseCIDR("2001:db8::44/64") 343 iface := &nwIface{address: ipv4, addressIPv6: ipv6, ns: n, dstName: "sideA"} 344 345 if err := nlh.LinkAdd(&netlink.Veth{ 346 LinkAttrs: netlink.LinkAttrs{Name: "sideA"}, 347 PeerName: "sideB", 348 }); err != nil { 349 t.Fatal(err) 350 } 351 352 linkA, err := nlh.LinkByName("sideA") 353 if err != nil { 354 t.Fatal(err) 355 } 356 357 linkB, err := nlh.LinkByName("sideB") 358 if err != nil { 359 t.Fatal(err) 360 } 361 362 if err := nlh.LinkSetUp(linkA); err != nil { 363 t.Fatal(err) 364 } 365 366 if err := nlh.LinkSetUp(linkB); err != nil { 367 t.Fatal(err) 368 } 369 370 if err := setInterfaceIP(nlh, linkA, iface); err != nil { 371 t.Fatal(err) 372 } 373 374 if err := setInterfaceIPv6(nlh, linkA, iface); err != nil { 375 t.Fatal(err) 376 } 377 378 err = setInterfaceIP(nlh, linkB, iface) 379 if err == nil { 380 t.Fatalf("Expected route conflict error, but succeeded") 381 } 382 if !strings.Contains(err.Error(), "conflicts with existing route") { 383 t.Fatalf("Unexpected error: %v", err) 384 } 385 386 err = setInterfaceIPv6(nlh, linkB, iface) 387 if err == nil { 388 t.Fatalf("Expected route conflict error, but succeeded") 389 } 390 if !strings.Contains(err.Error(), "conflicts with existing route") { 391 t.Fatalf("Unexpected error: %v", err) 392 } 393 394 // Create newsandbox with Restore - TRUE 395 s, err = NewSandbox(key, true, true) 396 if err != nil { 397 t.Fatalf("Failed to create a new sandbox: %v", err) 398 } 399 400 // Check if the IPV4 & IPV6 entry present 401 // If present , we should get error in below call 402 // It shows us , we don't delete any config in live-restore case 403 if err := setInterfaceIPv6(nlh, linkA, iface); err == nil { 404 t.Fatalf("Expected route conflict error, but succeeded for IPV6 ") 405 } 406 if err := setInterfaceIP(nlh, linkA, iface); err == nil { 407 t.Fatalf("Expected route conflict error, but succeeded for IPV4 ") 408 } 409 }