Add proper SELinux labeling to buildah run

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>

Closes: #294
Approved by: nalind
This commit is contained in:
Daniel J Walsh 2017-10-19 21:47:15 +00:00 committed by Atomic Bot
parent cde99f8517
commit 966f32b2ac
10 changed files with 84 additions and 8 deletions

View File

@ -21,6 +21,7 @@ dnf install -y \
libassuan-devel \ libassuan-devel \
libseccomp-devel \ libseccomp-devel \
libselinux-devel \ libselinux-devel \
libselinux-utils \
make \ make \
ostree-devel \ ostree-devel \
which which

View File

@ -77,6 +77,10 @@ type Builder struct {
// MountPoint is the last location where the container's root // MountPoint is the last location where the container's root
// filesystem was mounted. It should not be modified. // filesystem was mounted. It should not be modified.
MountPoint string `json:"mountpoint,omitempty"` MountPoint string `json:"mountpoint,omitempty"`
// ProcessLabel is the SELinux process label associated with the container
ProcessLabel string `json:"process-label,omitempty"`
// MountLabel is the SELinux mount label associated with the container
MountLabel string `json:"mount-label,omitempty"`
// ImageAnnotations is a set of key-value pairs which is stored in the // ImageAnnotations is a set of key-value pairs which is stored in the
// image's manifest. // image's manifest.

View File

@ -1,6 +1,7 @@
package buildah package buildah
import ( import (
"github.com/opencontainers/selinux/go-selinux/label"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
@ -13,5 +14,5 @@ func (b *Builder) Delete() error {
b.MountPoint = "" b.MountPoint = ""
b.Container = "" b.Container = ""
b.ContainerID = "" b.ContainerID = ""
return nil return label.ReleaseLabel(b.ProcessLabel)
} }

44
new.go
View File

@ -9,6 +9,8 @@ import (
"github.com/containers/image/transports/alltransports" "github.com/containers/image/transports/alltransports"
"github.com/containers/image/types" "github.com/containers/image/types"
"github.com/containers/storage" "github.com/containers/storage"
"github.com/opencontainers/selinux/go-selinux"
"github.com/opencontainers/selinux/go-selinux/label"
"github.com/openshift/imagebuilder" "github.com/openshift/imagebuilder"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
@ -25,8 +27,35 @@ const (
DefaultTransport = "docker://" DefaultTransport = "docker://"
) )
func reserveSELinuxLabels(store storage.Store, id string) error {
if selinux.GetEnabled() {
containers, err := store.Containers()
if err != nil {
return err
}
for _, c := range containers {
if id == c.ID {
continue
} else {
b, err := OpenBuilder(store, c.ID)
if err != nil {
if err == storage.ErrContainerUnknown {
continue
}
return err
}
// Prevent containers from using same MCS Label
if err := label.ReserveLabel(b.ProcessLabel); err != nil {
return err
}
}
}
}
return nil
}
func newBuilder(store storage.Store, options BuilderOptions) (*Builder, error) { func newBuilder(store storage.Store, options BuilderOptions) (*Builder, error) {
var err error
var ref types.ImageReference var ref types.ImageReference
var img *storage.Image var img *storage.Image
manifest := []byte{} manifest := []byte{}
@ -45,6 +74,7 @@ func newBuilder(store storage.Store, options BuilderOptions) (*Builder, error) {
imageID := "" imageID := ""
if image != "" { if image != "" {
var err error
if options.PullPolicy == PullAlways { if options.PullPolicy == PullAlways {
pulledReference, err2 := pullImage(store, options, systemContext) pulledReference, err2 := pullImage(store, options, systemContext)
if err2 != nil { if err2 != nil {
@ -158,6 +188,14 @@ func newBuilder(store storage.Store, options BuilderOptions) (*Builder, error) {
} }
}() }()
if err := reserveSELinuxLabels(store, container.ID); err != nil {
return nil, err
}
processLabel, mountLabel, err := label.InitLabels(nil)
if err != nil {
return nil, err
}
builder := &Builder{ builder := &Builder{
store: store, store: store,
Type: containerType, Type: containerType,
@ -169,10 +207,12 @@ func newBuilder(store storage.Store, options BuilderOptions) (*Builder, error) {
ContainerID: container.ID, ContainerID: container.ID,
ImageAnnotations: map[string]string{}, ImageAnnotations: map[string]string{},
ImageCreatedBy: "", ImageCreatedBy: "",
ProcessLabel: processLabel,
MountLabel: mountLabel,
} }
if options.Mount { if options.Mount {
_, err = builder.Mount("") _, err = builder.Mount(mountLabel)
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "error mounting build container") return nil, errors.Wrapf(err, "error mounting build container")
} }

4
run.go
View File

@ -182,7 +182,9 @@ func (b *Builder) Run(command []string, options RunOptions) error {
} else if b.Hostname() != "" { } else if b.Hostname() != "" {
g.SetHostname(b.Hostname()) g.SetHostname(b.Hostname())
} }
mountPoint, err := b.Mount("") g.SetProcessSelinuxLabel(b.ProcessLabel)
g.SetLinuxMountLabel(b.MountLabel)
mountPoint, err := b.Mount(b.MountLabel)
if err != nil { if err != nil {
return err return err
} }

26
tests/selinux.bats Normal file
View File

@ -0,0 +1,26 @@
#!/usr/bin/env bats
load helpers
@test "selinux test" {
if ! which selinuxenabled ; then
skip "No selinuxenabled"
elif ! /usr/sbin/selinuxenabled; then
skip "selinux is disabled"
fi
image=alpine
cid=$(buildah from --pull --signature-policy ${TESTSDIR}/policy.json $image)
firstlabel=$(buildah --debug=false run $cid cat /proc/1/attr/current)
run buildah --debug=false run $cid cat /proc/1/attr/current
[ "$status" -eq 0 ]
[ "$output" == $firstlabel ]
cid1=$(buildah from --pull --signature-policy ${TESTSDIR}/policy.json $image)
run buildah --debug=false run $cid1 cat /proc/1/attr/current
[ "$status" -eq 0 ]
[ "$output" != $firstlabel ]
buildah rm $cid
buildah rm $cid1
}

View File

@ -17,5 +17,5 @@ exec gometalinter.v1 \
--disable=gas \ --disable=gas \
--disable=aligncheck \ --disable=aligncheck \
--cyclo-over=40 \ --cyclo-over=40 \
--deadline=240s \ --deadline=480s \
--tests "$@" --tests "$@"

View File

@ -27,7 +27,7 @@ github.com/opencontainers/image-spec v1.0.0
github.com/opencontainers/runc master github.com/opencontainers/runc master
github.com/opencontainers/runtime-spec v1.0.0 github.com/opencontainers/runtime-spec v1.0.0
github.com/opencontainers/runtime-tools master github.com/opencontainers/runtime-tools master
github.com/opencontainers/selinux ba1aefe8057f1d0cfb8e88d0ec1dc85925ef987d github.com/opencontainers/selinux b29023b86e4a69d1b46b7e7b4e2b6fda03f0b9cd
github.com/openshift/imagebuilder master github.com/openshift/imagebuilder master
github.com/ostreedev/ostree-go aeb02c6b6aa2889db3ef62f7855650755befd460 github.com/ostreedev/ostree-go aeb02c6b6aa2889db3ef62f7855650755befd460
github.com/pborman/uuid master github.com/pborman/uuid master

View File

@ -49,8 +49,10 @@ func InitLabels(options []string) (string, string, error) {
mcon[con[0]] = con[1] mcon[con[0]] = con[1]
} }
} }
_ = ReleaseLabel(processLabel)
processLabel = pcon.Get() processLabel = pcon.Get()
mountLabel = mcon.Get() mountLabel = mcon.Get()
_ = ReserveLabel(processLabel)
} }
return processLabel, mountLabel, nil return processLabel, mountLabel, nil
} }

View File

@ -213,7 +213,7 @@ func SetFileLabel(path string, label string) error {
return lsetxattr(path, xattrNameSelinux, []byte(label), 0) return lsetxattr(path, xattrNameSelinux, []byte(label), 0)
} }
// Filecon returns the SELinux label for this path or returns an error. // FileLabel returns the SELinux label for this path or returns an error.
func FileLabel(path string) (string, error) { func FileLabel(path string) (string, error) {
label, err := lgetxattr(path, xattrNameSelinux) label, err := lgetxattr(path, xattrNameSelinux)
if err != nil { if err != nil {
@ -331,7 +331,7 @@ func EnforceMode() int {
} }
/* /*
SetEnforce sets the current SELinux mode Enforcing, Permissive. SetEnforceMode sets the current SELinux mode Enforcing, Permissive.
Disabled is not valid, since this needs to be set at boot time. Disabled is not valid, since this needs to be set at boot time.
*/ */
func SetEnforceMode(mode int) error { func SetEnforceMode(mode int) error {