diff --git a/src/bpm/runc/adapter/adapter.go b/src/bpm/runc/adapter/adapter.go index e99d36c0..0add5cd6 100644 --- a/src/bpm/runc/adapter/adapter.go +++ b/src/bpm/runc/adapter/adapter.go @@ -20,6 +20,7 @@ import ( "fmt" "os" "path/filepath" + "slices" "strings" "code.cloudfoundry.org/bytefmt" @@ -232,11 +233,11 @@ func (a *RuncAdapter) BuildSpec( ms.addMounts(boshMounts) ms.addMounts(userProvidedIdentityMounts(bpmCfg, procCfg.AdditionalVolumes)) if procCfg.Unsafe != nil && len(procCfg.Unsafe.UnrestrictedVolumes) > 0 { - expanded, err := a.globExpandVolumes(procCfg.Unsafe.UnrestrictedVolumes) + expandUnrestrictedVolumes, err := a.globExpandVolumes(procCfg.Unsafe.UnrestrictedVolumes) if err != nil { return specs.Spec{}, err } - filteredVolumes := filterVolumesUnderBoshMounts(boshMounts, expanded) + filteredVolumes := filterVolumesUnderBoshMounts(boshMounts, expandUnrestrictedVolumes) ms.addMounts(userProvidedIdentityMounts(bpmCfg, filteredVolumes)) } @@ -288,13 +289,23 @@ func (a *RuncAdapter) BuildSpec( return *spec, nil } -func filterVolumesUnderBoshMounts(mounts []specs.Mount, volumes []config.Volume) []config.Volume { +func filterVolumesUnderBoshMounts(boshMounts []specs.Mount, unrestrictedVolumes []config.Volume) []config.Volume { var filteredVolumes []config.Volume - for _, v := range volumes { + for _, v := range unrestrictedVolumes { keep := true - for _, m := range mounts { - if strings.HasPrefix(v.Path, m.Destination) { - keep = false + for _, m := range boshMounts { + // Check to see whether the "directory parts" of the volume are a sub-set of and existing BPM-default + // directory (that will already be mounted) so that we do not accidentally filter out mounts which + // have a name that is a sub-string of the existing job. For example the job `service-metrics` should be + // able to have an unrestricted volume mount of the `service-metrics-adapter` job directory. + boshMountDirParts := strings.Split(m.Destination, fmt.Sprintf("%c", filepath.Separator)) + volumeDirParts := strings.Split(v.Path, fmt.Sprintf("%c", filepath.Separator)) + + if len(boshMountDirParts) <= len(volumeDirParts) { + volumeDirPartsPrefix := volumeDirParts[:len(boshMountDirParts)] + if slices.Compare(boshMountDirParts, volumeDirPartsPrefix) == 0 { + keep = false + } } } diff --git a/src/bpm/runc/adapter/adapter_test.go b/src/bpm/runc/adapter/adapter_test.go index f33e7688..347f7b77 100644 --- a/src/bpm/runc/adapter/adapter_test.go +++ b/src/bpm/runc/adapter/adapter_test.go @@ -869,7 +869,8 @@ var _ = Describe("RuncAdapter", func() { {Path: "/this/is/an/unrestricted/path"}, {Path: "/writable/executable/path", Writable: true, AllowExecutions: true}, {Path: "/var/vcap/jobs/example/config/config.yml", MountOnly: true}, - {Path: "/var/vcap/jobs/other/config/config.yml", MountOnly: true}, + {Path: "/var/vcap/jobs/other/config/config.yml", MountOnly: true, AllowExecutions: true}, + {Path: "/var/vcap/jobs/example-two/config/config.yml", MountOnly: true, AllowExecutions: true}, }, } }) @@ -894,7 +895,13 @@ var _ = Describe("RuncAdapter", func() { Destination: "/var/vcap/jobs/other/config/config.yml", Type: "bind", Source: "/var/vcap/jobs/other/config/config.yml", - Options: []string{"nodev", "nosuid", "noexec", "rbind", "ro"}, + Options: []string{"nodev", "nosuid", "rbind", "exec", "ro"}, + })) + Expect(spec.Mounts).To(HaveMount(specs.Mount{ + Destination: "/var/vcap/jobs/example-two/config/config.yml", + Type: "bind", + Source: "/var/vcap/jobs/example-two/config/config.yml", + Options: []string{"nodev", "nosuid", "rbind", "exec", "ro"}, })) })