Преглед изворни кода

Mount (accessible) host devices in --privileged rootless containers

Signed-off-by: Elias Koromilas <elias.koromilas@gmail.com>
Elias Koromilas пре 3 година
родитељ
комит
8c7ea316d1
2 измењених фајлова са 56 додато и 1 уклоњено
  1. 1 1
      daemon/oci_linux.go
  2. 55 0
      integration/container/run_linux_test.go

+ 1 - 1
daemon/oci_linux.go

@@ -862,7 +862,7 @@ func WithDevices(daemon *Daemon, c *container.Container) coci.SpecOpts {
 		var devs []specs.LinuxDevice
 		devPermissions := s.Linux.Resources.Devices
 
-		if c.HostConfig.Privileged && !userns.RunningInUserNS() {
+		if c.HostConfig.Privileged {
 			hostDevices, err := coci.HostDevices()
 			if err != nil {
 				return err

+ 55 - 0
integration/container/run_linux_test.go

@@ -2,6 +2,8 @@ package container // import "github.com/docker/docker/integration/container"
 
 import (
 	"context"
+	"os"
+	"path/filepath"
 	"strings"
 	"testing"
 	"time"
@@ -10,6 +12,8 @@ import (
 	"github.com/docker/docker/api/types/versions"
 	"github.com/docker/docker/integration/internal/container"
 	net "github.com/docker/docker/integration/internal/network"
+	"github.com/docker/docker/pkg/system"
+	"golang.org/x/sys/unix"
 	"gotest.tools/v3/assert"
 	is "gotest.tools/v3/assert/cmp"
 	"gotest.tools/v3/poll"
@@ -128,3 +132,54 @@ func TestUnprivilegedPortsAndPing(t *testing.T) {
 	assert.Equal(t, 0, res.ExitCode)
 	assert.Equal(t, "0", strings.TrimSpace(res.Stdout()))
 }
+
+func TestPrivilegedHostDevices(t *testing.T) {
+	// Host devices are linux only. Also it creates host devices,
+	// so needs to be same host.
+	skip.If(t, testEnv.IsRemoteDaemon)
+	skip.If(t, testEnv.DaemonInfo.OSType != "linux")
+
+	defer setupTest(t)()
+	client := testEnv.APIClient()
+	ctx := context.Background()
+
+	const (
+		devTest         = "/dev/test"
+		devRootOnlyTest = "/dev/root-only/test"
+	)
+
+	// Create Null devices.
+	if err := system.Mknod(devTest, unix.S_IFCHR|0600, int(system.Mkdev(1, 3))); err != nil {
+		t.Fatal(err)
+	}
+	defer os.Remove(devTest)
+	if err := os.Mkdir(filepath.Dir(devRootOnlyTest), 0700); err != nil {
+		t.Fatal(err)
+	}
+	defer os.RemoveAll(filepath.Dir(devRootOnlyTest))
+	if err := system.Mknod(devRootOnlyTest, unix.S_IFCHR|0600, int(system.Mkdev(1, 3))); err != nil {
+		t.Fatal(err)
+	}
+	defer os.Remove(devRootOnlyTest)
+
+	cID := container.Run(ctx, t, client, container.WithPrivileged(true))
+
+	poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))
+
+	// Check test device.
+	res, err := container.Exec(ctx, client, cID, []string{"ls", devTest})
+	assert.NilError(t, err)
+	assert.Equal(t, 0, res.ExitCode)
+	assert.Check(t, is.Equal(strings.TrimSpace(res.Stdout()), devTest))
+
+	// Check root-only test device.
+	res, err = container.Exec(ctx, client, cID, []string{"ls", devRootOnlyTest})
+	assert.NilError(t, err)
+	if testEnv.IsRootless() {
+		assert.Equal(t, 1, res.ExitCode)
+		assert.Check(t, is.Contains(res.Stderr(), "No such file or directory"))
+	} else {
+		assert.Equal(t, 0, res.ExitCode)
+		assert.Check(t, is.Equal(strings.TrimSpace(res.Stdout()), devRootOnlyTest))
+	}
+}