diff --git a/runsc/boot/mount_hints.go b/runsc/boot/mount_hints.go index 61a076350..6c7817a00 100644 --- a/runsc/boot/mount_hints.go +++ b/runsc/boot/mount_hints.go @@ -153,7 +153,7 @@ func (m *mountHint) setField(key, val string) error { } m.share = share case "options": - return m.setOptions(val) + m.mount.Options = specutils.FilterMountOptions(strings.Split(val, ",")) default: return fmt.Errorf("invalid mount annotation: %s=%s", key, val) } @@ -170,15 +170,6 @@ func (m *mountHint) setType(val string) error { return nil } -func (m *mountHint) setOptions(val string) error { - opts := strings.Split(val, ",") - if err := specutils.ValidateMountOptions(opts); err != nil { - return err - } - m.mount.Options = opts - return nil -} - func (m *mountHint) isSupported() bool { // TODO(b/142076984): Only support tmpfs for now. Bind mounts require a // common gofer to mount all shared volumes. diff --git a/runsc/boot/mount_hints_test.go b/runsc/boot/mount_hints_test.go index 321fcb2b6..a0a31239a 100644 --- a/runsc/boot/mount_hints_test.go +++ b/runsc/boot/mount_hints_test.go @@ -169,6 +169,25 @@ func TestPodMountHintsIgnore(t *testing.T) { } } +func TestIgnoreInvalidMountOptions(t *testing.T) { + spec := &specs.Spec{ + Annotations: map[string]string{ + MountPrefix + "mount1.source": "foo", + MountPrefix + "mount1.type": "tmpfs", + MountPrefix + "mount1.share": "container", + MountPrefix + "mount1.options": "rw,invalid,private", + }, + } + podHints, err := newPodMountHints(spec) + if err != nil { + t.Fatalf("newPodMountHints failed: %v", err) + } + mount1 := podHints.mounts["mount1"] + if want := []string{"rw", "private"}; !reflect.DeepEqual(want, mount1.mount.Options) { + t.Errorf("mount2 type, want: %q, got: %q", want, mount1.mount.Options) + } +} + func TestHintsCheckCompatible(t *testing.T) { for _, tc := range []struct { name string diff --git a/runsc/specutils/fs.go b/runsc/specutils/fs.go index 2eb92ac89..ff792e728 100644 --- a/runsc/specutils/fs.go +++ b/runsc/specutils/fs.go @@ -22,6 +22,7 @@ import ( specs "github.com/opencontainers/runtime-spec/specs-go" "golang.org/x/sys/unix" + "gvisor.dev/gvisor/pkg/log" ) type mapping struct { @@ -126,24 +127,41 @@ func moptKey(opt string) string { return strings.SplitN(opt, "=", 2)[0] } +// FilterMountOptions filters out all invalid mount options. +func FilterMountOptions(opts []string) []string { + out := make([]string, 0, len(opts)) + for _, o := range opts { + if err := validateMountOption(o); err == nil { + out = append(out, o) + } else { + log.Warningf("mount option skipped %q: %v", o, err) + } + } + return out +} + // ValidateMountOptions validates that mount options are correct. func ValidateMountOptions(opts []string) error { for _, o := range opts { - if ContainsStr(invalidOptions, o) { - return fmt.Errorf("mount option %q is not supported", o) - } - _, ok1 := optionsMap[o] - _, ok2 := propOptionsMap[o] - if !ok1 && !ok2 { - return fmt.Errorf("unknown mount option %q", o) - } - if err := validatePropagation(o); err != nil { + if err := validateMountOption(o); err != nil { return err } } return nil } +func validateMountOption(o string) error { + if ContainsStr(invalidOptions, o) { + return fmt.Errorf("mount option %q is not supported", o) + } + _, ok1 := optionsMap[o] + _, ok2 := propOptionsMap[o] + if !ok1 && !ok2 { + return fmt.Errorf("unknown mount option %q", o) + } + return validatePropagation(o) +} + // ValidateRootfsPropagation validates that rootfs propagation options are // correct. func validateRootfsPropagation(opt string) error {