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  }