| package oci |
| |
| import ( |
| "context" |
| "path/filepath" |
| "strings" |
| |
| "github.com/containerd/containerd/containers" |
| "github.com/containerd/containerd/oci" |
| specs "github.com/opencontainers/runtime-spec/specs-go" |
| ) |
| |
| func withRemovedMount(destination string) oci.SpecOpts { |
| return func(_ context.Context, _ oci.Client, _ *containers.Container, s *specs.Spec) error { |
| newMounts := []specs.Mount{} |
| for _, o := range s.Mounts { |
| if o.Destination != destination { |
| newMounts = append(newMounts, o) |
| } |
| } |
| s.Mounts = newMounts |
| |
| return nil |
| } |
| } |
| |
| func withROBind(src, dest string) oci.SpecOpts { |
| return func(_ context.Context, _ oci.Client, _ *containers.Container, s *specs.Spec) error { |
| s.Mounts = append(s.Mounts, specs.Mount{ |
| Destination: dest, |
| Type: "bind", |
| Source: src, |
| Options: []string{"nosuid", "noexec", "nodev", "rbind", "ro"}, |
| }) |
| return nil |
| } |
| } |
| |
| func withCGroup() oci.SpecOpts { |
| return func(_ context.Context, _ oci.Client, _ *containers.Container, s *specs.Spec) error { |
| s.Mounts = append(s.Mounts, specs.Mount{ |
| Destination: "/sys/fs/cgroup", |
| Type: "cgroup", |
| Source: "cgroup", |
| Options: []string{"ro", "nosuid", "noexec", "nodev"}, |
| }) |
| return nil |
| } |
| |
| } |
| |
| func hasPrefix(p, prefixDir string) bool { |
| prefixDir = filepath.Clean(prefixDir) |
| if filepath.Base(prefixDir) == string(filepath.Separator) { |
| return true |
| } |
| p = filepath.Clean(p) |
| return p == prefixDir || strings.HasPrefix(p, prefixDir+string(filepath.Separator)) |
| } |
| |
| func removeMountsWithPrefix(mounts []specs.Mount, prefixDir string) []specs.Mount { |
| var ret []specs.Mount |
| for _, m := range mounts { |
| if !hasPrefix(m.Destination, prefixDir) { |
| ret = append(ret, m) |
| } |
| } |
| return ret |
| } |
| |
| func withBoundProc() oci.SpecOpts { |
| return func(_ context.Context, _ oci.Client, _ *containers.Container, s *specs.Spec) error { |
| s.Mounts = removeMountsWithPrefix(s.Mounts, "/proc") |
| procMount := specs.Mount{ |
| Destination: "/proc", |
| Type: "bind", |
| Source: "/proc", |
| // NOTE: "rbind"+"ro" does not make /proc read-only recursively. |
| // So we keep maskedPath and readonlyPaths (although not mandatory for rootless mode) |
| Options: []string{"rbind"}, |
| } |
| s.Mounts = append([]specs.Mount{procMount}, s.Mounts...) |
| |
| var maskedPaths []string |
| for _, s := range s.Linux.MaskedPaths { |
| if !hasPrefix(s, "/proc") { |
| maskedPaths = append(maskedPaths, s) |
| } |
| } |
| s.Linux.MaskedPaths = maskedPaths |
| |
| var readonlyPaths []string |
| for _, s := range s.Linux.ReadonlyPaths { |
| if !hasPrefix(s, "/proc") { |
| readonlyPaths = append(readonlyPaths, s) |
| } |
| } |
| s.Linux.ReadonlyPaths = readonlyPaths |
| |
| return nil |
| } |
| } |