From 0d0ad59641a308450d694d4c2fb95303c64fabf8 Mon Sep 17 00:00:00 2001 From: Peter Hunt Date: Thu, 7 Mar 2019 12:52:54 -0500 Subject: [PATCH] Default to SELinux private label for play kube mounts Before, there were SELinux denials when a volume was bind-mounted by podman play kube. Partially fix this by setting the default private label for mounts created by play kube (with DirectoryOrCreate) For volumes mounted as Directory, the user will have to set their own SELinux permissions on the mount point also remove left over debugging print statement Signed-off-by: Peter Hunt --- cmd/podman/play_kube.go | 7 ++++++- docs/podman-play-kube.1.md | 2 ++ libpod/runtime_volume_linux.go | 12 ++---------- libpod/util_linux.go | 21 +++++++++++++++++++++ libpod/util_unsupported.go | 6 ++++++ 5 files changed, 37 insertions(+), 11 deletions(-) diff --git a/cmd/podman/play_kube.go b/cmd/podman/play_kube.go index 10221a3396..0429a40eba 100644 --- a/cmd/podman/play_kube.go +++ b/cmd/podman/play_kube.go @@ -168,7 +168,13 @@ func playKubeYAMLCmd(c *cliconfig.KubePlayValues) error { return errors.Errorf("Error creating HostPath %s at %s", volume.Name, hostPath.Path) } } + // unconditionally label a newly created volume as private + if err := libpod.LabelVolumePath(hostPath.Path, false); err != nil { + return errors.Wrapf(err, "Error giving %s a label", hostPath.Path) + } + break case v1.HostPathDirectory: + case v1.HostPathUnset: // do nothing here because we will verify the path exists in validateVolumeHostDir break default: @@ -178,7 +184,6 @@ func playKubeYAMLCmd(c *cliconfig.KubePlayValues) error { if err := shared.ValidateVolumeHostDir(hostPath.Path); err != nil { return errors.Wrapf(err, "Error in parsing HostPath in YAML") } - fmt.Println(volume.Name) volumes[volume.Name] = hostPath.Path } diff --git a/docs/podman-play-kube.1.md b/docs/podman-play-kube.1.md index a9af961cdf..a38abf35aa 100644 --- a/docs/podman-play-kube.1.md +++ b/docs/podman-play-kube.1.md @@ -22,6 +22,8 @@ the ID of the new Pod is output. Ideally the input file would be one created by Podman (see podman-generate-kube(1)). This would guarantee a smooth import and expected results. +Note: HostPath volume types created by play kube will be given an SELinux private label (Z) + # OPTIONS: **--authfile** diff --git a/libpod/runtime_volume_linux.go b/libpod/runtime_volume_linux.go index b51bb8213f..5767a99e7b 100644 --- a/libpod/runtime_volume_linux.go +++ b/libpod/runtime_volume_linux.go @@ -10,7 +10,6 @@ import ( "github.com/containers/libpod/libpod/events" "github.com/containers/storage/pkg/stringid" - "github.com/opencontainers/selinux/go-selinux/label" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -56,15 +55,8 @@ func (r *Runtime) newVolume(ctx context.Context, options ...VolumeCreateOption) if err := os.MkdirAll(fullVolPath, 0755); err != nil { return nil, errors.Wrapf(err, "error creating volume directory %q", fullVolPath) } - _, mountLabel, err := label.InitLabels([]string{}) - if err != nil { - return nil, errors.Wrapf(err, "error getting default mountlabels") - } - if err := label.ReleaseLabel(mountLabel); err != nil { - return nil, errors.Wrapf(err, "error releasing label %q", mountLabel) - } - if err := label.Relabel(fullVolPath, mountLabel, true); err != nil { - return nil, errors.Wrapf(err, "error setting selinux label to %q", fullVolPath) + if err := LabelVolumePath(fullVolPath, true); err != nil { + return nil, err } volume.config.MountPoint = fullVolPath diff --git a/libpod/util_linux.go b/libpod/util_linux.go index 30e2538c31..a801df2ee8 100644 --- a/libpod/util_linux.go +++ b/libpod/util_linux.go @@ -9,6 +9,7 @@ import ( "github.com/containerd/cgroups" "github.com/containers/libpod/pkg/util" spec "github.com/opencontainers/runtime-spec/specs-go" + "github.com/opencontainers/selinux/go-selinux/label" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -91,3 +92,23 @@ func GetV1CGroups(excludes []string) cgroups.Hierarchy { return filtered, nil } } + +// LabelVolumePath takes a mount path for a volume and gives it an +// selinux label of either shared or not +func LabelVolumePath(path string, shared bool) error { + _, mountLabel, err := label.InitLabels([]string{}) + if err != nil { + return errors.Wrapf(err, "error getting default mountlabels") + } + if err := label.ReleaseLabel(mountLabel); err != nil { + return errors.Wrapf(err, "error releasing label %q", mountLabel) + } + if err := label.Relabel(path, mountLabel, shared); err != nil { + permString := "private" + if shared { + permString = "shared" + } + return errors.Wrapf(err, "error setting selinux label for %s to %q as %s", path, mountLabel, permString) + } + return nil +} diff --git a/libpod/util_unsupported.go b/libpod/util_unsupported.go index d598b465fa..940006e698 100644 --- a/libpod/util_unsupported.go +++ b/libpod/util_unsupported.go @@ -21,3 +21,9 @@ func deleteSystemdCgroup(path string) error { func assembleSystemdCgroupName(baseSlice, newSlice string) (string, error) { return "", errors.Wrapf(ErrOSNotSupported, "cgroups are not supported on non-linux OSes") } + +// LabelVolumePath takes a mount path for a volume and gives it an +// selinux label of either shared or not +func LabelVolumePath(path string, shared bool) error { + return ErrNotImplemented +}