Skip to content

Commit b0691fb

Browse files
committed
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 <[email protected]>
1 parent 4c40e8e commit b0691fb

File tree

5 files changed

+42
-0
lines changed

5 files changed

+42
-0
lines changed

run_linux.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -863,6 +863,9 @@ func runUsingRuntime(isolation define.Isolation, options RunOptions, configureNe
863863
if stdioPipe, err = runMakeStdioPipe(int(uid), int(gid)); err != nil {
864864
return 1, err
865865
}
866+
if err = runLabelStdioPipes(stdioPipe, spec.Process.SelinuxLabel, spec.Linux.MountLabel); err != nil {
867+
return 1, err
868+
}
866869
errorFds = []int{stdioPipe[unix.Stdout][0], stdioPipe[unix.Stderr][0]}
867870
closeBeforeReadingErrorFds = []int{stdioPipe[unix.Stdout][1], stdioPipe[unix.Stderr][1]}
868871
// Set stdio to our pipes.

selinux.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@
33
package buildah
44

55
import (
6+
"fmt"
7+
68
"github.com/opencontainers/runtime-tools/generate"
79
selinux "github.com/opencontainers/selinux/go-selinux"
10+
"github.com/pkg/errors"
11+
"golang.org/x/sys/unix"
812
)
913

1014
func selinuxGetEnabled() bool {
@@ -17,3 +21,23 @@ func setupSelinux(g *generate.Generator, processLabel, mountLabel string) {
1721
g.SetLinuxMountLabel(mountLabel)
1822
}
1923
}
24+
25+
func runLabelStdioPipes(stdioPipe [][]int, processLabel, mountLabel string) error {
26+
if !selinuxGetEnabled() || processLabel == "" || mountLabel == "" {
27+
// SELinux is completely disabled, or we're not doing anything at all with labeling
28+
return nil
29+
}
30+
pipeContext, err := selinux.ComputeCreateContext(processLabel, mountLabel, "fifo_file")
31+
if err != nil {
32+
return errors.Wrapf(err, "computing file creation context for pipes")
33+
}
34+
const xattrNameSelinux = "security.selinux"
35+
for i := range stdioPipe {
36+
pipeFdName := fmt.Sprintf("/proc/self/fd/%d", stdioPipe[i][0])
37+
// selinux.SetFileLabel() doesn't follow symlinks, but we need to do that here, so do it the hard way
38+
if err := unix.Setxattr(pipeFdName, xattrNameSelinux, []byte(pipeContext), 0); err != nil {
39+
return errors.Wrapf(err, "setting label")
40+
}
41+
}
42+
return nil
43+
}

selinux_unsupported.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,7 @@ func selinuxGetEnabled() bool {
1212

1313
func setupSelinux(g *generate.Generator, processLabel, mountLabel string) {
1414
}
15+
16+
func runLabelStdioPipes(stdioPipe [][]int, processLabel, mountLabel string) error {
17+
return nil
18+
}

tests/bud.bats

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ load helpers
77
expect_output --substring "non-directory/Dockerfile: not a directory"
88
}
99

10+
@test "bud stdio is usable pipes" {
11+
run_buildah build ${TESTSDIR}/bud/stdio
12+
}
13+
1014
@test "bud with --dns* flags" {
1115
_prefetch alpine
1216
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

tests/bud/stdio/Dockerfile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
FROM alpine
2+
# Will stall if this is connected to a terminal, or fail if it's not readable
3+
RUN cat /dev/stdin
4+
# Will fail if it's not writable
5+
RUN echo foo > /dev/stdout
6+
# Will fail if it's not writable
7+
RUN echo foo > /dev/stderr

0 commit comments

Comments
 (0)