Explorar el Código

apply selinux labels volume patch on volumes refactor

Signed-off-by: Jessica Frazelle <princess@docker.com>
Jessica Frazelle hace 10 años
padre
commit
af7d17a6c9
Se han modificado 3 ficheros con 86 adiciones y 41 borrados
  1. 54 11
      daemon/volumes.go
  2. 18 17
      daemon/volumes_experimental_unit_test.go
  3. 14 13
      daemon/volumes_stubs_unit_test.go

+ 54 - 11
daemon/volumes.go

@@ -6,11 +6,14 @@ import (
 	"io/ioutil"
 	"io/ioutil"
 	"os"
 	"os"
 	"path/filepath"
 	"path/filepath"
+	"runtime"
 	"strings"
 	"strings"
 
 
+	"github.com/Sirupsen/logrus"
 	"github.com/docker/docker/pkg/chrootarchive"
 	"github.com/docker/docker/pkg/chrootarchive"
 	"github.com/docker/docker/runconfig"
 	"github.com/docker/docker/runconfig"
 	"github.com/docker/docker/volume"
 	"github.com/docker/docker/volume"
+	"github.com/docker/libcontainer/label"
 )
 )
 
 
 type mountPoint struct {
 type mountPoint struct {
@@ -50,7 +53,7 @@ func (m *mountPoint) Path() string {
 	return m.Source
 	return m.Source
 }
 }
 
 
-func parseBindMount(spec string, config *runconfig.Config) (*mountPoint, error) {
+func parseBindMount(spec string, mountLabel string, config *runconfig.Config) (*mountPoint, error) {
 	bind := &mountPoint{
 	bind := &mountPoint{
 		RW: true,
 		RW: true,
 	}
 	}
@@ -61,10 +64,17 @@ func parseBindMount(spec string, config *runconfig.Config) (*mountPoint, error)
 		bind.Destination = arr[1]
 		bind.Destination = arr[1]
 	case 3:
 	case 3:
 		bind.Destination = arr[1]
 		bind.Destination = arr[1]
-		if !validMountMode(arr[2]) {
-			return nil, fmt.Errorf("invalid mode for volumes-from: %s", arr[2])
+		mode := arr[2]
+		if !validMountMode(mode) {
+			return nil, fmt.Errorf("invalid mode for volumes-from: %s", mode)
+		}
+		bind.RW = rwModes[mode]
+		// check if we need to apply a SELinux label
+		if strings.ContainsAny(mode, "zZ") {
+			if err := label.Relabel(bind.Source, mountLabel, mode); err != nil {
+				return nil, err
+			}
 		}
 		}
-		bind.RW = arr[2] == "rw"
 	default:
 	default:
 		return nil, fmt.Errorf("Invalid volume specification: %s", spec)
 		return nil, fmt.Errorf("Invalid volume specification: %s", spec)
 	}
 	}
@@ -106,12 +116,28 @@ func parseVolumesFrom(spec string) (string, string, error) {
 	return id, mode, nil
 	return id, mode, nil
 }
 }
 
 
+// read-write modes
+var rwModes = map[string]bool{
+	"rw":   true,
+	"rw,Z": true,
+	"rw,z": true,
+	"z,rw": true,
+	"Z,rw": true,
+	"Z":    true,
+	"z":    true,
+}
+
+// read-only modes
+var roModes = map[string]bool{
+	"ro":   true,
+	"ro,Z": true,
+	"ro,z": true,
+	"z,ro": true,
+	"Z,ro": true,
+}
+
 func validMountMode(mode string) bool {
 func validMountMode(mode string) bool {
-	validModes := map[string]bool{
-		"rw": true,
-		"ro": true,
-	}
-	return validModes[mode]
+	return roModes[mode] || rwModes[mode]
 }
 }
 
 
 func copyExistingContents(source, destination string) error {
 func copyExistingContents(source, destination string) error {
@@ -177,10 +203,13 @@ func (daemon *Daemon) registerMountPoints(container *Container, hostConfig *runc
 		}
 		}
 	}
 	}
 
 
+	// lock for labels
+	runtime.LockOSThread()
+	defer runtime.UnlockOSThread()
 	// 3. Read bind mounts
 	// 3. Read bind mounts
 	for _, b := range hostConfig.Binds {
 	for _, b := range hostConfig.Binds {
 		// #10618
 		// #10618
-		bind, err := parseBindMount(b, container.Config)
+		bind, err := parseBindMount(b, container.MountLabel, container.Config)
 		if err != nil {
 		if err != nil {
 			return err
 			return err
 		}
 		}
@@ -190,11 +219,26 @@ func (daemon *Daemon) registerMountPoints(container *Container, hostConfig *runc
 		}
 		}
 
 
 		if len(bind.Name) > 0 && len(bind.Driver) > 0 {
 		if len(bind.Name) > 0 && len(bind.Driver) > 0 {
+			// set the label
+			if err := label.SetFileCreateLabel(container.MountLabel); err != nil {
+				return fmt.Errorf("Unable to setup default labeling for volume creation %s: %v", bind.Source, err)
+			}
+
+			// create the volume
 			v, err := createVolume(bind.Name, bind.Driver)
 			v, err := createVolume(bind.Name, bind.Driver)
 			if err != nil {
 			if err != nil {
+				// reset the label
+				if e := label.SetFileCreateLabel(""); e != nil {
+					logrus.Errorf("Unable to reset labeling for volume creation %s: %v", bind.Source, e)
+				}
 				return err
 				return err
 			}
 			}
 			bind.Volume = v
 			bind.Volume = v
+
+			// reset the label
+			if err := label.SetFileCreateLabel(""); err != nil {
+				return fmt.Errorf("Unable to reset labeling for volume creation %s: %v", bind.Source, err)
+			}
 		}
 		}
 
 
 		binds[bind.Destination] = true
 		binds[bind.Destination] = true
@@ -250,7 +294,6 @@ func (daemon *Daemon) verifyOldVolumesInfo(container *Container) error {
 
 
 func createVolume(name, driverName string) (volume.Volume, error) {
 func createVolume(name, driverName string) (volume.Volume, error) {
 	vd, err := getVolumeDriver(driverName)
 	vd, err := getVolumeDriver(driverName)
-
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}

+ 18 - 17
daemon/volumes_experimental_unit_test.go

@@ -34,28 +34,29 @@ func TestGetVolumeDriver(t *testing.T) {
 
 
 func TestParseBindMount(t *testing.T) {
 func TestParseBindMount(t *testing.T) {
 	cases := []struct {
 	cases := []struct {
-		bind      string
-		driver    string
-		expDest   string
-		expSource string
-		expName   string
-		expDriver string
-		expRW     bool
-		fail      bool
+		bind       string
+		driver     string
+		expDest    string
+		expSource  string
+		expName    string
+		expDriver  string
+		mountLabel string
+		expRW      bool
+		fail       bool
 	}{
 	}{
-		{"/tmp:/tmp", "", "/tmp", "/tmp", "", "", true, false},
-		{"/tmp:/tmp:ro", "", "/tmp", "/tmp", "", "", false, false},
-		{"/tmp:/tmp:rw", "", "/tmp", "/tmp", "", "", true, false},
-		{"/tmp:/tmp:foo", "", "/tmp", "/tmp", "", "", false, true},
-		{"name:/tmp", "", "/tmp", "", "name", "local", true, false},
-		{"name:/tmp", "external", "/tmp", "", "name", "external", true, false},
-		{"name:/tmp:ro", "local", "/tmp", "", "name", "local", false, false},
-		{"local/name:/tmp:rw", "", "/tmp", "", "local/name", "local", true, false},
+		{"/tmp:/tmp", "", "/tmp", "/tmp", "", "", "", true, false},
+		{"/tmp:/tmp:ro", "", "/tmp", "/tmp", "", "", "", false, false},
+		{"/tmp:/tmp:rw", "", "/tmp", "/tmp", "", "", "", true, false},
+		{"/tmp:/tmp:foo", "", "/tmp", "/tmp", "", "", "", false, true},
+		{"name:/tmp", "", "/tmp", "", "name", "local", "", true, false},
+		{"name:/tmp", "external", "/tmp", "", "name", "external", "", true, false},
+		{"name:/tmp:ro", "local", "/tmp", "", "name", "local", "", false, false},
+		{"local/name:/tmp:rw", "", "/tmp", "", "local/name", "local", "", true, false},
 	}
 	}
 
 
 	for _, c := range cases {
 	for _, c := range cases {
 		conf := &runconfig.Config{VolumeDriver: c.driver}
 		conf := &runconfig.Config{VolumeDriver: c.driver}
-		m, err := parseBindMount(c.bind, conf)
+		m, err := parseBindMount(c.bind, c.mountLabel, conf)
 		if c.fail {
 		if c.fail {
 			if err == nil {
 			if err == nil {
 				t.Fatalf("Expected error, was nil, for spec %s\n", c.bind)
 				t.Fatalf("Expected error, was nil, for spec %s\n", c.bind)

+ 14 - 13
daemon/volumes_stubs_unit_test.go

@@ -37,24 +37,25 @@ func TestGetVolumeDefaultDriver(t *testing.T) {
 
 
 func TestParseBindMount(t *testing.T) {
 func TestParseBindMount(t *testing.T) {
 	cases := []struct {
 	cases := []struct {
-		bind      string
-		expDest   string
-		expSource string
-		expName   string
-		expRW     bool
-		fail      bool
+		bind       string
+		expDest    string
+		expSource  string
+		expName    string
+		mountLabel string
+		expRW      bool
+		fail       bool
 	}{
 	}{
-		{"/tmp:/tmp", "/tmp", "/tmp", "", true, false},
-		{"/tmp:/tmp:ro", "/tmp", "/tmp", "", false, false},
-		{"/tmp:/tmp:rw", "/tmp", "/tmp", "", true, false},
-		{"/tmp:/tmp:foo", "/tmp", "/tmp", "", false, true},
-		{"name:/tmp", "", "", "", false, true},
-		{"local/name:/tmp:rw", "", "", "", true, true},
+		{"/tmp:/tmp", "/tmp", "/tmp", "", "", true, false},
+		{"/tmp:/tmp:ro", "/tmp", "/tmp", "", "", false, false},
+		{"/tmp:/tmp:rw", "/tmp", "/tmp", "", "", true, false},
+		{"/tmp:/tmp:foo", "/tmp", "/tmp", "", "", false, true},
+		{"name:/tmp", "", "", "", "", false, true},
+		{"local/name:/tmp:rw", "", "", "", "", true, true},
 	}
 	}
 
 
 	for _, c := range cases {
 	for _, c := range cases {
 		conf := &runconfig.Config{}
 		conf := &runconfig.Config{}
-		m, err := parseBindMount(c.bind, conf)
+		m, err := parseBindMount(c.bind, c.mountLabel, conf)
 		if c.fail {
 		if c.fail {
 			if err == nil {
 			if err == nil {
 				t.Fatalf("Expected error, was nil, for spec %s\n", c.bind)
 				t.Fatalf("Expected error, was nil, for spec %s\n", c.bind)