diff options
-rw-r--r-- | libpod/oci_linux.go | 53 | ||||
-rw-r--r-- | pkg/spec/spec.go | 3 | ||||
-rw-r--r-- | test/system/030-run.bats | 8 |
3 files changed, 64 insertions, 0 deletions
diff --git a/libpod/oci_linux.go b/libpod/oci_linux.go index 8c0abad80..01f7c3649 100644 --- a/libpod/oci_linux.go +++ b/libpod/oci_linux.go @@ -3,15 +3,20 @@ package libpod import ( + "fmt" "os" "os/exec" "path/filepath" + "runtime" "strings" "syscall" "github.com/containerd/cgroups" + "github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/utils" + pmount "github.com/containers/storage/pkg/mount" spec "github.com/opencontainers/runtime-spec/specs-go" + "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/sys/unix" ) @@ -91,6 +96,54 @@ func (r *OCIRuntime) createContainer(ctr *Container, cgroupParent string, restor return err } } + + // if we are running a non privileged container, be sure to umount some kernel paths so they are not + // bind mounted inside the container at all. + if !ctr.config.Privileged && !rootless.IsRootless() { + ch := make(chan error) + go func() { + runtime.LockOSThread() + err := func() error { + fd, err := os.Open(fmt.Sprintf("/proc/%d/task/%d/ns/mnt", os.Getpid(), unix.Gettid())) + if err != nil { + return err + } + defer fd.Close() + + // create a new mountns on the current thread + if err = unix.Unshare(unix.CLONE_NEWNS); err != nil { + return err + } + defer unix.Setns(int(fd.Fd()), unix.CLONE_NEWNS) + + // don't spread our mounts around. We are setting only /sys to be slave + // so that the cleanup process is still able to umount the storage and the + // changes are propagated to the host. + err = unix.Mount("/sys", "/sys", "none", unix.MS_REC|unix.MS_SLAVE, "") + if err != nil { + return errors.Wrapf(err, "cannot make /sys slave") + } + + mounts, err := pmount.GetMounts() + if err != nil { + return err + } + for _, m := range mounts { + if !strings.HasPrefix(m.Mountpoint, "/sys/kernel") { + continue + } + err = unix.Unmount(m.Mountpoint, 0) + if err != nil { + return errors.Wrapf(err, "cannot unmount %s", m.Mountpoint) + } + } + return r.createOCIContainer(ctr, cgroupParent, restoreOptions) + }() + ch <- err + }() + err := <-ch + return err + } } return r.createOCIContainer(ctr, cgroupParent, restoreOptions) } diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go index 9b6bd089e..0371b6d4d 100644 --- a/pkg/spec/spec.go +++ b/pkg/spec/spec.go @@ -132,6 +132,9 @@ func CreateConfigToOCISpec(config *CreateConfig) (*spec.Spec, error) { //nolint Options: []string{"rprivate", "nosuid", "noexec", "nodev", r, "rbind"}, } g.AddMount(sysMnt) + if !config.Privileged && isRootless { + g.AddLinuxMaskedPaths("/sys/kernel") + } } if isRootless { nGids, err := getAvailableGids() diff --git a/test/system/030-run.bats b/test/system/030-run.bats index 8ae68f33d..188070550 100644 --- a/test/system/030-run.bats +++ b/test/system/030-run.bats @@ -31,4 +31,12 @@ echo $rand | 0 | $rand done < <(parse_table "$tests") } +@test "podman run - uidmapping has no /sys/kernel mounts" { + run_podman $expected_rc run --uidmapping 0:100:10000 $IMAGE mount | grep /sys/kernel + is "$output" "" "podman run $cmd - output" + + run_podman $expected_rc run --net host --uidmapping 0:100:10000 $IMAGE mount | grep /sys/kernel + is "$output" "" "podman run $cmd - output" +} + # vim: filetype=sh |