diff --git a/pkg/spec/config_linux.go b/pkg/spec/config_linux.go index 9f6a4a058f..a84e9a72fb 100644 --- a/pkg/spec/config_linux.go +++ b/pkg/spec/config_linux.go @@ -8,6 +8,7 @@ import ( "path/filepath" "strings" + "github.com/containers/libpod/pkg/rootless" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/devices" spec "github.com/opencontainers/runtime-spec/specs-go" @@ -118,8 +119,44 @@ func (c *CreateConfig) addPrivilegedDevices(g *generate.Generator) error { return err } g.ClearLinuxDevices() - for _, d := range hostDevices { - g.AddDevice(Device(d)) + + if rootless.IsRootless() { + mounts := make(map[string]interface{}) + for _, m := range g.Mounts() { + mounts[m.Destination] = true + } + newMounts := []spec.Mount{} + for _, d := range hostDevices { + devMnt := spec.Mount{ + Destination: d.Path, + Type: TypeBind, + Source: d.Path, + Options: []string{"slave", "nosuid", "noexec", "rw", "rbind"}, + } + if d.Path == "/dev/ptmx" || strings.HasPrefix(d.Path, "/dev/tty") { + continue + } + if _, found := mounts[d.Path]; found { + continue + } + st, err := os.Stat(d.Path) + if err != nil { + if err == unix.EPERM { + continue + } + return errors.Wrapf(err, "stat %s", d.Path) + } + // Skip devices that the user has not access to. + if st.Mode()&0007 == 0 { + continue + } + newMounts = append(newMounts, devMnt) + } + g.Config.Mounts = append(newMounts, g.Config.Mounts...) + } else { + for _, d := range hostDevices { + g.AddDevice(Device(d)) + } } // Add resources device - need to clear the existing one first. diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go index 41054633fa..0f785df011 100644 --- a/pkg/spec/spec.go +++ b/pkg/spec/spec.go @@ -264,10 +264,8 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM // If privileged, we need to add all the host devices to the // spec. We do not add the user provided ones because we are // already adding them all. - if !rootless.IsRootless() { - if err := config.AddPrivilegedDevices(&g); err != nil { - return nil, err - } + if err := config.AddPrivilegedDevices(&g); err != nil { + return nil, err } } else { for _, devicePath := range config.Devices { diff --git a/test/e2e/run_device_test.go b/test/e2e/run_device_test.go index 2e537a9f9f..cf7ce9cdf3 100644 --- a/test/e2e/run_device_test.go +++ b/test/e2e/run_device_test.go @@ -85,4 +85,13 @@ var _ = Describe("Podman run device", func() { session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) }) + + It("podman run device host device with --privileged", func() { + if _, err := os.Stat("/dev/kvm"); err != nil { + Skip("/dev/kvm not available") + } + session := podmanTest.Podman([]string{"run", "--privileged", ALPINE, "ls", "/dev/kvm"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + }) })