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
} }
func validMountMode(mode string) bool { // read-write modes
validModes := map[string]bool{ var rwModes = map[string]bool{
"rw": true, "rw": true,
"ro": true, "rw,Z": true,
"rw,z": true,
"z,rw": true,
"Z,rw": true,
"Z": true,
"z": true,
} }
return validModes[mode]
// 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 {
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
} }

View File

@ -40,22 +40,23 @@ func TestParseBindMount(t *testing.T) {
expSource string expSource string
expName string expName string
expDriver string expDriver string
mountLabel string
expRW bool expRW bool
fail 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

@ -41,20 +41,21 @@ func TestParseBindMount(t *testing.T) {
expDest string expDest string
expSource string expSource string
expName string expName string
mountLabel string
expRW bool expRW bool
fail 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)