github.com/lacework-dev/go-moby@v20.10.12+incompatible/daemon/oci_linux_test.go (about)

     1  package daemon // import "github.com/docker/docker/daemon"
     2  
     3  import (
     4  	"io/ioutil"
     5  	"os"
     6  	"path/filepath"
     7  	"testing"
     8  
     9  	containertypes "github.com/docker/docker/api/types/container"
    10  	"github.com/docker/docker/container"
    11  	"github.com/docker/docker/daemon/config"
    12  	"github.com/docker/docker/daemon/network"
    13  	"github.com/docker/docker/pkg/containerfs"
    14  	"github.com/docker/docker/pkg/idtools"
    15  	"github.com/docker/libnetwork"
    16  	"gotest.tools/v3/assert"
    17  	is "gotest.tools/v3/assert/cmp"
    18  	"gotest.tools/v3/skip"
    19  )
    20  
    21  func setupFakeDaemon(t *testing.T, c *container.Container) *Daemon {
    22  	root, err := ioutil.TempDir("", "oci_linux_test-root")
    23  	assert.NilError(t, err)
    24  
    25  	rootfs := filepath.Join(root, "rootfs")
    26  	err = os.MkdirAll(rootfs, 0755)
    27  	assert.NilError(t, err)
    28  
    29  	netController, err := libnetwork.New()
    30  	assert.NilError(t, err)
    31  
    32  	d := &Daemon{
    33  		// some empty structs to avoid getting a panic
    34  		// caused by a null pointer dereference
    35  		idMapping:     &idtools.IdentityMapping{},
    36  		configStore:   &config.Config{},
    37  		linkIndex:     newLinkIndex(),
    38  		netController: netController,
    39  	}
    40  
    41  	c.Root = root
    42  	c.BaseFS = containerfs.NewLocalContainerFS(rootfs)
    43  
    44  	if c.Config == nil {
    45  		c.Config = new(containertypes.Config)
    46  	}
    47  	if c.HostConfig == nil {
    48  		c.HostConfig = new(containertypes.HostConfig)
    49  	}
    50  	if c.NetworkSettings == nil {
    51  		c.NetworkSettings = &network.Settings{Networks: make(map[string]*network.EndpointSettings)}
    52  	}
    53  
    54  	return d
    55  }
    56  
    57  func cleanupFakeContainer(c *container.Container) {
    58  	_ = os.RemoveAll(c.Root)
    59  }
    60  
    61  // TestTmpfsDevShmNoDupMount checks that a user-specified /dev/shm tmpfs
    62  // mount (as in "docker run --tmpfs /dev/shm:rw,size=NNN") does not result
    63  // in "Duplicate mount point" error from the engine.
    64  // https://github.com/moby/moby/issues/35455
    65  func TestTmpfsDevShmNoDupMount(t *testing.T) {
    66  	skip.If(t, os.Getuid() != 0, "skipping test that requires root")
    67  	c := &container.Container{
    68  		ShmPath: "foobar", // non-empty, for c.IpcMounts() to work
    69  		HostConfig: &containertypes.HostConfig{
    70  			IpcMode: containertypes.IpcMode("shareable"), // default mode
    71  			// --tmpfs /dev/shm:rw,exec,size=NNN
    72  			Tmpfs: map[string]string{
    73  				"/dev/shm": "rw,exec,size=1g",
    74  			},
    75  		},
    76  	}
    77  	d := setupFakeDaemon(t, c)
    78  	defer cleanupFakeContainer(c)
    79  
    80  	_, err := d.createSpec(c)
    81  	assert.Check(t, err)
    82  }
    83  
    84  // TestIpcPrivateVsReadonly checks that in case of IpcMode: private
    85  // and ReadonlyRootfs: true (as in "docker run --ipc private --read-only")
    86  // the resulting /dev/shm mount is NOT made read-only.
    87  // https://github.com/moby/moby/issues/36503
    88  func TestIpcPrivateVsReadonly(t *testing.T) {
    89  	skip.If(t, os.Getuid() != 0, "skipping test that requires root")
    90  	c := &container.Container{
    91  		HostConfig: &containertypes.HostConfig{
    92  			IpcMode:        containertypes.IpcMode("private"),
    93  			ReadonlyRootfs: true,
    94  		},
    95  	}
    96  	d := setupFakeDaemon(t, c)
    97  	defer cleanupFakeContainer(c)
    98  
    99  	s, err := d.createSpec(c)
   100  	assert.Check(t, err)
   101  
   102  	// Find the /dev/shm mount in ms, check it does not have ro
   103  	for _, m := range s.Mounts {
   104  		if m.Destination != "/dev/shm" {
   105  			continue
   106  		}
   107  		assert.Check(t, is.Equal(false, inSlice(m.Options, "ro")))
   108  	}
   109  }
   110  
   111  // TestSysctlOverride ensures that any implicit sysctls (such as
   112  // Config.Domainname) are overridden by an explicit sysctl in the HostConfig.
   113  func TestSysctlOverride(t *testing.T) {
   114  	skip.If(t, os.Getuid() != 0, "skipping test that requires root")
   115  	c := &container.Container{
   116  		Config: &containertypes.Config{
   117  			Hostname:   "foobar",
   118  			Domainname: "baz.cyphar.com",
   119  		},
   120  		HostConfig: &containertypes.HostConfig{
   121  			NetworkMode: "bridge",
   122  			Sysctls:     map[string]string{},
   123  			UsernsMode:  "host",
   124  		},
   125  	}
   126  	d := setupFakeDaemon(t, c)
   127  	defer cleanupFakeContainer(c)
   128  
   129  	// Ensure that the implicit sysctl is set correctly.
   130  	s, err := d.createSpec(c)
   131  	assert.NilError(t, err)
   132  	assert.Equal(t, s.Hostname, "foobar")
   133  	assert.Equal(t, s.Linux.Sysctl["kernel.domainname"], c.Config.Domainname)
   134  	if sysctlExists("net.ipv4.ip_unprivileged_port_start") {
   135  		assert.Equal(t, s.Linux.Sysctl["net.ipv4.ip_unprivileged_port_start"], "0")
   136  	}
   137  	if sysctlExists("net.ipv4.ping_group_range") {
   138  		assert.Equal(t, s.Linux.Sysctl["net.ipv4.ping_group_range"], "0 2147483647")
   139  	}
   140  
   141  	// Set an explicit sysctl.
   142  	c.HostConfig.Sysctls["kernel.domainname"] = "foobar.net"
   143  	assert.Assert(t, c.HostConfig.Sysctls["kernel.domainname"] != c.Config.Domainname)
   144  	c.HostConfig.Sysctls["net.ipv4.ip_unprivileged_port_start"] = "1024"
   145  
   146  	s, err = d.createSpec(c)
   147  	assert.NilError(t, err)
   148  	assert.Equal(t, s.Hostname, "foobar")
   149  	assert.Equal(t, s.Linux.Sysctl["kernel.domainname"], c.HostConfig.Sysctls["kernel.domainname"])
   150  	assert.Equal(t, s.Linux.Sysctl["net.ipv4.ip_unprivileged_port_start"], c.HostConfig.Sysctls["net.ipv4.ip_unprivileged_port_start"])
   151  }
   152  
   153  // TestSysctlOverrideHost ensures that any implicit network sysctls are not set
   154  // with host networking
   155  func TestSysctlOverrideHost(t *testing.T) {
   156  	skip.If(t, os.Getuid() != 0, "skipping test that requires root")
   157  	c := &container.Container{
   158  		Config: &containertypes.Config{},
   159  		HostConfig: &containertypes.HostConfig{
   160  			NetworkMode: "host",
   161  			Sysctls:     map[string]string{},
   162  			UsernsMode:  "host",
   163  		},
   164  	}
   165  	d := setupFakeDaemon(t, c)
   166  	defer cleanupFakeContainer(c)
   167  
   168  	// Ensure that the implicit sysctl is not set
   169  	s, err := d.createSpec(c)
   170  	assert.NilError(t, err)
   171  	assert.Equal(t, s.Linux.Sysctl["net.ipv4.ip_unprivileged_port_start"], "")
   172  	assert.Equal(t, s.Linux.Sysctl["net.ipv4.ping_group_range"], "")
   173  
   174  	// Set an explicit sysctl.
   175  	c.HostConfig.Sysctls["net.ipv4.ip_unprivileged_port_start"] = "1024"
   176  
   177  	s, err = d.createSpec(c)
   178  	assert.NilError(t, err)
   179  	assert.Equal(t, s.Linux.Sysctl["net.ipv4.ip_unprivileged_port_start"], c.HostConfig.Sysctls["net.ipv4.ip_unprivileged_port_start"])
   180  }
   181  
   182  func TestGetSourceMount(t *testing.T) {
   183  	// must be able to find source mount for /
   184  	mnt, _, err := getSourceMount("/")
   185  	assert.NilError(t, err)
   186  	assert.Equal(t, mnt, "/")
   187  
   188  	// must be able to find source mount for current directory
   189  	cwd, err := os.Getwd()
   190  	assert.NilError(t, err)
   191  	_, _, err = getSourceMount(cwd)
   192  	assert.NilError(t, err)
   193  }