fix: Block creating files with non-existing parent directories using O_CREATE

This commit is contained in:
Felicitas Pojtinger
2022-01-12 22:39:00 +01:00
parent 5ed0eec75e
commit 3a0165895a
3 changed files with 34 additions and 20 deletions

View File

@@ -193,7 +193,7 @@ var serveFTPCmd = &cobra.Command{
) )
}, },
viper.GetBool(readOnlyFlag), viper.GetBool(readOnlyFlag),
true, // FTP requires read permission even if `O_WRONLY` is set if cache is enabled true, // FTP requires read permission even if `O_WRONLY` is set if cache is enabled, as the cache needs to read the written file
func(hdr *config.Header) { func(hdr *config.Header) {
jsonLogger.Trace("Header transform", hdr) jsonLogger.Trace("Header transform", hdr)

View File

@@ -31,10 +31,10 @@ type STFS struct {
metadata config.MetadataConfig metadata config.MetadataConfig
compressionLevel string compressionLevel string
getFileBuffer func() (cache.WriteCache, func() error, error) getFileBuffer func() (cache.WriteCache, func() error, error)
readOnly bool readOnly bool
writeImpliesRead bool writePermImpliesReadPerm bool
ioLock sync.Mutex ioLock sync.Mutex
@@ -51,7 +51,7 @@ func NewSTFS(
compressionLevel string, compressionLevel string,
getFileBuffer func() (cache.WriteCache, func() error, error), getFileBuffer func() (cache.WriteCache, func() error, error),
readOnly bool, readOnly bool,
writeImpliesRead bool, writePermImpliesReadPerm bool,
onHeader func(hdr *config.Header), onHeader func(hdr *config.Header),
log logging.StructuredLogger, log logging.StructuredLogger,
@@ -62,10 +62,10 @@ func NewSTFS(
metadata: metadata, metadata: metadata,
compressionLevel: compressionLevel, compressionLevel: compressionLevel,
getFileBuffer: getFileBuffer, getFileBuffer: getFileBuffer,
readOnly: readOnly, readOnly: readOnly,
writeImpliesRead: writeImpliesRead, writePermImpliesReadPerm: writePermImpliesReadPerm,
onHeader: onHeader, onHeader: onHeader,
log: log, log: log,
@@ -376,7 +376,7 @@ func (f *STFS) OpenFile(name string, flag int, perm os.FileMode) (afero.File, er
if (flag & O_ACCMODE) == os.O_RDONLY { if (flag & O_ACCMODE) == os.O_RDONLY {
flags.Read = true flags.Read = true
} else if (flag & O_ACCMODE) == os.O_WRONLY { } else if (flag & O_ACCMODE) == os.O_WRONLY {
if f.writeImpliesRead { if f.writePermImpliesReadPerm {
flags.Read = true flags.Read = true
} }
@@ -406,6 +406,21 @@ func (f *STFS) OpenFile(name string, flag int, perm os.FileMode) (afero.File, er
if err != nil { if err != nil {
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
if !f.readOnly && flag&os.O_CREATE != 0 && flag&os.O_EXCL == 0 { if !f.readOnly && flag&os.O_CREATE != 0 && flag&os.O_EXCL == 0 {
if _, err := inventory.Stat(
f.metadata,
filepath.Dir(name),
false,
f.onHeader,
); err != nil {
if err == sql.ErrNoRows {
return nil, os.ErrNotExist
}
return nil, err
}
if err := f.mknodeWithoutLocking(false, name, perm, false, "", false); err != nil { if err := f.mknodeWithoutLocking(false, name, perm, false, "", false); err != nil {
return nil, err return nil, err
} }

View File

@@ -1114,15 +1114,14 @@ var openFileTests = []struct {
func(f afero.File) error { return nil }, func(f afero.File) error { return nil },
false, false,
}, },
// FIXME: STFS can create file in non-existent directory, which should not be possible {
// { "Can not open /mydir/test.txt if O_CREATE is set",
// "Can not open /mydir/test.txt if O_CREATE is set", openFileArgs{"/mydir/test.txt", os.O_CREATE, os.ModePerm},
// openFileArgs{"/mydir/test.txt", os.O_CREATE, os.ModePerm}, true,
// true, func(f afero.Fs) error { return nil },
// func(f afero.Fs) error { return nil }, func(f afero.File) error { return nil },
// func(f afero.File) error { return nil }, false,
// false, },
// },
{ {
"Can open /mydir/test.txt after creating it", "Can open /mydir/test.txt after creating it",
openFileArgs{"/mydir/test.txt", os.O_RDONLY, 0}, openFileArgs{"/mydir/test.txt", os.O_RDONLY, 0},