From 301943c3a5eabba87a7f21c9545ece3defcb828b Mon Sep 17 00:00:00 2001 From: Felicitas Pojtinger Date: Fri, 21 Jan 2022 01:12:05 +0100 Subject: [PATCH] fix: Prevent creating files in place of symlinks to directories --- pkg/fs/filesystem.go | 16 +++++-- pkg/fs/filesystem_test.go | 96 +++++++++++++++++++++++++++++++++++---- 2 files changed, 100 insertions(+), 12 deletions(-) diff --git a/pkg/fs/filesystem.go b/pkg/fs/filesystem.go index 7ff54b7..9a307b6 100644 --- a/pkg/fs/filesystem.go +++ b/pkg/fs/filesystem.go @@ -78,9 +78,6 @@ func (f *STFS) Name() string { "name": config.FileSystemNameSTFS, }) - f.ioLock.Lock() - defer f.ioLock.Unlock() - return config.FileSystemNameSTFS } @@ -442,6 +439,19 @@ func (f *STFS) OpenFile(name string, flag int, perm os.FileMode) (afero.File, er return nil, err } + if target, err := inventory.Stat( + f.metadata, + + name, + true, + + f.onHeader, + ); err == nil { + if target.Typeflag == tar.TypeDir { + return nil, config.ErrIsDirectory + } + } + if err := f.mknodeWithoutLocking(false, name, perm, false, "", false); err != nil { return nil, err } diff --git a/pkg/fs/filesystem_test.go b/pkg/fs/filesystem_test.go index 19f44e8..e260716 100644 --- a/pkg/fs/filesystem_test.go +++ b/pkg/fs/filesystem_test.go @@ -656,36 +656,103 @@ var createTests = []struct { name string args createArgs wantErr bool + prepare func(symFs) error }{ { "Can create file /test.txt", createArgs{"/test.txt"}, false, + func(sf symFs) error { return nil }, }, { "Can create file /test.txt/", createArgs{"/test.txt/"}, false, + func(sf symFs) error { return nil }, }, { - "Can not create existing file/directory /", + "Can not create existing file /", createArgs{"/"}, true, + func(sf symFs) error { return nil }, }, { "Can create file ' '", createArgs{" "}, false, + func(sf symFs) error { return nil }, }, { "Can create file ''", createArgs{""}, true, + func(sf symFs) error { return nil }, }, { "Can not create /nonexistent/test.txt", createArgs{"/nonexistent/test.txt"}, true, + func(sf symFs) error { return nil }, + }, + { + "Can not create file in place of symlink to root", + createArgs{"/existingsymlink"}, + true, + func(sf symFs) error { + if err := sf.SymlinkIfPossible("/", "/existingsymlink"); err != nil { + return nil + } + + return nil + }, + }, + { + "Can create file in place of broken symlink /brokensymlink", + createArgs{"/brokensymlink"}, + false, + func(sf symFs) error { + if err := sf.SymlinkIfPossible("/test.txt", "/brokensymlink"); err != nil { + return nil + } + + return nil + }, + }, + { + "Can create file in place of existing symlink /existingsymlink to file", + createArgs{"/existingsymlink"}, + false, + func(sf symFs) error { + file, err := sf.Create("/test.txt") + if err != nil { + return err + } + if err := file.Close(); err != nil { + return err + } + + if err := sf.SymlinkIfPossible("/test.txt", "/existingsymlink"); err != nil { + return nil + } + + return nil + }, + }, + { + "Can not create file in place of existing symlink /existingsymlink to directory", + createArgs{"/existingsymlink"}, + true, + func(sf symFs) error { + if err := sf.Mkdir("/mydir", os.ModePerm); err != nil { + return err + } + + if err := sf.SymlinkIfPossible("/mydir", "/existingsymlink"); err != nil { + return nil + } + + return nil + }, }, } @@ -694,36 +761,47 @@ func TestSTFS_Create(t *testing.T) { tt := tt runTestForAllFss(t, tt.name, true, true, true, func(t *testing.T, fs fsConfig) { - file, err := fs.fs.Create(tt.args.name) + symFs, ok := fs.fs.(symFs) + if !ok { + return + } + + if err := tt.prepare(symFs); err != nil { + t.Errorf("%v prepare() error = %v", symFs.Name(), err) + + return + } + + file, err := symFs.Create(tt.args.name) if (err != nil) != tt.wantErr { - t.Errorf("%v.Create() error = %v, wantErr %v", fs.fs.Name(), err, tt.wantErr) + t.Errorf("%v.Create() error = %v, wantErr %v", symFs.Name(), err, tt.wantErr) return } if !tt.wantErr { - want, err := fs.fs.Stat(tt.args.name) + want, err := symFs.Stat(tt.args.name) if err != nil { - t.Errorf("%v.Stat() error = %v, wantErr %v", fs.fs.Name(), err, tt.wantErr) + t.Errorf("%v.Stat() error = %v, wantErr %v", symFs.Name(), err, tt.wantErr) return } if file == nil { - t.Errorf("%v.Create() error = %v, wantErr %v", fs.fs.Name(), err, tt.wantErr) + t.Errorf("%v.Create() error = %v, wantErr %v", symFs.Name(), err, tt.wantErr) return } - got, err := fs.fs.Stat(file.Name()) + got, err := symFs.Stat(file.Name()) if err != nil { - t.Errorf("%v.Stat() error = %v, wantErr %v", fs.fs.Name(), err, tt.wantErr) + t.Errorf("%v.Stat() error = %v, wantErr %v", symFs.Name(), err, tt.wantErr) return } if !reflect.DeepEqual(got, want) { - t.Errorf("%v.Create().Name() = %v, want %v", fs.fs.Name(), got, want) + t.Errorf("%v.Create().Name() = %v, want %v", symFs.Name(), got, want) return }