use chrootarchive over plain archive package

Just as additional hardening.

Note chrootarchive does not work on macos/windows, in that case it still
falls back to the regular pkg/archive.

Signed-off-by: Paul Holzinger <pholzing@redhat.com>
This commit is contained in:
Paul Holzinger
2026-04-08 13:22:33 +02:00
parent abb5120624
commit 25aee24cbd
8 changed files with 28 additions and 27 deletions

View File

@@ -55,6 +55,7 @@ import (
"go.podman.io/common/pkg/umask"
is "go.podman.io/image/v5/storage"
"go.podman.io/storage/pkg/archive"
"go.podman.io/storage/pkg/chrootarchive"
"go.podman.io/storage/pkg/fileutils"
"go.podman.io/storage/pkg/idtools"
"go.podman.io/storage/pkg/lockfile"
@@ -1210,11 +1211,10 @@ func (c *Container) exportCheckpoint(options ContainerCheckpointOptions) error {
if mp == "" {
return fmt.Errorf("volume %s is not mounted, cannot export: %w", volume.Name(), define.ErrInternal)
}
input, err := archive.TarWithOptions(mp, &archive.TarOptions{
input, err := chrootarchive.Tar(mp, &archive.TarOptions{
Compression: archive.Uncompressed,
IncludeSourceDir: true,
})
}, mp)
if err != nil {
return fmt.Errorf("reading volume directory %q: %w", v.Dest, err)
}
@@ -1229,11 +1229,12 @@ func (c *Container) exportCheckpoint(options ContainerCheckpointOptions) error {
}
}
input, err := archive.TarWithOptions(c.bundlePath(), &archive.TarOptions{
bundle := c.bundlePath()
input, err := chrootarchive.Tar(bundle, &archive.TarOptions{
Compression: options.Compression,
IncludeSourceDir: true,
IncludeFiles: includeFiles,
})
}, bundle)
if err != nil {
return fmt.Errorf("reading checkpoint directory %q: %w", c.ID(), err)
}
@@ -1314,10 +1315,10 @@ func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointO
}
defer shmDirTarFile.Close()
input, err := archive.TarWithOptions(c.config.ShmDir, &archive.TarOptions{
input, err := chrootarchive.Tar(c.config.ShmDir, &archive.TarOptions{
Compression: archive.Uncompressed,
IncludeSourceDir: true,
})
}, c.config.ShmDir)
if err != nil {
return nil, 0, err
}
@@ -1490,7 +1491,7 @@ func (c *Container) importPreCheckpoint(input string) error {
defer archiveFile.Close()
err = archive.Untar(archiveFile, c.bundlePath(), nil)
err = chrootarchive.Untar(archiveFile, c.bundlePath(), nil)
if err != nil {
return fmt.Errorf("unpacking of pre-checkpoint archive %s failed: %w", input, err)
}
@@ -1753,7 +1754,7 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
}
defer shmDirTarFile.Close()
if err := archive.UntarUncompressed(shmDirTarFile, c.config.ShmDir, nil); err != nil {
if err := chrootarchive.UntarUncompressed(shmDirTarFile, c.config.ShmDir, nil); err != nil {
return nil, 0, err
}
}
@@ -1793,7 +1794,7 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
if mountPoint == "" {
return nil, 0, fmt.Errorf("unable to import volume %s as it is not mounted: %w", volume.Name(), err)
}
if err := archive.UntarUncompressed(volumeFile, mountPoint, nil); err != nil {
if err := chrootarchive.UntarUncompressed(volumeFile, mountPoint, nil); err != nil {
return nil, 0, fmt.Errorf("failed to extract volume %s to %s: %w", volumeFilePath, mountPoint, err)
}
}

View File

@@ -13,7 +13,7 @@ import (
"github.com/containers/podman/v6/libpod/plugin"
"github.com/containers/podman/v6/utils"
"github.com/sirupsen/logrus"
"go.podman.io/storage/pkg/archive"
"go.podman.io/storage/pkg/chrootarchive"
"go.podman.io/storage/pkg/directory"
)
@@ -342,7 +342,7 @@ func (v *Volume) Import(r io.Reader) error {
}
}()
if err := archive.Untar(r, mountPoint, nil); err != nil {
if err := chrootarchive.Untar(r, mountPoint, nil); err != nil {
return fmt.Errorf("extracting into volume %s: %w", v.Name(), err)
}

View File

@@ -1270,6 +1270,6 @@ func extractTarFile(anchorDir string, r io.ReadCloser) (string, error) {
return "", err
}
err = archive.Untar(r, buildDir, nil)
err = chrootarchive.Untar(r, buildDir, nil)
return buildDir, err
}

View File

@@ -12,8 +12,6 @@ import (
"os"
"path/filepath"
"go.podman.io/storage/pkg/archive"
"github.com/containers/podman/v6/libpod"
"github.com/containers/podman/v6/pkg/api/handlers/utils"
api "github.com/containers/podman/v6/pkg/api/types"
@@ -23,6 +21,7 @@ import (
"github.com/gorilla/schema"
"github.com/sirupsen/logrus"
"go.podman.io/image/v5/types"
"go.podman.io/storage/pkg/chrootarchive"
)
// ExtractPlayReader provide an io.Reader given a http.Request object
@@ -52,7 +51,7 @@ func extractPlayReader(anchorDir string, r *http.Request) (io.Reader, error) {
reader = r.Body
case "application/x-tar":
// un-tar the content
err := archive.Untar(r.Body, anchorDir, nil)
err := chrootarchive.Untar(r.Body, anchorDir, nil)
if err != nil {
return nil, err
}

View File

@@ -11,8 +11,6 @@ import (
"path/filepath"
"strings"
"go.podman.io/storage/pkg/archive"
"github.com/containers/podman/v6/libpod"
"github.com/containers/podman/v6/libpod/define"
"github.com/containers/podman/v6/pkg/api/handlers/utils"
@@ -23,6 +21,7 @@ import (
"github.com/containers/podman/v6/pkg/util"
"github.com/gorilla/schema"
"github.com/sirupsen/logrus"
"go.podman.io/storage/pkg/chrootarchive"
)
func ListQuadlets(w http.ResponseWriter, r *http.Request) {
@@ -94,7 +93,7 @@ func extractQuadletFiles(tempDir string, r io.ReadCloser) ([]string, error) {
return nil, err
}
err = archive.Untar(r, quadletDir, nil)
err = chrootarchive.Untar(r, quadletDir, nil)
if err != nil {
return nil, err
}

View File

@@ -14,6 +14,7 @@ import (
securejoin "github.com/cyphar/filepath-securejoin"
"github.com/opencontainers/selinux/go-selinux/label"
"go.podman.io/storage/pkg/archive"
"go.podman.io/storage/pkg/chrootarchive"
)
// This file mainly exists to make the checkpoint/restore functions
@@ -35,7 +36,7 @@ func CRImportCheckpointWithoutConfig(destination, input string) error {
metadata.SpecDumpFile,
},
}
if err = archive.Untar(archiveFile, destination, options); err != nil {
if err = chrootarchive.Untar(archiveFile, destination, options); err != nil {
return fmt.Errorf("unpacking of checkpoint archive %s failed: %w", input, err)
}
@@ -65,7 +66,7 @@ func CRImportCheckpointConfigOnly(destination, input string) error {
metadata.CheckpointVolumesDirectory,
},
}
if err = archive.Untar(archiveFile, destination, options); err != nil {
if err = chrootarchive.Untar(archiveFile, destination, options); err != nil {
return fmt.Errorf("unpacking of checkpoint archive %s failed: %w", input, err)
}
@@ -114,7 +115,7 @@ func CRApplyRootFsDiffTar(baseDirectory, containerRootDirectory string) error {
}
defer rootfsDiffFile.Close()
if err := archive.Untar(rootfsDiffFile, containerRootDirectory, nil); err != nil {
if err := chrootarchive.Untar(rootfsDiffFile, containerRootDirectory, nil); err != nil {
return fmt.Errorf("failed to apply root file-system diff file %s: %w", rootfsDiffPath, err)
}
@@ -157,11 +158,11 @@ func CRCreateRootFsDiffTar(changes *[]archive.Change, mountPoint, destination st
}
if len(rootfsIncludeFiles) > 0 {
rootfsTar, err := archive.TarWithOptions(mountPoint, &archive.TarOptions{
rootfsTar, err := chrootarchive.Tar(mountPoint, &archive.TarOptions{
Compression: archive.Uncompressed,
IncludeSourceDir: true,
IncludeFiles: rootfsIncludeFiles,
})
}, mountPoint)
if err != nil {
return includeFiles, fmt.Errorf("exporting root file-system diff to %q: %w", rootfsDiffPath, err)
}

View File

@@ -43,7 +43,7 @@ import (
"go.podman.io/common/pkg/secrets"
"go.podman.io/image/v5/docker/reference"
"go.podman.io/image/v5/types"
"go.podman.io/storage/pkg/archive"
"go.podman.io/storage/pkg/chrootarchive"
"go.podman.io/storage/pkg/fileutils"
yamlv3 "gopkg.in/yaml.v3"
"sigs.k8s.io/yaml"
@@ -1503,7 +1503,7 @@ func (ic *ContainerEngine) importVolume(ctx context.Context, vol *libpod.Volume,
}
// dont care if volume is mounted or not we are gonna import everything to mountPoint
return archive.Untar(tarFile, mountPoint, nil)
return chrootarchive.Untar(tarFile, mountPoint, nil)
}
// readConfigMapFromFile returns a kubernetes configMap obtained from --configmap flag

View File

@@ -24,6 +24,7 @@ import (
"go.podman.io/image/v5/docker/reference"
"go.podman.io/image/v5/types"
"go.podman.io/storage/pkg/archive"
"go.podman.io/storage/pkg/chrootarchive"
)
func (ir *ImageEngine) Exists(_ context.Context, nameOrID string) (*entities.BoolReport, error) {
@@ -367,7 +368,7 @@ func (ir *ImageEngine) Save(_ context.Context, nameOrID string, tags []string, o
return err
}
return archive.Untar(f, opts.Output, &archive.TarOptions{NoLchown: true})
return chrootarchive.Untar(f, opts.Output, &archive.TarOptions{NoLchown: true})
}
func (ir *ImageEngine) Search(_ context.Context, term string, opts entities.ImageSearchOptions) ([]entities.ImageSearchReport, error) {