Validate downloads before installing workspace files

This commit is contained in:
2026-09-02 00:37:00 +00:00
parent ba858cc997
commit 39b2665d8b
13 changed files with 204 additions and 665 deletions

View File

@@ -5,7 +5,6 @@ import (
"encoding/hex"
"errors"
"fmt"
"io"
"os"
"path/filepath"
"strings"
@@ -325,232 +324,3 @@ func validateOpenedConfinedFile(parent *os.Root, name string, file *os.File) (*o
}
return file, nil
}
// DownloadedTempFile is a completed, destination-confined temporary file. It
// keeps its parent directory open until the caller installs or cleans it up.
type DownloadedTempFile struct {
parent *os.Root
name string
}
// DownloadToSiblingTemp writes a remote object into a sibling temporary file.
// The caller supplies transport behavior through download and retains object
// identity and validation policy. The destination parent must already exist.
func DownloadToSiblingTemp(destination string, download func(io.Writer) error) (*DownloadedTempFile, error) {
if download == nil {
return nil, fmt.Errorf("download function is required")
}
parent, name, err := openConfinedParent(destination, false, 0)
if err != nil {
return nil, err
}
file, tempName, err := createSiblingTemp(parent, name)
if err != nil {
_ = parent.Close()
return nil, fmt.Errorf("create sibling temporary file: %w", err)
}
if err := download(file); err != nil {
_ = file.Close()
_ = parent.Remove(tempName)
_ = parent.Close()
return nil, err
}
if err := file.Sync(); err != nil {
_ = file.Close()
_ = parent.Remove(tempName)
_ = parent.Close()
return nil, fmt.Errorf("sync downloaded temporary file: %w", err)
}
if err := file.Close(); err != nil {
_ = parent.Remove(tempName)
_ = parent.Close()
return nil, fmt.Errorf("close downloaded temporary file: %w", err)
}
return &DownloadedTempFile{parent: parent, name: tempName}, nil
}
// Open returns a read handle for validation before installation.
func (f *DownloadedTempFile) Open() (*os.File, error) {
if f == nil || f.parent == nil || f.name == "" {
return nil, fmt.Errorf("downloaded temporary file is unavailable")
}
return f.parent.Open(f.name)
}
// Install atomically replaces destinationName in the opened parent directory.
func (f *DownloadedTempFile) Install(destinationName string, mode os.FileMode) error {
if f == nil || f.parent == nil || f.name == "" {
return fmt.Errorf("downloaded temporary file is unavailable")
}
if filepath.Base(destinationName) != destinationName || destinationName == "." || destinationName == "" {
return fmt.Errorf("destination file name is required")
}
file, err := f.parent.Open(f.name)
if err != nil {
return fmt.Errorf("open downloaded temporary file: %w", err)
}
if err := file.Chmod(mode); err != nil {
_ = file.Close()
return fmt.Errorf("set downloaded temporary file permissions: %w", err)
}
if err := file.Sync(); err != nil {
_ = file.Close()
return fmt.Errorf("sync downloaded temporary file: %w", err)
}
if err := file.Close(); err != nil {
return fmt.Errorf("close downloaded temporary file: %w", err)
}
if err := f.parent.Rename(f.name, destinationName); err != nil {
return fmt.Errorf("install downloaded temporary file: %w", err)
}
f.name = ""
if err := syncOpenedDirectory(f.parent); err != nil {
return fmt.Errorf("sync destination directory after downloaded-file replacement: %w", err)
}
return f.closeParent()
}
// Cleanup removes an uninstalled temporary file. It is safe to call repeatedly.
func (f *DownloadedTempFile) Cleanup() error {
if f == nil || f.parent == nil {
return nil
}
var err error
if f.name != "" {
err = f.parent.Remove(f.name)
if errors.Is(err, os.ErrNotExist) {
err = nil
}
f.name = ""
}
closeErr := f.closeParent()
if err != nil && closeErr != nil {
return errors.Join(err, closeErr)
}
if err != nil {
return err
}
return closeErr
}
func (f *DownloadedTempFile) closeParent() error {
if f.parent == nil {
return nil
}
err := f.parent.Close()
f.parent = nil
return err
}
// DownloadAndInstall obtains remote bytes through a confined sibling temporary
// file and installs them with the caller-selected final mode.
func DownloadAndInstall(destination string, mode os.FileMode, download func(io.Writer) error) error {
temporary, err := DownloadToSiblingTemp(destination, download)
if err != nil {
return err
}
defer func() { _ = temporary.Cleanup() }()
return temporary.Install(filepath.Base(destination), mode)
}
func replaceFileFromReaderConfined(dst string, source io.Reader, options ReplaceFileOptions) (resultErr error) {
parent, name, err := openConfinedParent(dst, false, 0)
if err != nil {
return err
}
defer func() { _ = parent.Close() }()
temporary, tempName, err := createSiblingTemp(parent, name)
if err != nil {
return fmt.Errorf("create temp file: %w", err)
}
removeTemp := true
defer func() {
if removeTemp {
if err := parent.Remove(tempName); err != nil && !errors.Is(err, os.ErrNotExist) {
resultErr = errors.Join(resultErr, fmt.Errorf("remove temporary file: %w", err))
}
}
}()
if _, err := io.Copy(temporary, source); err != nil {
return closeTemporaryFileAfterError(temporary, fmt.Errorf("write temp file: %w", err))
}
if err := temporary.Chmod(options.Mode); err != nil {
return closeTemporaryFileAfterError(temporary, fmt.Errorf("set temp file permissions: %w", err))
}
if err := temporary.Sync(); err != nil {
return closeTemporaryFileAfterError(temporary, fmt.Errorf("sync temp file: %w", err))
}
if err := temporary.Close(); err != nil {
return fmt.Errorf("close temp file: %w", err)
}
if options.BeforeRename != nil {
if err := options.BeforeRename(); err != nil {
return fmt.Errorf("check before file replacement: %w", err)
}
}
if err := parent.Rename(tempName, name); err != nil {
return fmt.Errorf("install temp file: %w", err)
}
removeTemp = false
if err := syncOpenedDirectory(parent); err != nil {
return fmt.Errorf("sync destination directory after replacement: %w", err)
}
return nil
}
func installDownloadedTempFileConfined(tmpPath, dst string, mode os.FileMode) error {
if filepath.Clean(filepath.Dir(tmpPath)) != filepath.Clean(filepath.Dir(dst)) {
source, err := os.Open(tmpPath)
if err != nil {
return fmt.Errorf("open downloaded temporary file: %w", err)
}
err = replaceFileFromReaderConfined(dst, source, ReplaceFileOptions{Mode: mode})
closeErr := source.Close()
if err != nil {
return fmt.Errorf("install downloaded file: %w", err)
}
if closeErr != nil {
return fmt.Errorf("close downloaded temporary file: %w", closeErr)
}
if err := os.Remove(tmpPath); err != nil {
return fmt.Errorf("remove installed temporary file: %w", err)
}
return nil
}
parent, destinationName, err := openConfinedParent(dst, false, 0)
if err != nil {
return err
}
defer func() { _ = parent.Close() }()
temporaryName := filepath.Base(tmpPath)
info, err := parent.Lstat(temporaryName)
if err != nil {
return fmt.Errorf("inspect downloaded temporary file: %w", err)
}
if info.Mode()&os.ModeSymlink != 0 || !info.Mode().IsRegular() {
return fmt.Errorf("downloaded temporary file is not a regular file")
}
file, err := parent.Open(temporaryName)
if err != nil {
return fmt.Errorf("open downloaded temporary file: %w", err)
}
if err := file.Chmod(mode); err != nil {
_ = file.Close()
return fmt.Errorf("set temp file permissions: %w", err)
}
if err := file.Sync(); err != nil {
_ = file.Close()
return fmt.Errorf("sync downloaded temp file: %w", err)
}
if err := file.Close(); err != nil {
return fmt.Errorf("close downloaded temp file: %w", err)
}
if err := parent.Rename(temporaryName, destinationName); err != nil {
return fmt.Errorf("install downloaded file: %w", err)
}
if err := syncOpenedDirectory(parent); err != nil {
return fmt.Errorf("sync destination directory after downloaded-file replacement: %w", err)
}
return nil
}