From dfd4d88445c01cd9c0b008316e1156cb96dd7e4e Mon Sep 17 00:00:00 2001 From: "ye.sijun" Date: Tue, 25 Jan 2022 17:02:52 +0800 Subject: [PATCH] fix duplicate mount /dev/shm Signed-off-by: ye.sijun --- cmd/nerdctl/run_mount.go | 53 +++++++++++++++++++++++------ cmd/nerdctl/run_mount_linux_test.go | 6 ++++ 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/cmd/nerdctl/run_mount.go b/cmd/nerdctl/run_mount.go index 8fe602cc301..436cfe017e8 100644 --- a/cmd/nerdctl/run_mount.go +++ b/cmd/nerdctl/run_mount.go @@ -22,8 +22,10 @@ import ( "os" "path/filepath" "runtime" + "strings" "github.com/containerd/containerd" + "github.com/containerd/containerd/containers" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/mount" "github.com/containerd/containerd/oci" @@ -41,6 +43,38 @@ import ( "github.com/spf13/cobra" ) +// copy from https://github.com/containerd/containerd/blob/v1.6.0-rc.1/pkg/cri/opts/spec_linux.go#L129-L151 +func withMounts(mounts []specs.Mount) oci.SpecOpts { + return func(ctx context.Context, _ oci.Client, _ *containers.Container, s *specs.Spec) error { + // Copy all mounts from default mounts, except for + // - mounts overridden by supplied mount; + // - all mounts under /dev if a supplied /dev is present. + mountSet := make(map[string]struct{}) + for _, m := range mounts { + mountSet[filepath.Clean(m.Destination)] = struct{}{} + } + + defaultMounts := s.Mounts + s.Mounts = nil + + for _, m := range defaultMounts { + dst := filepath.Clean(m.Destination) + if _, ok := mountSet[dst]; ok { + // filter out mount overridden by a supplied mount + continue + } + if _, mountDev := mountSet["/dev"]; mountDev && strings.HasPrefix(dst, "/dev/") { + // filter out everything under /dev if /dev is a supplied mount + continue + } + s.Mounts = append(s.Mounts, m) + } + + s.Mounts = append(s.Mounts, mounts...) + return nil + } +} + // parseMountFlags parses --volume and --tmpfs. // parseMountFlags will also parse --mount in a future release. func parseMountFlags(cmd *cobra.Command, volStore volumestore.VolumeStore) ([]*mountutil.Processed, error) { @@ -84,6 +118,7 @@ func generateMountOpts(cmd *cobra.Command, ctx context.Context, client *containe var ( opts []oci.SpecOpts anonVolumes []string + userMounts []specs.Mount ) mounted := make(map[string]struct{}) var imageVolumes map[string]struct{} @@ -181,7 +216,7 @@ func generateMountOpts(cmd *cobra.Command, ctx context.Context, client *containe } opts = append(opts, x.Opts...) } - opts = append(opts, oci.WithMounts(ociMounts)) + userMounts = append(userMounts, ociMounts...) } // imageVolumes are defined in Dockerfile "VOLUME" instruction @@ -213,19 +248,17 @@ func generateMountOpts(cmd *cobra.Command, ctx context.Context, client *containe return nil, nil, err } - m := []specs.Mount{ - { - Type: "none", - Source: anonVol.Mountpoint, - Destination: imgVol, - Options: []string{"rbind"}, - }, + m := specs.Mount{ + Type: "none", + Source: anonVol.Mountpoint, + Destination: imgVol, + Options: []string{"rbind"}, } - - opts = append(opts, oci.WithMounts(m)) + userMounts = append(userMounts, m) anonVolumes = append(anonVolumes, anonVolName) } + opts = append(opts, withMounts(userMounts)) return opts, anonVolumes, nil } diff --git a/cmd/nerdctl/run_mount_linux_test.go b/cmd/nerdctl/run_mount_linux_test.go index b50cd211e63..725c5901ec6 100644 --- a/cmd/nerdctl/run_mount_linux_test.go +++ b/cmd/nerdctl/run_mount_linux_test.go @@ -226,6 +226,10 @@ func TestRunTmpfs(t *testing.T) { base := testutil.NewBase(t) f := func(allow, deny []string) func(stdout string) error { return func(stdout string) error { + lines := strings.Split(strings.TrimSpace(stdout), "\n") + if len(lines) != 1 { + return fmt.Errorf("expected 1 lines, got %q", stdout) + } for _, s := range allow { if !strings.Contains(stdout, s) { return fmt.Errorf("expected stdout to contain %q, got %q", s, stdout) @@ -241,4 +245,6 @@ func TestRunTmpfs(t *testing.T) { } base.Cmd("run", "--rm", "--tmpfs", "/tmp", testutil.AlpineImage, "grep", "/tmp", "/proc/mounts").AssertOutWithFunc(f([]string{"rw", "nosuid", "nodev", "noexec"}, nil)) base.Cmd("run", "--rm", "--tmpfs", "/tmp:size=64m,exec", testutil.AlpineImage, "grep", "/tmp", "/proc/mounts").AssertOutWithFunc(f([]string{"rw", "nosuid", "nodev", "size=65536k"}, []string{"noexec"})) + // for https://github.com/containerd/nerdctl/issues/594 + base.Cmd("run", "--rm", "--tmpfs", "/dev/shm:rw,exec,size=1g", testutil.AlpineImage, "grep", "/dev/shm", "/proc/mounts").AssertOutWithFunc(f([]string{"rw", "nosuid", "nodev", "size=1048576k"}, []string{"noexec"})) }