From ba1c57030f10ece60678a848e04375e4cd2c843d Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Thu, 29 Aug 2019 22:47:15 +0200 Subject: rootless: bind mount devices instead of creating them when running in rootless mode, --device creates a bind mount from the host instead of specifying the device in the OCI configuration. This is required as an unprivileged user cannot use mknod, even when root in a user namespace. Closes: https://github.com/containers/libpod/issues/3905 Signed-off-by: Giuseppe Scrivano --- pkg/spec/config_linux.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'pkg/spec/config_linux.go') diff --git a/pkg/spec/config_linux.go b/pkg/spec/config_linux.go index 60d31d78e..dea9b393c 100644 --- a/pkg/spec/config_linux.go +++ b/pkg/spec/config_linux.go @@ -98,6 +98,26 @@ func addDevice(g *generate.Generator, device string) error { if err != nil { return errors.Wrapf(err, "%s is not a valid device", src) } + if rootless.IsRootless() { + if _, err := os.Stat(src); err != nil { + if os.IsNotExist(err) { + return errors.Wrapf(err, "the specified device %s doesn't exist", src) + } + return errors.Wrapf(err, "stat device %s exist", src) + } + perm := "ro" + if strings.Contains(permissions, "w") { + perm = "rw" + } + devMnt := spec.Mount{ + Destination: dst, + Type: TypeBind, + Source: src, + Options: []string{"slave", "nosuid", "noexec", perm, "rbind"}, + } + g.Config.Mounts = append(g.Config.Mounts, devMnt) + return nil + } dev.Path = dst linuxdev := spec.LinuxDevice{ Path: dev.Path, -- cgit v1.2.3-54-g00ecf From b101a8d3664f054157a9e3f08a6bf8db0144041c Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Sun, 1 Sep 2019 00:30:55 +0200 Subject: spec: do not set devices cgroup when rootless eBPF requires to be root in the init namespace. Signed-off-by: Giuseppe Scrivano --- pkg/spec/config_linux.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'pkg/spec/config_linux.go') diff --git a/pkg/spec/config_linux.go b/pkg/spec/config_linux.go index dea9b393c..9636d7a11 100644 --- a/pkg/spec/config_linux.go +++ b/pkg/spec/config_linux.go @@ -173,15 +173,16 @@ func (c *CreateConfig) addPrivilegedDevices(g *generate.Generator) error { newMounts = append(newMounts, devMnt) } g.Config.Mounts = append(newMounts, g.Config.Mounts...) + g.Config.Linux.Resources.Devices = nil } else { for _, d := range hostDevices { g.AddDevice(Device(d)) } + // Add resources device - need to clear the existing one first. + g.Config.Linux.Resources.Devices = nil + g.AddLinuxResourcesDevice(true, "", nil, nil, "rwm") } - // Add resources device - need to clear the existing one first. - g.Config.Linux.Resources.Devices = nil - g.AddLinuxResourcesDevice(true, "", nil, nil, "rwm") return nil } -- cgit v1.2.3-54-g00ecf From 759ca2cfc66c372dd197b4a2b6cf2b454b497d00 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Sun, 1 Sep 2019 00:27:29 +0200 Subject: spec: provide custom implementation for getDevices provide an implementation for getDevices that skip unreadable directories for the current user. Based on the implementation from runc/libcontainer. Closes: https://github.com/containers/libpod/issues/3919 Signed-off-by: Giuseppe Scrivano Signed-off-by: Giuseppe Scrivano --- pkg/spec/config_linux.go | 48 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) (limited to 'pkg/spec/config_linux.go') diff --git a/pkg/spec/config_linux.go b/pkg/spec/config_linux.go index 9636d7a11..32d8cb4de 100644 --- a/pkg/spec/config_linux.go +++ b/pkg/spec/config_linux.go @@ -4,6 +4,7 @@ package createconfig import ( "fmt" + "io/ioutil" "os" "path/filepath" "strings" @@ -133,8 +134,53 @@ func addDevice(g *generate.Generator, device string) error { return nil } +// based on getDevices from runc (libcontainer/devices/devices.go) +func getDevices(path string) ([]*configs.Device, error) { + files, err := ioutil.ReadDir(path) + if err != nil { + if rootless.IsRootless() && os.IsPermission(err) { + return nil, nil + } + return nil, err + } + out := []*configs.Device{} + for _, f := range files { + switch { + case f.IsDir(): + switch f.Name() { + // ".lxc" & ".lxd-mounts" added to address https://github.com/lxc/lxd/issues/2825 + case "pts", "shm", "fd", "mqueue", ".lxc", ".lxd-mounts": + continue + default: + sub, err := getDevices(filepath.Join(path, f.Name())) + if err != nil { + return nil, err + } + if sub != nil { + out = append(out, sub...) + } + continue + } + case f.Name() == "console": + continue + } + device, err := devices.DeviceFromPath(filepath.Join(path, f.Name()), "rwm") + if err != nil { + if err == devices.ErrNotADevice { + continue + } + if os.IsNotExist(err) { + continue + } + return nil, err + } + out = append(out, device) + } + return out, nil +} + func (c *CreateConfig) addPrivilegedDevices(g *generate.Generator) error { - hostDevices, err := devices.HostDevices() + hostDevices, err := getDevices("/dev") if err != nil { return err } -- cgit v1.2.3-54-g00ecf