Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SELinux support for pods #7902

Merged
merged 1 commit into from
Oct 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions libpod/pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,3 +327,21 @@ func (p *Pod) GetPodStats(previousContainerStats map[string]*define.ContainerSta
}
return newContainerStats, nil
}

// ProcessLabel returns the SELinux label associated with the pod
func (p *Pod) ProcessLabel() (string, error) {
if !p.HasInfraContainer() {
return "", nil
}

id, err := p.InfraContainerID()
if err != nil {
return "", err
}

ctr, err := p.runtime.state.Container(id)
if err != nil {
return "", err
}
return ctr.ProcessLabel(), nil
}
16 changes: 16 additions & 0 deletions pkg/specgen/generate/container_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/containers/podman/v2/pkg/specgen"
"github.com/containers/podman/v2/pkg/util"
"github.com/containers/storage"
"github.com/opencontainers/selinux/go-selinux/label"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
Expand Down Expand Up @@ -272,6 +273,21 @@ func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen.
// Security options
if len(s.SelinuxOpts) > 0 {
options = append(options, libpod.WithSecLabels(s.SelinuxOpts))
} else {
if pod != nil {
// duplicate the security options from the pod
processLabel, err := pod.ProcessLabel()
if err != nil {
return nil, err
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be nonfatal, making pods without an infra container is perfectly valid.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There will be no SELinux label though, although we have to figure out how to get one.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked inside of the code where it checks for an infra container, if no infra then it will return "" for process label, which will get SELinux to fall back to default, which is to label the containers differently.
Added a test for this use case.

}
if processLabel != "" {
selinuxOpts, err := label.DupSecOpt(processLabel)
if err != nil {
return nil, err
}
options = append(options, libpod.WithSecLabels(selinuxOpts))
}
}
}
options = append(options, libpod.WithPrivileged(s.Privileged))

Expand Down
111 changes: 111 additions & 0 deletions test/e2e/run_selinux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,4 +182,115 @@ var _ = Describe("Podman run", func() {
match2, _ := session.GrepString("s0:c1,c2")
Expect(match2).To(BeTrue())
})

It("podman pod container share SELinux labels", func() {
session := podmanTest.Podman([]string{"pod", "create"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
podID := session.OutputToString()

session = podmanTest.Podman([]string{"run", "--pod", podID, ALPINE, "cat", "/proc/self/attr/current"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
label1 := session.OutputToString()

session = podmanTest.Podman([]string{"run", "--pod", podID, ALPINE, "cat", "/proc/self/attr/current"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(Equal(label1))

session = podmanTest.Podman([]string{"pod", "rm", podID, "--force"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
})

It("podman pod container --infra=false doesn't share SELinux labels", func() {
session := podmanTest.Podman([]string{"pod", "create", "--infra=false"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
podID := session.OutputToString()

session = podmanTest.Podman([]string{"run", "--pod", podID, ALPINE, "cat", "/proc/self/attr/current"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
label1 := session.OutputToString()

session = podmanTest.Podman([]string{"run", "--pod", podID, ALPINE, "cat", "/proc/self/attr/current"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(Not(Equal(label1)))

session = podmanTest.Podman([]string{"pod", "rm", podID, "--force"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
})

It("podman shared IPC NS container share SELinux labels", func() {
session := podmanTest.RunTopContainer("test1")
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))

session = podmanTest.Podman([]string{"exec", "test1", "cat", "/proc/self/attr/current"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
label1 := session.OutputToString()

session = podmanTest.Podman([]string{"run", "--ipc", "container:test1", ALPINE, "cat", "/proc/self/attr/current"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(Equal(label1))
})

It("podman shared PID NS container share SELinux labels", func() {
session := podmanTest.RunTopContainer("test1")
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))

session = podmanTest.Podman([]string{"exec", "test1", "cat", "/proc/self/attr/current"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
label1 := session.OutputToString()

session = podmanTest.Podman([]string{"run", "--pid", "container:test1", ALPINE, "cat", "/proc/self/attr/current"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(Equal(label1))
})

It("podman shared NET NS container doesn't share SELinux labels", func() {
session := podmanTest.RunTopContainer("test1")
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))

session = podmanTest.Podman([]string{"exec", "test1", "cat", "/proc/self/attr/current"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
label1 := session.OutputToString()

session = podmanTest.Podman([]string{"run", "--net", "container:test1", ALPINE, "cat", "/proc/self/attr/current"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(Not(Equal(label1)))
})

It("podman test --pid=host", func() {
session := podmanTest.Podman([]string{"run", "--pid=host", ALPINE, "cat", "/proc/self/attr/current"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(ContainSubstring("spc_t"))
})
Comment on lines +276 to +281
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I cannot get this to work. I'm trying to write an equivalent system test, and no matter what, I get:

$ ./bin/podman run --pid=host alpine cat /proc/self/attr/current
unconfined_u:system_r:container_runtime_t:s0%
$ ls -lZ bin/podman
-rwxrwxr-x. 1 esm esm system_u:object_r:container_runtime_exec_t:s0 54319936 Oct  5 15:08 bin/podman

(As root, I get spc_t as expected). master @ f48b163, with container-selinux-2.145.0-1.fc32.

I must be missing something simple. Any suggestions, please?


It("podman test --ipc=host", func() {
session := podmanTest.Podman([]string{"run", "--ipc=host", ALPINE, "cat", "/proc/self/attr/current"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(ContainSubstring("spc_t"))
})

It("podman test --ipc=net", func() {
session := podmanTest.Podman([]string{"run", "--net=host", ALPINE, "cat", "/proc/self/attr/current"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(ContainSubstring("container_t"))
})
})