Make temporary names container/image specific

If you hit Ctr-C while pulling an image files and directories get
left in /var/tmp. By adding "containers_images" prefix, we can use
systemd tmpfiles handling to remove them on reboot safely.

Help to make https://github.com/containers/podman/pull/19201 safer.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
Daniel J Walsh 2023-07-16 17:32:45 -04:00
parent 26afd95cfc
commit f485997b9a
No known key found for this signature in database
GPG Key ID: A2DF901DABE2C028
8 changed files with 71 additions and 7 deletions

View File

@ -57,7 +57,7 @@ func NewReaderFromFile(sys *types.SystemContext, path string) (*Reader, error) {
// The caller should call .Close() on the returned archive when done.
func NewReaderFromStream(sys *types.SystemContext, inputStream io.Reader) (*Reader, error) {
// Save inputStream to a temporary file
tarCopyFile, err := os.CreateTemp(tmpdir.TemporaryDirectoryForBigFiles(sys), "docker-tar")
tarCopyFile, err := tmpdir.CreateBigFileTemp(sys, "docker-tar")
if err != nil {
return nil, fmt.Errorf("creating temporary file: %w", err)
}

View File

@ -15,7 +15,7 @@ import (
// It is the caller's responsibility to call the cleanup function, which closes and removes the temporary file.
// If an error occurs, inputInfo is not modified.
func ComputeBlobInfo(sys *types.SystemContext, stream io.Reader, inputInfo *types.BlobInfo) (io.Reader, func(), error) {
diskBlob, err := os.CreateTemp(tmpdir.TemporaryDirectoryForBigFiles(sys), "stream-blob")
diskBlob, err := tmpdir.CreateBigFileTemp(sys, "stream-blob")
if err != nil {
return nil, nil, fmt.Errorf("creating temporary on-disk layer: %w", err)
}

View File

@ -17,10 +17,12 @@ var unixTempDirForBigFiles = builtinUnixTempDirForBigFiles
// DO NOT change this, instead see unixTempDirForBigFiles above.
const builtinUnixTempDirForBigFiles = "/var/tmp"
const prefix = "container_images_"
// TemporaryDirectoryForBigFiles returns a directory for temporary (big) files.
// On non Windows systems it avoids the use of os.TempDir(), because the default temporary directory usually falls under /tmp
// which on systemd based systems could be the unsuitable tmpfs filesystem.
func TemporaryDirectoryForBigFiles(sys *types.SystemContext) string {
func temporaryDirectoryForBigFiles(sys *types.SystemContext) string {
if sys != nil && sys.BigFilesTemporaryDir != "" {
return sys.BigFilesTemporaryDir
}
@ -32,3 +34,11 @@ func TemporaryDirectoryForBigFiles(sys *types.SystemContext) string {
}
return temporaryDirectoryForBigFiles
}
func CreateBigFileTemp(sys *types.SystemContext, name string) (*os.File, error) {
return os.CreateTemp(temporaryDirectoryForBigFiles(sys), prefix+name)
}
func MkDirBigFileTemp(sys *types.SystemContext, name string) (string, error) {
return os.MkdirTemp(temporaryDirectoryForBigFiles(sys), prefix+name)
}

View File

@ -0,0 +1,54 @@
package tmpdir
import (
"os"
"strings"
"testing"
"github.com/containers/image/v5/types"
"github.com/stretchr/testify/assert"
)
func TestCreateBigFileTemp(t *testing.T) {
f, err := CreateBigFileTemp(nil, "")
assert.NoError(t, err)
f.Close()
os.Remove(f.Name())
f, err = CreateBigFileTemp(nil, "foobar")
assert.NoError(t, err)
f.Close()
assert.True(t, strings.Contains(f.Name(), prefix+"foobar"))
os.Remove(f.Name())
var sys types.SystemContext
sys.BigFilesTemporaryDir = "/tmp"
f, err = CreateBigFileTemp(&sys, "foobar1")
assert.NoError(t, err)
f.Close()
assert.True(t, strings.Contains(f.Name(), "/tmp/"+prefix+"foobar1"))
os.Remove(f.Name())
sys.BigFilesTemporaryDir = "/tmp/bogus"
_, err = CreateBigFileTemp(&sys, "foobar1")
assert.Error(t, err)
}
func TestMkDirBigFileTemp(t *testing.T) {
d, err := MkDirBigFileTemp(nil, "foobar")
assert.NoError(t, err)
assert.True(t, strings.Contains(d, prefix+"foobar"))
os.RemoveAll(d)
var sys types.SystemContext
sys.BigFilesTemporaryDir = "/tmp"
d, err = MkDirBigFileTemp(&sys, "foobar1")
assert.NoError(t, err)
assert.True(t, strings.Contains(d, "/tmp/"+prefix+"foobar1"))
os.RemoveAll(d)
sys.BigFilesTemporaryDir = "/tmp/bogus"
_, err = MkDirBigFileTemp(&sys, "foobar1")
assert.Error(t, err)
}

View File

@ -156,7 +156,7 @@ func (t *tempDirOCIRef) deleteTempDir() error {
// createOCIRef creates the oci reference of the image
// If SystemContext.BigFilesTemporaryDir not "", overrides the temporary directory to use for storing big files
func createOCIRef(sys *types.SystemContext, image string) (tempDirOCIRef, error) {
dir, err := os.MkdirTemp(tmpdir.TemporaryDirectoryForBigFiles(sys), "oci")
dir, err := tmpdir.MkDirBigFileTemp(sys, "oci")
if err != nil {
return tempDirOCIRef{}, fmt.Errorf("creating temp directory: %w", err)
}

View File

@ -73,7 +73,7 @@ func newImageSource(ctx context.Context, sys *types.SystemContext, ref sifRefere
_ = sifImg.UnloadContainer()
}()
workDir, err := os.MkdirTemp(tmpdir.TemporaryDirectoryForBigFiles(sys), "sif")
workDir, err := tmpdir.MkDirBigFileTemp(sys, "sif")
if err != nil {
return nil, fmt.Errorf("creating temp directory: %w", err)
}

View File

@ -95,7 +95,7 @@ type addedLayerInfo struct {
// newImageDestination sets us up to write a new image, caching blobs in a temporary directory until
// it's time to Commit() the image
func newImageDestination(sys *types.SystemContext, imageRef storageReference) (*storageImageDestination, error) {
directory, err := os.MkdirTemp(tmpdir.TemporaryDirectoryForBigFiles(sys), "storage")
directory, err := tmpdir.MkDirBigFileTemp(sys, "storage")
if err != nil {
return nil, fmt.Errorf("creating a temporary directory: %w", err)
}

View File

@ -124,7 +124,7 @@ func (s *storageImageSource) GetBlob(ctx context.Context, info types.BlobInfo, c
}
defer rc.Close()
tmpFile, err := os.CreateTemp(tmpdir.TemporaryDirectoryForBigFiles(s.systemContext), "")
tmpFile, err := tmpdir.CreateBigFileTemp(s.systemContext, "")
if err != nil {
return nil, 0, err
}