github.com/adityamillind98/moby@v23.0.0-rc.4+incompatible/daemon/oci_linux_test.go (about)

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