Merge pull request #10185 from rhatdan/volume

Add filepath glob support to --security-opt unmask
This commit is contained in:
OpenShift Merge Robot
2021-05-05 15:38:11 -04:00
committed by GitHub
7 changed files with 82 additions and 30 deletions

View File

@@ -540,7 +540,7 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string
return fmt.Errorf("invalid systempaths option %q, only `unconfined` is supported", con[1]) return fmt.Errorf("invalid systempaths option %q, only `unconfined` is supported", con[1])
} }
case "unmask": case "unmask":
s.ContainerSecurityConfig.Unmask = append(s.ContainerSecurityConfig.Unmask, strings.Split(con[1], ":")...) s.ContainerSecurityConfig.Unmask = append(s.ContainerSecurityConfig.Unmask, con[1:]...)
default: default:
return fmt.Errorf("invalid --security-opt 2: %q", opt) return fmt.Errorf("invalid --security-opt 2: %q", opt)
} }

View File

@@ -5,6 +5,7 @@ ipcns="host"
utsns="host" utsns="host"
cgroupns="host" cgroupns="host"
cgroups="disabled" cgroups="disabled"
log_driver = "k8s_file"
[engine] [engine]
cgroup_manager = "cgroupfs" cgroup_manager = "cgroupfs"
events_logger="file" events_logger="file"

View File

@@ -882,8 +882,7 @@ Note: Labeling can be disabled for all containers by setting label=false in the
- `proc-opts=OPTIONS` : Comma-separated list of options to use for the /proc mount. More details for the - `proc-opts=OPTIONS` : Comma-separated list of options to use for the /proc mount. More details for the
possible mount options are specified in the **proc(5)** man page. possible mount options are specified in the **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_ or _/path/1:/path/2_, or shell expanded paths (/proc/*): 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.
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, /sys/fs/cgroup**. 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** (`/etc/containers/containers.conf` or `$HOME/.config/containers/containers.conf`) file. Note: Labeling can be disabled for all containers by setting label=false in the **containers.conf** (`/etc/containers/containers.conf` or `$HOME/.config/containers/containers.conf`) file.

View File

@@ -934,8 +934,7 @@ Note: Labeling can be disabled for all containers by setting label=false in the
- **proc-opts**=_OPTIONS_ : Comma-separated list of options to use for the /proc mount. More details - **proc-opts**=_OPTIONS_ : Comma-separated list of options to use for the /proc mount. More details
for the possible mount options are specified in the **proc(5)** man page. for the possible mount options are specified in the **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_ or _/path/1:/path/2_, or shell expanded paths (/proc/*): 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.
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**, **/sys/fs/cgroup**. 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. Note: Labeling can be disabled for all containers by setting **label=false** in the **containers.conf**(5) file.
@@ -1644,6 +1643,13 @@ the **mask** option.
$ podman run --security-opt unmask=ALL fedora bash $ podman run --security-opt unmask=ALL fedora bash
``` ```
To unmask all the paths that start with /proc, set the **unmask** option to
**/proc/***.
```
$ podman run --security-opt unmask=/proc/* fedora bash
```
``` ```
$ podman run --security-opt unmask=/foo/bar:/sys/firmware fedora bash $ podman run --security-opt unmask=/foo/bar:/sys/firmware fedora bash
``` ```

View File

@@ -10,7 +10,6 @@ import (
"github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/pkg/rootless" "github.com/containers/podman/v3/pkg/rootless"
"github.com/containers/podman/v3/pkg/util"
spec "github.com/opencontainers/runtime-spec/specs-go" spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-tools/generate" "github.com/opencontainers/runtime-tools/generate"
"github.com/pkg/errors" "github.com/pkg/errors"
@@ -151,30 +150,23 @@ func BlockAccessToKernelFilesystems(privileged, pidModeIsHost bool, mask, unmask
"/sys/dev/block", "/sys/dev/block",
} }
unmaskAll := false
if unmask != nil && unmask[0] == "ALL" {
unmaskAll = true
}
if !privileged { if !privileged {
if !unmaskAll { for _, mp := range defaultMaskPaths {
for _, mp := range defaultMaskPaths { // check that the path to mask is not in the list of paths to unmask
// check that the path to mask is not in the list of paths to unmask if shouldMask(mp, unmask) {
if !util.StringInSlice(mp, unmask) { g.AddLinuxMaskedPaths(mp)
g.AddLinuxMaskedPaths(mp)
}
} }
for _, rp := range []string{ }
"/proc/asound", for _, rp := range []string{
"/proc/bus", "/proc/asound",
"/proc/fs", "/proc/bus",
"/proc/irq", "/proc/fs",
"/proc/sys", "/proc/irq",
"/proc/sysrq-trigger", "/proc/sys",
} { "/proc/sysrq-trigger",
if !util.StringInSlice(rp, unmask) { } {
g.AddLinuxReadonlyPaths(rp) if shouldMask(rp, unmask) {
} g.AddLinuxReadonlyPaths(rp)
} }
} }
@@ -376,3 +368,21 @@ func supportAmbientCapabilities() bool {
err := unix.Prctl(unix.PR_CAP_AMBIENT, unix.PR_CAP_AMBIENT_IS_SET, 0, 0, 0) err := unix.Prctl(unix.PR_CAP_AMBIENT, unix.PR_CAP_AMBIENT_IS_SET, 0, 0, 0)
return err == nil return err == nil
} }
func shouldMask(mask string, unmask []string) bool {
for _, m := range unmask {
if strings.ToLower(m) == "all" {
return false
}
for _, m1 := range strings.Split(m, ":") {
match, err := filepath.Match(m1, mask)
if err != nil {
logrus.Errorf(err.Error())
}
if match {
return false
}
}
}
return true
}

View File

@@ -0,0 +1,28 @@
package generate
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestShouldMask(t *testing.T) {
tests := []struct {
mask string
unmask []string
shouldMask bool
}{
{"/proc/foo", []string{"all"}, false},
{"/proc/foo", []string{"ALL"}, false},
{"/proc/foo", []string{"/proc/foo"}, false},
{"/proc/foo", []string{"/proc/*"}, false},
{"/proc/foo", []string{"/proc/bar", "all"}, false},
{"/proc/foo", []string{"/proc/f*"}, false},
{"/proc/foo", []string{"/proc/b*"}, true},
{"/proc/foo", []string{}, true},
}
for _, test := range tests {
val := shouldMask(test.mask, test.unmask)
assert.Equal(t, val, test.shouldMask)
}
}

View File

@@ -299,9 +299,17 @@ var _ = Describe("Podman run", func() {
session = podmanTest.Podman([]string{"run", "-d", "--name=maskCtr5", "--security-opt", "systempaths=unconfined", ALPINE, "grep", "/proc", "/proc/self/mounts"}) session = podmanTest.Podman([]string{"run", "-d", "--name=maskCtr5", "--security-opt", "systempaths=unconfined", ALPINE, "grep", "/proc", "/proc/self/mounts"})
session.WaitWithDefaultTimeout() session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0)) Expect(session.ExitCode()).To(Equal(0))
stdoutLines := session.OutputToStringArray() Expect(session.OutputToStringArray()).Should(HaveLen(1))
Expect(stdoutLines).Should(HaveLen(1))
session = podmanTest.Podman([]string{"run", "-d", "--security-opt", "unmask=/proc/*", ALPINE, "grep", "/proc", "/proc/self/mounts"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToStringArray()).Should(HaveLen(1))
session = podmanTest.Podman([]string{"run", "--security-opt", "unmask=/proc/a*", ALPINE, "ls", "/proc/acpi"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(Not(BeEmpty()))
}) })
It("podman run security-opt unmask on /sys/fs/cgroup", func() { It("podman run security-opt unmask on /sys/fs/cgroup", func() {