Skip to content

Commit 7a6af83

Browse files
csi: fix check of StagePublishBaseDir being subdirectory of MountDir
backport of commit a4f577f (#27905) Co-authored-by: Allison Larson <allison.larson@hashicorp.com>
1 parent 82c0487 commit 7a6af83

5 files changed

Lines changed: 42 additions & 1 deletion

File tree

.changelog/27717.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:bug
2+
csi: improve check of StagePublishBaseDir being subdirectory of MountDir
3+
```

helper/funcs.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,3 +568,12 @@ func FindExecutableFiles(path string) (map[string]string, error) {
568568
}
569569
return executables, nil
570570
}
571+
572+
// IsSubdirectory returns true if potentialParent is equal to or a parent directory of path.
573+
func IsSubdirectory(potentialParent, path string) bool {
574+
rel, err := filepath.Rel(potentialParent, path)
575+
if err != nil {
576+
return false
577+
}
578+
return !strings.HasPrefix(rel, "..")
579+
}

helper/funcs_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,3 +528,23 @@ func TestFlattenMultiError(t *testing.T) {
528528
529529
`, err.Error())
530530
}
531+
532+
func TestIsSubdirectory(t *testing.T) {
533+
cases := []struct {
534+
potentialParent string
535+
path string
536+
expected bool
537+
}{
538+
{potentialParent: "/dir", path: "/dir/local", expected: true},
539+
{potentialParent: "/dir", path: "/other", expected: false},
540+
{potentialParent: "/dir", path: "/directory", expected: false},
541+
{potentialParent: "/dir", path: "/directory/../dir/local", expected: true},
542+
}
543+
544+
for _, tc := range cases {
545+
t.Run(fmt.Sprintf("parent=%q path=%q", tc.potentialParent, tc.path), func(t *testing.T) {
546+
result := IsSubdirectory(tc.potentialParent, tc.path)
547+
require.Equal(t, tc.expected, result)
548+
})
549+
}
550+
}

nomad/structs/structs.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8357,7 +8357,7 @@ func (t *Task) Validate(jobType string, tg *TaskGroup) error {
83578357
}
83588358

83598359
if t.CSIPluginConfig.StagePublishBaseDir != "" && t.CSIPluginConfig.MountDir != "" &&
8360-
strings.HasPrefix(t.CSIPluginConfig.StagePublishBaseDir, t.CSIPluginConfig.MountDir) {
8360+
helper.IsSubdirectory(t.CSIPluginConfig.MountDir, t.CSIPluginConfig.StagePublishBaseDir) {
83618361
mErr.Errors = append(mErr.Errors, fmt.Errorf("CSIPluginConfig StagePublishBaseDir must not be a subdirectory of MountDir, got: StagePublishBaseDir=\"%s\" MountDir=\"%s\"", t.CSIPluginConfig.StagePublishBaseDir, t.CSIPluginConfig.MountDir))
83628362
}
83638363

nomad/structs/structs_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3369,6 +3369,15 @@ func TestTask_Validate_CSIPluginConfig(t *testing.T) {
33693369
},
33703370
expectedErr: "CSIPluginConfig StagePublishBaseDir must not be a subdirectory of MountDir, got: StagePublishBaseDir=\"/csi/local\" MountDir=\"/csi\"",
33713371
},
3372+
{
3373+
name: "handles valid staging publish base dir",
3374+
pc: &TaskCSIPluginConfig{
3375+
ID: "com.hashicorp.csi",
3376+
Type: "monolith",
3377+
MountDir: "/csi",
3378+
StagePublishBaseDir: "/csilocal",
3379+
},
3380+
},
33723381
}
33733382

33743383
for _, tt := range table {

0 commit comments

Comments
 (0)