From 350ede1eeb6ab33bce2918d7768b940c255e63c6 Mon Sep 17 00:00:00 2001
From: Giuseppe Scrivano <gscrivan@redhat.com>
Date: Thu, 18 Jul 2019 11:38:54 +0200
Subject: rootless: add rw devices with --privileged

when --privileged is specified, add all the devices that are usable by
the user.

Closes: https://bugzilla.redhat.com/show_bug.cgi?id=1730773

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
---
 pkg/spec/config_linux.go | 41 +++++++++++++++++++++++++++++++++++++++--
 pkg/spec/spec.go         |  6 ++----
 2 files changed, 41 insertions(+), 6 deletions(-)

(limited to 'pkg/spec')

diff --git a/pkg/spec/config_linux.go b/pkg/spec/config_linux.go
index 9f6a4a058..a84e9a72f 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 41054633f..0f785df01 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 {
-- 
cgit v1.2.3-54-g00ecf