server(filesystem): fix archives in subdirectories

When creating an archive starting from a subdirectory instead of the
root of a server's filesystem, the walker would treat the paths as if
they where relative to the parent of the subdirectory, instead of as
descendants of the subdirectory.

Fixes https://github.com/pterodactyl/panel/issues/5030
This commit is contained in:
Matthew Penner 2024-03-14 13:46:36 -06:00
parent 979df34392
commit ac9bd1d95e
No known key found for this signature in database
2 changed files with 30 additions and 0 deletions

View File

@ -66,6 +66,13 @@ func (fs *UnixFS) walkDir(b []byte, parentfd int, name, relative string, d DirEn
}
for _, d1 := range dirs {
// TODO: the path.Join on this line may actually be partially incorrect.
// If we are not walking starting at the root, relative will contain the
// name of the directory we are starting the walk from, which will be
// relative to the root of the filesystem instead of from where the walk
// was initiated from.
//
// ref; https://github.com/pterodactyl/panel/issues/5030
if err := fs.walkDir(b, dirfd, d1.Name(), path.Join(relative, d1.Name()), d1, walkDirFn); err != nil {
if err == SkipDir {
break

View File

@ -113,6 +113,10 @@ func (a *Archive) Stream(ctx context.Context, w io.Writer) error {
return errors.New("filesystem: archive.Filesystem is unset")
}
// The base directory may come with a prefixed `/`, strip it to prevent
// problems.
a.BaseDirectory = strings.TrimPrefix(a.BaseDirectory, "/")
if filesLen := len(a.Files); filesLen > 0 {
files := make([]string, filesLen)
for i, f := range a.Files {
@ -167,11 +171,14 @@ func (a *Archive) Stream(ctx context.Context, w io.Writer) error {
callback = a.callback()
}
// Open the base directory we were provided.
dirfd, name, closeFd, err := fs.SafePath(a.BaseDirectory)
defer closeFd()
if err != nil {
return err
}
// Recursively walk the base directory.
return fs.WalkDirat(dirfd, name, func(dirfd int, name, relative string, d ufs.DirEntry, err error) error {
if err != nil {
return err
@ -188,12 +195,28 @@ func (a *Archive) Stream(ctx context.Context, w io.Writer) error {
// Callback function used to determine if a given file should be included in the archive
// being generated.
func (a *Archive) callback(opts ...walkFunc) walkFunc {
// Get the base directory we need to strip when walking.
//
// This is important as when we are walking, the last part of the base directory
// is present on all the paths we walk.
var base string
if a.BaseDirectory != "" {
base = filepath.Base(a.BaseDirectory) + "/"
}
return func(dirfd int, name, relative string, d ufs.DirEntry) error {
// Skip directories because we are walking them recursively.
if d.IsDir() {
return nil
}
// If base isn't empty, strip it from the relative path. This fixes an
// issue when creating an archive starting from a nested directory.
//
// See https://github.com/pterodactyl/panel/issues/5030 for more details.
if base != "" {
relative = strings.TrimPrefix(relative, base)
}
// Call the additional options passed to this callback function. If any of them return
// a non-nil error we will exit immediately.
for _, opt := range opts {