mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
apply selinux labels volume patch on volumes refactor
Signed-off-by: Jessica Frazelle <princess@docker.com>
This commit is contained in:
parent
160dc79db0
commit
af7d17a6c9
3 changed files with 86 additions and 41 deletions
|
@ -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
|
||||
}
|
||||
|
||||
// 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 {
|
||||
validModes := map[string]bool{
|
||||
"rw": true,
|
||||
"ro": true,
|
||||
}
|
||||
return validModes[mode]
|
||||
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
|
||||
}
|
||||
|
|
|
@ -34,28 +34,29 @@ func TestGetVolumeDriver(t *testing.T) {
|
|||
|
||||
func TestParseBindMount(t *testing.T) {
|
||||
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 {
|
||||
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)
|
||||
|
|
|
@ -37,24 +37,25 @@ func TestGetVolumeDefaultDriver(t *testing.T) {
|
|||
|
||||
func TestParseBindMount(t *testing.T) {
|
||||
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 {
|
||||
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)
|
||||
|
|
Loading…
Reference in a new issue