diff options
-rw-r--r-- | internal/jail/jail.go | 4 | ||||
-rw-r--r-- | internal/jail/jail_test.go | 28 |
2 files changed, 31 insertions, 1 deletions
diff --git a/internal/jail/jail.go b/internal/jail/jail.go index 22f22eac..a565fada 100644 --- a/internal/jail/jail.go +++ b/internal/jail/jail.go @@ -115,7 +115,9 @@ func (j *Jail) removeAll() error { } } - for _, dest := range j.directories { + // Iterate directories in reverse to remove children before parents + for i := len(j.directories) - 1; i >= 0; i-- { + dest := j.directories[i] if err := os.Remove(dest.path); err != nil { return fmt.Errorf("Can't delete directory in jail %q: %s", dest.path, err) } diff --git a/internal/jail/jail_test.go b/internal/jail/jail_test.go index 27282cae..6736816d 100644 --- a/internal/jail/jail_test.go +++ b/internal/jail/jail_test.go @@ -316,3 +316,31 @@ func TestJailIntoOnlyCleansSubpaths(t *testing.T) { _, err = os.Stat(jailPath) require.NoError(t, err, "/ in jail (corresponding to external directory) was removed") } + +func TestJailIntoCleansNestedDirs(t *testing.T) { + jailPath := tmpJailPath() + require.NoError(t, os.MkdirAll(jailPath, 0755)) + defer os.RemoveAll(jailPath) + + chroot := jail.Into(jailPath) + + // These need to be cleaned up in reverse order + chroot.MkDir("/way", 0755) + chroot.MkDir("/way/down", 0755) + chroot.MkDir("/way/down/here", 0755) + + require.NoError(t, chroot.Build()) + require.NoError(t, chroot.Dispose()) + + verify := func(inPath string) { + _, err := os.Stat(path.Join(jailPath, inPath)) + require.True(t, os.IsNotExist(err), "{} in jail was not removed", inPath) + } + + verify("/way") + verify("/way/down") + verify("/way/down/here") + + _, err := os.Stat(jailPath) + require.NoError(t, err, "/ in jail (corresponding to external directory) was removed") +} |