From 1f363a386c6d97a60c61dae88a992b9eb57858bb Mon Sep 17 00:00:00 2001 From: liubin Date: Wed, 29 Jun 2022 16:43:16 +0800 Subject: [PATCH] runtime: overwrite mount type to bind for bind mounts Some clients like nerdctl may pass mount type of none for volumes/bind mounts, this will lead to container start fails. Referring to runc, it overwrites the mount type to bind and ignores the input value. Fixes: #4548 Signed-off-by: liubin --- src/runtime/pkg/oci/utils.go | 20 +++++--- src/runtime/pkg/oci/utils_test.go | 76 +++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 6 deletions(-) diff --git a/src/runtime/pkg/oci/utils.go b/src/runtime/pkg/oci/utils.go index 71423cf0cc..53503b3222 100644 --- a/src/runtime/pkg/oci/utils.go +++ b/src/runtime/pkg/oci/utils.go @@ -187,16 +187,27 @@ func cmdEnvs(spec specs.Spec, envs []types.EnvVar) []types.EnvVar { func newMount(m specs.Mount) vc.Mount { readonly := false + bind := false for _, flag := range m.Options { - if flag == "ro" { + switch flag { + case "rbind", "bind": + bind = true + case "ro": readonly = true - break } } + + // normal bind mounts, set type to bind. + // https://github.com/opencontainers/runc/blob/v1.1.3/libcontainer/specconv/spec_linux.go#L512-L520 + mountType := m.Type + if mountType != vc.KataEphemeralDevType && mountType != vc.KataLocalDevType && bind { + mountType = "bind" + } + return vc.Mount{ Source: m.Source, Destination: m.Destination, - Type: m.Type, + Type: mountType, Options: m.Options, ReadOnly: readonly, } @@ -913,9 +924,6 @@ func SandboxConfig(ocispec specs.Spec, runtime RuntimeConfig, bundlePath, cid, c DisableGuestSeccomp: runtime.DisableGuestSeccomp, - // Q: Is this really necessary? @weizhang555 - // Spec: &ocispec, - Experimental: runtime.Experimental, } diff --git a/src/runtime/pkg/oci/utils_test.go b/src/runtime/pkg/oci/utils_test.go index 2ddd42d111..7caa51aa28 100644 --- a/src/runtime/pkg/oci/utils_test.go +++ b/src/runtime/pkg/oci/utils_test.go @@ -1210,3 +1210,79 @@ func TestCalculateSandboxSizing(t *testing.T) { assert.Equal(tt.expectedMem, mem, "unexpected memory") } } + +func TestNewMount(t *testing.T) { + assert := assert.New(t) + + testCases := []struct { + out vc.Mount + in specs.Mount + }{ + { + in: specs.Mount{ + Source: "proc", + Destination: "/proc", + Type: "proc", + Options: nil, + }, + out: vc.Mount{ + Source: "proc", + Destination: "/proc", + Type: "proc", + Options: nil, + }, + }, + { + in: specs.Mount{ + Source: "proc", + Destination: "/proc", + Type: "proc", + Options: []string{"ro"}, + }, + out: vc.Mount{ + Source: "proc", + Destination: "/proc", + Type: "proc", + Options: []string{"ro"}, + ReadOnly: true, + }, + }, + { + in: specs.Mount{ + Source: "/abc", + Destination: "/def", + Type: "none", + Options: []string{"bind"}, + }, + out: vc.Mount{ + Source: "/abc", + Destination: "/def", + Type: "bind", + Options: []string{"bind"}, + }, + }, { + in: specs.Mount{ + Source: "/abc", + Destination: "/def", + Type: "none", + Options: []string{"rbind"}, + }, + out: vc.Mount{ + Source: "/abc", + Destination: "/def", + Type: "bind", + Options: []string{"rbind"}, + }, + }, + } + + for _, tt := range testCases { + actualMount := newMount(tt.in) + + assert.Equal(tt.out.Source, actualMount.Source, "unexpected mount source") + assert.Equal(tt.out.Destination, actualMount.Destination, "unexpected mount destination") + assert.Equal(tt.out.Type, actualMount.Type, "unexpected mount type") + assert.Equal(tt.out.Options, actualMount.Options, "unexpected mount options") + assert.Equal(tt.out.ReadOnly, actualMount.ReadOnly, "unexpected mount ReadOnly") + } +}