apply selinux labels volume patch on volumes refactor

Signed-off-by: Jessica Frazelle <princess@docker.com>
This commit is contained in:
Jessica Frazelle 2015-05-24 18:39:31 -07:00
parent 160dc79db0
commit af7d17a6c9
3 changed files with 86 additions and 41 deletions

View File

@ -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]) { mode := arr[2]
return nil, fmt.Errorf("invalid mode for volumes-from: %s", 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{ return roModes[mode] || rwModes[mode]
"rw": true,
"ro": true,
}
return validModes[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
} }

View File

@ -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 bind string
driver string driver string
expDest string expDest string
expSource string expSource string
expName string expName string
expDriver string expDriver string
expRW bool mountLabel string
fail bool expRW bool
fail bool
}{ }{
{"/tmp:/tmp", "", "/tmp", "/tmp", "", "", true, false}, {"/tmp:/tmp", "", "/tmp", "/tmp", "", "", "", true, false},
{"/tmp:/tmp:ro", "", "/tmp", "/tmp", "", "", false, false}, {"/tmp:/tmp:ro", "", "/tmp", "/tmp", "", "", "", false, false},
{"/tmp:/tmp:rw", "", "/tmp", "/tmp", "", "", true, false}, {"/tmp:/tmp:rw", "", "/tmp", "/tmp", "", "", "", true, false},
{"/tmp:/tmp:foo", "", "/tmp", "/tmp", "", "", false, true}, {"/tmp:/tmp:foo", "", "/tmp", "/tmp", "", "", "", false, true},
{"name:/tmp", "", "/tmp", "", "name", "local", true, false}, {"name:/tmp", "", "/tmp", "", "name", "local", "", true, false},
{"name:/tmp", "external", "/tmp", "", "name", "external", true, false}, {"name:/tmp", "external", "/tmp", "", "name", "external", "", true, false},
{"name:/tmp:ro", "local", "/tmp", "", "name", "local", false, false}, {"name:/tmp:ro", "local", "/tmp", "", "name", "local", "", false, false},
{"local/name:/tmp:rw", "", "/tmp", "", "local/name", "local", true, 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)

View File

@ -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 bind string
expDest string expDest string
expSource string expSource string
expName string expName string
expRW bool mountLabel string
fail bool expRW bool
fail bool
}{ }{
{"/tmp:/tmp", "/tmp", "/tmp", "", true, false}, {"/tmp:/tmp", "/tmp", "/tmp", "", "", true, false},
{"/tmp:/tmp:ro", "/tmp", "/tmp", "", false, false}, {"/tmp:/tmp:ro", "/tmp", "/tmp", "", "", false, false},
{"/tmp:/tmp:rw", "/tmp", "/tmp", "", true, false}, {"/tmp:/tmp:rw", "/tmp", "/tmp", "", "", true, false},
{"/tmp:/tmp:foo", "/tmp", "/tmp", "", false, true}, {"/tmp:/tmp:foo", "/tmp", "/tmp", "", "", false, true},
{"name:/tmp", "", "", "", false, true}, {"name:/tmp", "", "", "", "", false, true},
{"local/name:/tmp:rw", "", "", "", true, 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)