vendor: update checkpointctl to v1.6.0

Podman uses checkpointctl when importing checkpoint archives and images.
Updating this dependency to include metadata handling changes.

Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This commit is contained in:
Radostin Stoyanov 2026-08-14 09:09:26 +01:00
parent 05b3b7220b
commit dd48cfffb4
8 changed files with 179 additions and 6 deletions

2
go.mod
View file

@ -8,7 +8,7 @@ go 1.25.9
require (
github.com/Microsoft/go-winio v0.6.2
github.com/blang/semver/v4 v4.0.0
github.com/checkpoint-restore/checkpointctl v1.5.0
github.com/checkpoint-restore/checkpointctl v1.6.0
github.com/checkpoint-restore/go-criu/v8 v8.4.0
github.com/containers/gvisor-tap-vsock v0.8.9
github.com/containers/libhvee v0.11.0

4
go.sum
View file

@ -28,8 +28,8 @@ github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/checkpoint-restore/checkpointctl v1.5.0 h1:Uu+D2cOf/GUyCMk23Y8L69P6YoATTe6pH+Au64O3y28=
github.com/checkpoint-restore/checkpointctl v1.5.0/go.mod h1:y5HRs1ZWQUZGyEuthlTHmTJN9PUMOjlaH6JvVaNq9kE=
github.com/checkpoint-restore/checkpointctl v1.6.0 h1:e+hOhEFiUUYZRCbbfbceQ3lLGQXHt2+qKSAR2l9Mv5M=
github.com/checkpoint-restore/checkpointctl v1.6.0/go.mod h1:LjfSgCtcTMbzwcA7d+vXJ7udJsWC/VRJpKUojTAGeCk=
github.com/checkpoint-restore/go-criu/v8 v8.4.0 h1:w6WDxjde4pvXYTIBuj6dsWsaPorKwSWuCk/qSKTO3Jw=
github.com/checkpoint-restore/go-criu/v8 v8.4.0/go.mod h1:SK5UexowK0P99gCcJJOavgVVlUWydGUfXSQUf1qDkHU=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=

View file

@ -19,6 +19,9 @@ const (
// CheckpointAnnotationNamespace specifies the namespace of the pod associated with the checkpoint.
CheckpointAnnotationNamespace = "org.criu.checkpoint.pod.namespace"
// CheckpointAnnotationPodUID specifies the UID of the pod associated with the checkpoint.
CheckpointAnnotationPodUID = "org.criu.checkpoint.pod.uid"
// CheckpointAnnotationRootfsImageName specifies the name of the root filesystem image associated with the checkpoint.
CheckpointAnnotationRootfsImageName = "org.criu.checkpoint.rootfsImageName"

View file

@ -4,7 +4,9 @@ package metadata
import (
"encoding/json"
"errors"
"fmt"
"io"
"os"
"path/filepath"
"time"
@ -12,6 +14,8 @@ import (
spec "github.com/opencontainers/runtime-spec/specs-go"
)
var errNotRegularFile = errors.New("not a regular file")
const (
// container archive
ConfigDumpFile = "config.dump"
@ -79,6 +83,43 @@ type KubernetesContainerCheckpointMetadata struct {
Checkpoints []KubernetesCheckpoint `json:"checkpoints"`
}
// CheckpointedPodOptions contains metadata about a checkpointed pod
type CheckpointedPodOptions struct {
// Version is the version of the pod checkpoint format
Version int `json:"version"`
// Containers is a map with the short container name as key and the full name as value
Containers map[string]string `json:"containers"`
// Annotations stores checkpoint-related annotations (keys defined in annotations.go)
Annotations map[string]string `json:"annotations,omitempty"`
}
// PodmanNetworkSubnet represents a single subnet entry in the Podman network status
type PodmanNetworkSubnet struct {
IPNet string `json:"ipnet"`
Gateway string `json:"gateway"`
}
// PodmanNetworkInterface represents a network interface in the Podman network status
type PodmanNetworkInterface struct {
Subnets []PodmanNetworkSubnet `json:"subnets"`
MacAddress string `json:"mac_address"`
}
// PodmanNetworkResult represents the network status for a single CNI/netavark network
type PodmanNetworkResult struct {
Interfaces map[string]PodmanNetworkInterface `json:"interfaces"`
}
// PodmanNetworkStatus maps network names to their results in the network.status file
type PodmanNetworkStatus map[string]PodmanNetworkResult
func ReadContainerCheckpointNetworkStatus(checkpointDirectory string) (*PodmanNetworkStatus, string, error) {
var networkStatus PodmanNetworkStatus
networkStatusFile, err := ReadJSONFile(&networkStatus, checkpointDirectory, NetworkStatusFile)
return &networkStatus, networkStatusFile, err
}
func ReadContainerCheckpointSpecDump(checkpointDirectory string) (*spec.Spec, string, error) {
var specDump spec.Spec
specDumpFile, err := ReadJSONFile(&specDump, checkpointDirectory, SpecDumpFile)
@ -107,6 +148,13 @@ func ReadContainerCheckpointStatusFile(checkpointDirectory string) (*ContainerdS
return &containerdStatus, statusFile, err
}
func ReadCheckpointPodOptions(checkpointDirectory string) (*CheckpointedPodOptions, string, error) {
var podOptions CheckpointedPodOptions
podOptionsFile, err := ReadJSONFile(&podOptions, checkpointDirectory, PodOptionsFile)
return &podOptions, podOptionsFile, err
}
// WriteJSONFile marshalls and writes the given data to a JSON file
func WriteJSONFile(v interface{}, dir, file string) (string, error) {
fileJSON, err := json.MarshalIndent(v, "", " ")
@ -121,9 +169,18 @@ func WriteJSONFile(v interface{}, dir, file string) (string, error) {
return file, nil
}
// ReadJSONFile reads JSON from a regular file in dir. On Unix, a symbolic link
// in the final path component is rejected. On Linux, reopening the validated
// file descriptor requires access to a usable procfs instance.
func ReadJSONFile(v interface{}, dir, file string) (string, error) {
file = filepath.Join(dir, file)
content, err := os.ReadFile(file)
f, err := openRegularFile(file)
if err != nil {
return "", err
}
defer f.Close()
content, err := io.ReadAll(f)
if err != nil {
return "", err
}
@ -134,6 +191,27 @@ func ReadJSONFile(v interface{}, dir, file string) (string, error) {
return file, nil
}
// openRegularFile applies platform-specific opening safeguards and verifies
// the opened descriptor before returning it.
func openRegularFile(file string) (*os.File, error) {
f, err := openFile(file)
if err != nil {
return nil, err
}
info, err := f.Stat()
if err != nil {
_ = f.Close()
return nil, err
}
if !info.Mode().IsRegular() {
_ = f.Close()
return nil, fmt.Errorf("%s is %w", file, errNotRegularFile)
}
return f, nil
}
func ByteToString(b int64) string {
const unit = 1024
if b < unit {

View file

@ -0,0 +1,53 @@
// SPDX-License-Identifier: Apache-2.0
//go:build linux
package metadata
import (
"fmt"
"os"
pathrs "github.com/cyphar/filepath-securejoin/pathrs-lite"
"golang.org/x/sys/unix"
)
// openFile opens path without activating the inode, verifies that the opened
// inode is a regular file, and then reopens that same inode for reading.
func openFile(path string) (*os.File, error) {
handle, err := os.OpenFile(path, unix.O_PATH|unix.O_NOFOLLOW|unix.O_CLOEXEC, 0)
if err != nil {
return nil, err
}
defer handle.Close()
handleInfo, err := handle.Stat()
if err != nil {
return nil, fmt.Errorf("stat %s: %w", path, err)
}
if !handleInfo.Mode().IsRegular() {
return nil, fmt.Errorf("%s is %w", path, errNotRegularFile)
}
return reopenFile(handle, path, handleInfo)
}
func reopenFile(handle *os.File, path string, handleInfo os.FileInfo) (*os.File, error) {
// Linux openat(2) does not support AT_EMPTY_PATH. Reopen the pinned O_PATH
// descriptor using pathrs, which protects against unsafe procfs mounts.
f, err := pathrs.Reopen(handle, unix.O_RDONLY)
if err != nil {
return nil, fmt.Errorf("reopen %s: %w", path, err)
}
info, err := f.Stat()
if err != nil {
_ = f.Close()
return nil, fmt.Errorf("stat reopened %s: %w", path, err)
}
if !os.SameFile(handleInfo, info) {
_ = f.Close()
return nil, fmt.Errorf("reopened file does not match %s", path)
}
return f, nil
}

View file

@ -0,0 +1,13 @@
// SPDX-License-Identifier: Apache-2.0
//go:build !unix
package metadata
import "os"
func openFile(path string) (*os.File, error) {
// Preserve the platform's ordinary open behavior. openRegularFile validates
// the resulting descriptor before any JSON is read.
return os.Open(path)
}

View file

@ -0,0 +1,26 @@
// SPDX-License-Identifier: Apache-2.0
//go:build unix && !linux
package metadata
import (
"fmt"
"os"
"syscall"
)
func openFile(path string) (*os.File, error) {
// Reject stable special files before open. O_NONBLOCK prevents a FIFO
// replacement from blocking between this check and the descriptor check in
// openRegularFile.
info, err := os.Lstat(path)
if err != nil {
return nil, err
}
if !info.Mode().IsRegular() {
return nil, fmt.Errorf("%s is %w", path, errNotRegularFile)
}
return os.OpenFile(path, os.O_RDONLY|syscall.O_NONBLOCK|syscall.O_NOFOLLOW, 0)
}

4
vendor/modules.txt vendored
View file

@ -68,8 +68,8 @@ github.com/blang/semver/v4
# github.com/cespare/xxhash/v2 v2.3.0
## explicit; go 1.11
github.com/cespare/xxhash/v2
# github.com/checkpoint-restore/checkpointctl v1.5.0
## explicit; go 1.24.6
# github.com/checkpoint-restore/checkpointctl v1.6.0
## explicit; go 1.25.0
github.com/checkpoint-restore/checkpointctl/lib
# github.com/checkpoint-restore/go-criu/v8 v8.4.0
## explicit; go 1.25.0