diff --git a/go.mod b/go.mod index 570e318e550bf..5a33f49cedd2e 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf github.com/cristalhq/hedgedhttp v0.9.1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc - github.com/docker/docker v28.0.2+incompatible + github.com/docker/docker v28.0.4+incompatible github.com/docker/go-plugins-helpers v0.0.0-20240701071450-45e2431495c8 github.com/drone/envsubst v1.0.3 github.com/dustin/go-humanize v1.0.1 diff --git a/go.sum b/go.sum index 0b7d5e1b0b373..c30f70b1f91e8 100644 --- a/go.sum +++ b/go.sum @@ -350,8 +350,8 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo= github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/docker/docker v28.0.2+incompatible h1:9BILleFwug5FSSqWBgVevgL3ewDJfWWWyZVqlDMttE8= -github.com/docker/docker v28.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v28.0.4+incompatible h1:JNNkBctYKurkw6FrHfKqY0nKIDf5nrbxjVBtS+cdcok= +github.com/docker/docker v28.0.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= diff --git a/vendor/github.com/docker/docker/pkg/atomicwriter/atomicwriter.go b/vendor/github.com/docker/docker/pkg/atomicwriter/atomicwriter.go index abf46275318c0..e8aa78071f9ba 100644 --- a/vendor/github.com/docker/docker/pkg/atomicwriter/atomicwriter.go +++ b/vendor/github.com/docker/docker/pkg/atomicwriter/atomicwriter.go @@ -1,16 +1,75 @@ package atomicwriter import ( + "errors" + "fmt" "io" "os" "path/filepath" ) +func validateDestination(fileName string) error { + if fileName == "" { + return errors.New("file name is empty") + } + + // Deliberately using Lstat here to match the behavior of [os.Rename], + // which is used when completing the write and does not resolve symlinks. + // + // TODO(thaJeztah): decide whether we want to disallow symlinks or to follow them. + if fi, err := os.Lstat(fileName); err != nil { + if !os.IsNotExist(err) { + return fmt.Errorf("failed to stat output path: %w", err) + } + } else if err := validateFileMode(fi.Mode()); err != nil { + return err + } + if dir := filepath.Dir(fileName); dir != "" && dir != "." { + if _, err := os.Stat(dir); errors.Is(err, os.ErrNotExist) { + return fmt.Errorf("invalid file path: %w", err) + } + } + return nil +} + +func validateFileMode(mode os.FileMode) error { + switch { + case mode.IsRegular(): + return nil // Regular file + case mode&os.ModeDir != 0: + return errors.New("cannot write to a directory") + // TODO(thaJeztah): decide whether we want to disallow symlinks or to follow them. + // case mode&os.ModeSymlink != 0: + // return errors.New("cannot write to a symbolic link directly") + case mode&os.ModeNamedPipe != 0: + return errors.New("cannot write to a named pipe (FIFO)") + case mode&os.ModeSocket != 0: + return errors.New("cannot write to a socket") + case mode&os.ModeDevice != 0: + if mode&os.ModeCharDevice != 0 { + return errors.New("cannot write to a character device file") + } + return errors.New("cannot write to a block device file") + case mode&os.ModeSetuid != 0: + return errors.New("cannot write to a setuid file") + case mode&os.ModeSetgid != 0: + return errors.New("cannot write to a setgid file") + case mode&os.ModeSticky != 0: + return errors.New("cannot write to a sticky bit file") + default: + // Unknown file mode; let's assume it works + return nil + } +} + // New returns a WriteCloser so that writing to it writes to a // temporary file and closing it atomically changes the temporary file to // destination path. Writing and closing concurrently is not allowed. // NOTE: umask is not considered for the file's permissions. func New(filename string, perm os.FileMode) (io.WriteCloser, error) { + if err := validateDestination(filename); err != nil { + return nil, err + } abspath, err := filepath.Abs(filename) if err != nil { return nil, err @@ -49,10 +108,12 @@ type atomicFileWriter struct { f *os.File fn string writeErr error + written bool perm os.FileMode } func (w *atomicFileWriter) Write(dt []byte) (int, error) { + w.written = true n, err := w.f.Write(dt) if err != nil { w.writeErr = err @@ -62,12 +123,12 @@ func (w *atomicFileWriter) Write(dt []byte) (int, error) { func (w *atomicFileWriter) Close() (retErr error) { defer func() { - if retErr != nil || w.writeErr != nil { - os.Remove(w.f.Name()) + if err := os.Remove(w.f.Name()); !errors.Is(err, os.ErrNotExist) && retErr == nil { + retErr = err } }() if err := w.f.Sync(); err != nil { - w.f.Close() + _ = w.f.Close() return err } if err := w.f.Close(); err != nil { @@ -76,7 +137,7 @@ func (w *atomicFileWriter) Close() (retErr error) { if err := os.Chmod(w.f.Name(), w.perm); err != nil { return err } - if w.writeErr == nil { + if w.writeErr == nil && w.written { return os.Rename(w.f.Name(), w.fn) } return nil diff --git a/vendor/modules.txt b/vendor/modules.txt index 723efd1d5da09..03584e6bd0a37 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -623,7 +623,7 @@ github.com/distribution/reference ## explicit; go 1.13 github.com/dlclark/regexp2 github.com/dlclark/regexp2/syntax -# github.com/docker/docker v28.0.2+incompatible +# github.com/docker/docker v28.0.4+incompatible ## explicit github.com/docker/docker/api github.com/docker/docker/api/types