run: ensure that stdio pipes are labeled correctly
Label stdio pipes to ensure that processes we run can read through /dev/stdin and write through the /dev/stdout and /dev/stderr links. Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
This commit is contained in:
parent
e6f732096c
commit
9b6a02f3af
2
go.mod
2
go.mod
|
@ -26,7 +26,7 @@ require (
|
|||
github.com/opencontainers/runc v1.0.2
|
||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417
|
||||
github.com/opencontainers/runtime-tools v0.9.0
|
||||
github.com/opencontainers/selinux v1.9.1
|
||||
github.com/opencontainers/selinux v1.10.0
|
||||
github.com/openshift/imagebuilder v1.2.2-0.20210415181909-87f3e48c2656
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/seccomp/libseccomp-golang v0.9.2-0.20200616122406-847368b35ebf
|
||||
|
|
4
go.sum
4
go.sum
|
@ -672,8 +672,8 @@ github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3
|
|||
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
|
||||
github.com/opencontainers/selinux v1.8.4/go.mod h1:HTvjPFoGMbpQsG886e3lQwnsRWtE4TC1OF3OUvG9FAo=
|
||||
github.com/opencontainers/selinux v1.8.5/go.mod h1:HTvjPFoGMbpQsG886e3lQwnsRWtE4TC1OF3OUvG9FAo=
|
||||
github.com/opencontainers/selinux v1.9.1 h1:b4VPEF3O5JLZgdTDBmGepaaIbAo0GqoF6EBRq5f/g3Y=
|
||||
github.com/opencontainers/selinux v1.9.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
|
||||
github.com/opencontainers/selinux v1.10.0 h1:rAiKF8hTcgLI3w0DHm6i0ylVVcOrlgR1kK99DRLDhyU=
|
||||
github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
|
||||
github.com/openshift/imagebuilder v1.2.2-0.20210415181909-87f3e48c2656 h1:WaxyNFpmIDu4i6so9r6LVFIbSaXqsj8oitMitt86ae4=
|
||||
github.com/openshift/imagebuilder v1.2.2-0.20210415181909-87f3e48c2656/go.mod h1:9aJRczxCH0mvT6XQ+5STAQaPWz7OsWcU5/mRkt8IWeo=
|
||||
github.com/ostreedev/ostree-go v0.0.0-20190702140239-759a8c1ac913 h1:TnbXhKzrTOyuvWrjI8W6pcoI9XPbLHFXCdN2dtUw7Rw=
|
||||
|
|
|
@ -863,6 +863,9 @@ func runUsingRuntime(isolation define.Isolation, options RunOptions, configureNe
|
|||
if stdioPipe, err = runMakeStdioPipe(int(uid), int(gid)); err != nil {
|
||||
return 1, err
|
||||
}
|
||||
if err = runLabelStdioPipes(stdioPipe, spec.Process.SelinuxLabel, spec.Linux.MountLabel); err != nil {
|
||||
return 1, err
|
||||
}
|
||||
errorFds = []int{stdioPipe[unix.Stdout][0], stdioPipe[unix.Stderr][0]}
|
||||
closeBeforeReadingErrorFds = []int{stdioPipe[unix.Stdout][1], stdioPipe[unix.Stderr][1]}
|
||||
// Set stdio to our pipes.
|
||||
|
|
22
selinux.go
22
selinux.go
|
@ -3,8 +3,12 @@
|
|||
package buildah
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/opencontainers/runtime-tools/generate"
|
||||
selinux "github.com/opencontainers/selinux/go-selinux"
|
||||
"github.com/opencontainers/selinux/go-selinux/label"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func selinuxGetEnabled() bool {
|
||||
|
@ -17,3 +21,21 @@ func setupSelinux(g *generate.Generator, processLabel, mountLabel string) {
|
|||
g.SetLinuxMountLabel(mountLabel)
|
||||
}
|
||||
}
|
||||
|
||||
func runLabelStdioPipes(stdioPipe [][]int, processLabel, mountLabel string) error {
|
||||
if !selinuxGetEnabled() || processLabel == "" || mountLabel == "" {
|
||||
// SELinux is completely disabled, or we're not doing anything at all with labeling
|
||||
return nil
|
||||
}
|
||||
pipeContext, err := selinux.ComputeCreateContext(processLabel, mountLabel, "fifo_file")
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "computing file creation context for pipes")
|
||||
}
|
||||
for i := range stdioPipe {
|
||||
pipeFdName := fmt.Sprintf("/proc/self/fd/%d", stdioPipe[i][0])
|
||||
if err := label.Relabel(pipeFdName, pipeContext, false); err != nil {
|
||||
return errors.Wrapf(err, "setting file label on %q", pipeFdName)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -12,3 +12,7 @@ func selinuxGetEnabled() bool {
|
|||
|
||||
func setupSelinux(g *generate.Generator, processLabel, mountLabel string) {
|
||||
}
|
||||
|
||||
func runLabelStdioPipes(stdioPipe [][]int, processLabel, mountLabel string) error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -7,6 +7,10 @@ load helpers
|
|||
expect_output --substring "non-directory/Dockerfile: not a directory"
|
||||
}
|
||||
|
||||
@test "bud stdio is usable pipes" {
|
||||
run_buildah build ${TESTSDIR}/bud/stdio
|
||||
}
|
||||
|
||||
@test "bud with --dns* flags" {
|
||||
_prefetch alpine
|
||||
run_buildah build --dns-search=example.com --dns=223.5.5.5 --dns-option=use-vc --signature-policy ${TESTSDIR}/policy.json -f ${TESTSDIR}/bud/dns/Dockerfile ${TESTSDIR}/bud/dns
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
FROM alpine
|
||||
# Will stall if this is connected to a terminal, or fail if it's not readable
|
||||
RUN cat /dev/stdin
|
||||
# Will fail if it's not writable
|
||||
RUN echo foo > /dev/stdout
|
||||
# Will fail if it's not writable
|
||||
RUN echo foo > /dev/stderr
|
|
@ -61,16 +61,30 @@ func ClassIndex(class string) (int, error) {
|
|||
return classIndex(class)
|
||||
}
|
||||
|
||||
// SetFileLabel sets the SELinux label for this path or returns an error.
|
||||
// SetFileLabel sets the SELinux label for this path, following symlinks,
|
||||
// or returns an error.
|
||||
func SetFileLabel(fpath string, label string) error {
|
||||
return setFileLabel(fpath, label)
|
||||
}
|
||||
|
||||
// FileLabel returns the SELinux label for this path or returns an error.
|
||||
// LsetFileLabel sets the SELinux label for this path, not following symlinks,
|
||||
// or returns an error.
|
||||
func LsetFileLabel(fpath string, label string) error {
|
||||
return lSetFileLabel(fpath, label)
|
||||
}
|
||||
|
||||
// FileLabel returns the SELinux label for this path, following symlinks,
|
||||
// or returns an error.
|
||||
func FileLabel(fpath string) (string, error) {
|
||||
return fileLabel(fpath)
|
||||
}
|
||||
|
||||
// LfileLabel returns the SELinux label for this path, not following symlinks,
|
||||
// or returns an error.
|
||||
func LfileLabel(fpath string) (string, error) {
|
||||
return lFileLabel(fpath)
|
||||
}
|
||||
|
||||
// SetFSCreateLabel tells the kernel what label to use for all file system objects
|
||||
// created by this task.
|
||||
// Set the label to an empty string to return to the default label. Calls to SetFSCreateLabel
|
||||
|
|
|
@ -316,8 +316,9 @@ func classIndex(class string) (int, error) {
|
|||
return index, nil
|
||||
}
|
||||
|
||||
// setFileLabel sets the SELinux label for this path or returns an error.
|
||||
func setFileLabel(fpath string, label string) error {
|
||||
// lSetFileLabel sets the SELinux label for this path, not following symlinks,
|
||||
// or returns an error.
|
||||
func lSetFileLabel(fpath string, label string) error {
|
||||
if fpath == "" {
|
||||
return ErrEmptyPath
|
||||
}
|
||||
|
@ -334,12 +335,50 @@ func setFileLabel(fpath string, label string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// fileLabel returns the SELinux label for this path or returns an error.
|
||||
// setFileLabel sets the SELinux label for this path, following symlinks,
|
||||
// or returns an error.
|
||||
func setFileLabel(fpath string, label string) error {
|
||||
if fpath == "" {
|
||||
return ErrEmptyPath
|
||||
}
|
||||
for {
|
||||
err := unix.Setxattr(fpath, xattrNameSelinux, []byte(label), 0)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
if err != unix.EINTR { //nolint:errorlint // unix errors are bare
|
||||
return &os.PathError{Op: "setxattr", Path: fpath, Err: err}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// fileLabel returns the SELinux label for this path, following symlinks,
|
||||
// or returns an error.
|
||||
func fileLabel(fpath string) (string, error) {
|
||||
if fpath == "" {
|
||||
return "", ErrEmptyPath
|
||||
}
|
||||
|
||||
label, err := getxattr(fpath, xattrNameSelinux)
|
||||
if err != nil {
|
||||
return "", &os.PathError{Op: "getxattr", Path: fpath, Err: err}
|
||||
}
|
||||
// Trim the NUL byte at the end of the byte buffer, if present.
|
||||
if len(label) > 0 && label[len(label)-1] == '\x00' {
|
||||
label = label[:len(label)-1]
|
||||
}
|
||||
return string(label), nil
|
||||
}
|
||||
|
||||
// lFileLabel returns the SELinux label for this path, not following symlinks,
|
||||
// or returns an error.
|
||||
func lFileLabel(fpath string) (string, error) {
|
||||
if fpath == "" {
|
||||
return "", ErrEmptyPath
|
||||
}
|
||||
|
||||
label, err := lgetxattr(fpath, xattrNameSelinux)
|
||||
if err != nil {
|
||||
return "", &os.PathError{Op: "lgetxattr", Path: fpath, Err: err}
|
||||
|
|
|
@ -17,10 +17,18 @@ func setFileLabel(fpath string, label string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func lSetFileLabel(fpath string, label string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func fileLabel(fpath string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func lFileLabel(fpath string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func setFSCreateLabel(label string) error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -36,3 +36,36 @@ func doLgetxattr(path, attr string, dest []byte) (int, error) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// getxattr returns a []byte slice containing the value of
|
||||
// an extended attribute attr set for path.
|
||||
func getxattr(path, attr string) ([]byte, error) {
|
||||
// Start with a 128 length byte array
|
||||
dest := make([]byte, 128)
|
||||
sz, errno := dogetxattr(path, attr, dest)
|
||||
for errno == unix.ERANGE { //nolint:errorlint // unix errors are bare
|
||||
// Buffer too small, use zero-sized buffer to get the actual size
|
||||
sz, errno = dogetxattr(path, attr, []byte{})
|
||||
if errno != nil {
|
||||
return nil, errno
|
||||
}
|
||||
|
||||
dest = make([]byte, sz)
|
||||
sz, errno = dogetxattr(path, attr, dest)
|
||||
}
|
||||
if errno != nil {
|
||||
return nil, errno
|
||||
}
|
||||
|
||||
return dest[:sz], nil
|
||||
}
|
||||
|
||||
// dogetxattr is a wrapper that retries on EINTR
|
||||
func dogetxattr(path, attr string, dest []byte) (int, error) {
|
||||
for {
|
||||
sz, err := unix.Getxattr(path, attr, dest)
|
||||
if err != unix.EINTR { //nolint:errorlint // unix errors are bare
|
||||
return sz, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -407,7 +407,7 @@ github.com/opencontainers/runtime-tools/generate
|
|||
github.com/opencontainers/runtime-tools/generate/seccomp
|
||||
github.com/opencontainers/runtime-tools/specerror
|
||||
github.com/opencontainers/runtime-tools/validate
|
||||
# github.com/opencontainers/selinux v1.9.1
|
||||
# github.com/opencontainers/selinux v1.10.0
|
||||
github.com/opencontainers/selinux/go-selinux
|
||||
github.com/opencontainers/selinux/go-selinux/label
|
||||
github.com/opencontainers/selinux/pkg/pwalk
|
||||
|
|
Loading…
Reference in New Issue