diff options
-rw-r--r-- | docs/source/markdown/podman-create.1.md | 2 | ||||
-rw-r--r-- | docs/source/markdown/podman-run.1.md | 2 | ||||
-rw-r--r-- | pkg/specgen/generate/oci.go | 28 | ||||
-rw-r--r-- | test/e2e/run_test.go | 36 |
4 files changed, 65 insertions, 3 deletions
diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md index 30cadf703..a0963d178 100644 --- a/docs/source/markdown/podman-create.1.md +++ b/docs/source/markdown/podman-create.1.md @@ -859,7 +859,7 @@ Security Options - `unmask=ALL or /path/1:/path/2` : Paths to unmask separated by a colon. If set to **ALL**, it will unmask all the paths that are masked or made read only by default. - The default masked paths are **/proc/acpi, /proc/kcore, /proc/keys, /proc/latency_stats, /proc/sched_debug, /proc/scsi, /proc/timer_list, /proc/timer_stats, /sys/firmware, and /sys/fs/selinux.** The default paths that are read only are **/proc/asound, /proc/bus, /proc/fs, /proc/irq, /proc/sys, /proc/sysrq-trigger**. + The default masked paths are **/proc/acpi, /proc/kcore, /proc/keys, /proc/latency_stats, /proc/sched_debug, /proc/scsi, /proc/timer_list, /proc/timer_stats, /sys/firmware, and /sys/fs/selinux.** The default paths that are read only are **/proc/asound, /proc/bus, /proc/fs, /proc/irq, /proc/sys, /proc/sysrq-trigger, /sys/fs/cgroup**. - `proc-opts=OPTIONS` : Comma separated list of options to use for the /proc mount. More details for the possible mount options are specified at **proc(5)** man page. diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md index a633df94e..d3db18560 100644 --- a/docs/source/markdown/podman-run.1.md +++ b/docs/source/markdown/podman-run.1.md @@ -908,7 +908,7 @@ Security Options for the possible mount options are specified at **proc(5)** man page. - **unmask**=_ALL_ or _/path/1:/path/2_: Paths to unmask separated by a colon. If set to **ALL**, it will unmask all the paths that are masked or made read only by default. - The default masked paths are **/proc/acpi, /proc/kcore, /proc/keys, /proc/latency_stats, /proc/sched_debug, /proc/scsi, /proc/timer_list, /proc/timer_stats, /sys/firmware, and /sys/fs/selinux.**. The default paths that are read only are **/proc/asound**, **/proc/bus**, **/proc/fs**, **/proc/irq**, **/proc/sys**, **/proc/sysrq-trigger**. + The default masked paths are **/proc/acpi, /proc/kcore, /proc/keys, /proc/latency_stats, /proc/sched_debug, /proc/scsi, /proc/timer_list, /proc/timer_stats, /sys/firmware, and /sys/fs/selinux.**. The default paths that are read only are **/proc/asound**, **/proc/bus**, **/proc/fs**, **/proc/irq**, **/proc/sys**, **/proc/sysrq-trigger**, **/sys/fs/cgroup**. Note: Labeling can be disabled for all containers by setting **label=false** in the **containers.conf**(5) file. diff --git a/pkg/specgen/generate/oci.go b/pkg/specgen/generate/oci.go index 23a9ce831..eb4dbc944 100644 --- a/pkg/specgen/generate/oci.go +++ b/pkg/specgen/generate/oci.go @@ -2,12 +2,14 @@ package generate import ( "context" + "path" "strings" "github.com/containers/common/pkg/config" "github.com/containers/podman/v3/libpod" "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/libpod/image" + "github.com/containers/podman/v3/pkg/cgroups" "github.com/containers/podman/v3/pkg/rootless" "github.com/containers/podman/v3/pkg/specgen" spec "github.com/opencontainers/runtime-spec/specs-go" @@ -157,8 +159,32 @@ func canMountSys(isRootless, isNewUserns bool, s *specgen.SpecGenerator) bool { return true } +func getCGroupPermissons(unmask []string) string { + ro := "ro" + rw := "rw" + cgroup := "/sys/fs/cgroup" + + cgroupv2, _ := cgroups.IsCgroup2UnifiedMode() + if !cgroupv2 { + return ro + } + + if unmask != nil && unmask[0] == "ALL" { + return rw + } + + for _, p := range unmask { + if path.Clean(p) == cgroup { + return rw + } + } + return ro +} + +// SpecGenToOCI returns the base configuration for the container. func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runtime, rtc *config.Config, newImage *image.Image, mounts []spec.Mount, pod *libpod.Pod, finalCmd []string) (*spec.Spec, error) { - cgroupPerm := "ro" + cgroupPerm := getCGroupPermissons(s.Unmask) + g, err := generate.New("linux") if err != nil { return nil, err diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index f0ba9d1d9..490d05699 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -304,6 +304,42 @@ var _ = Describe("Podman run", func() { }) + It("podman run security-opt unmask on /sys/fs/cgroup", func() { + + SkipIfCgroupV1("podman umask on /sys/fs/cgroup will fail with cgroups V1") + SkipIfRootless("/sys/fs/cgroup rw access is needed") + rwOnCGroups := "/sys/fs/cgroup cgroup2 rw" + session := podmanTest.Podman([]string{"run", "--security-opt", "unmask=ALL", "--security-opt", "mask=/sys/fs/cgroup", ALPINE, "cat", "/proc/mounts"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(ContainSubstring(rwOnCGroups)) + + session = podmanTest.Podman([]string{"run", "--security-opt", "unmask=/sys/fs/cgroup", ALPINE, "cat", "/proc/mounts"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(ContainSubstring(rwOnCGroups)) + + session = podmanTest.Podman([]string{"run", "--security-opt", "unmask=/sys/fs/cgroup///", ALPINE, "cat", "/proc/mounts"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(ContainSubstring(rwOnCGroups)) + + session = podmanTest.Podman([]string{"run", "--security-opt", "unmask=ALL", ALPINE, "cat", "/proc/mounts"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(ContainSubstring(rwOnCGroups)) + + session = podmanTest.Podman([]string{"run", "--security-opt", "unmask=/sys/fs/cgroup", "--security-opt", "mask=/sys/fs/cgroup", ALPINE, "cat", "/proc/mounts"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(ContainSubstring(rwOnCGroups)) + + session = podmanTest.Podman([]string{"run", "--security-opt", "unmask=/sys/fs/cgroup", ALPINE, "ls", "/sys/fs/cgroup"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).ToNot(BeEmpty()) + }) + It("podman run seccomp test", func() { session := podmanTest.Podman([]string{"run", "-it", "--security-opt", strings.Join([]string{"seccomp=", forbidGetCWDSeccompProfile()}, ""), ALPINE, "pwd"}) session.WaitWithDefaultTimeout() |