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"
"os"
"path/filepath"
"runtime"
"strings"
"github.com/Sirupsen/logrus"
"github.com/docker/docker/pkg/chrootarchive"
"github.com/docker/docker/runconfig"
"github.com/docker/docker/volume"
"github.com/docker/libcontainer/label"
)
type mountPoint struct {
@ -50,7 +53,7 @@ func (m *mountPoint) Path() string {
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{
RW: true,
}
@ -61,10 +64,17 @@ func parseBindMount(spec string, config *runconfig.Config) (*mountPoint, error)
bind.Destination = arr[1]
case 3:
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:
return nil, fmt.Errorf("Invalid volume specification: %s", spec)
}
@ -106,12 +116,28 @@ func parseVolumesFrom(spec string) (string, string, error) {
return id, mode, nil
}
func validMountMode(mode string) bool {
validModes := map[string]bool{
// read-write modes
var rwModes = map[string]bool{
"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 {
@ -177,10 +203,13 @@ func (daemon *Daemon) registerMountPoints(container *Container, hostConfig *runc
}
}
// lock for labels
runtime.LockOSThread()
defer runtime.UnlockOSThread()
// 3. Read bind mounts
for _, b := range hostConfig.Binds {
// #10618
bind, err := parseBindMount(b, container.Config)
bind, err := parseBindMount(b, container.MountLabel, container.Config)
if err != nil {
return err
}
@ -190,11 +219,26 @@ func (daemon *Daemon) registerMountPoints(container *Container, hostConfig *runc
}
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)
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
}
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
@ -250,7 +294,6 @@ func (daemon *Daemon) verifyOldVolumesInfo(container *Container) error {
func createVolume(name, driverName string) (volume.Volume, error) {
vd, err := getVolumeDriver(driverName)
if err != nil {
return nil, err
}

View File

@ -40,22 +40,23 @@ func TestParseBindMount(t *testing.T) {
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 {
conf := &runconfig.Config{VolumeDriver: c.driver}
m, err := parseBindMount(c.bind, conf)
m, err := parseBindMount(c.bind, c.mountLabel, conf)
if c.fail {
if err == nil {
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
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 {
conf := &runconfig.Config{}
m, err := parseBindMount(c.bind, conf)
m, err := parseBindMount(c.bind, c.mountLabel, conf)
if c.fail {
if err == nil {
t.Fatalf("Expected error, was nil, for spec %s\n", c.bind)