mirror of
https://github.com/containerd/containerd.git
synced 2026-11-06 05:17:02 +00:00
build(deps): bump github.com/checkpoint-restore/checkpointctl
Bumps [github.com/checkpoint-restore/checkpointctl](https://github.com/checkpoint-restore/checkpointctl) from 1.5.0 to 1.6.0. - [Release notes](https://github.com/checkpoint-restore/checkpointctl/releases) - [Commits](https://github.com/checkpoint-restore/checkpointctl/compare/v1.5.0...v1.6.0) --- updated-dependencies: - dependency-name: github.com/checkpoint-restore/checkpointctl dependency-version: 1.6.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
1 parent
aeb8f4e52a
commit
64f05273e3
14 files changed
+305
-73
No files matched your search
@@ -7,7 +7,7 @@ require (
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6
|
||||
github.com/Microsoft/go-winio v0.6.3-0.20251027160822-ad3df93bed29
|
||||
github.com/Microsoft/hcsshim v0.15.0-rc.4
|
||||
github.com/checkpoint-restore/checkpointctl v1.5.0
|
||||
github.com/checkpoint-restore/checkpointctl v1.6.0
|
||||
github.com/checkpoint-restore/go-criu/v7 v7.2.0
|
||||
github.com/containerd/btrfs/v2 v2.0.0
|
||||
github.com/containerd/cgroups/v3 v3.1.3
|
||||
@@ -92,7 +92,7 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
cyphar.com/go-pathrs v0.2.4 // indirect
|
||||
cyphar.com/go-pathrs v0.2.5 // indirect
|
||||
github.com/ProtonMail/go-crypto v1.4.1 // indirect
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
@@ -102,7 +102,7 @@ require (
|
||||
github.com/cloudflare/circl v1.6.3 // indirect
|
||||
github.com/containers/ocicrypt v1.3.2 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.6.1 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.7.0 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.13.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.1.0 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
cyphar.com/go-pathrs v0.2.4 h1:iD/mge36swa1UFKdINkr1Frkpp6wZsy3YYEildj9cLY=
|
||||
cyphar.com/go-pathrs v0.2.4/go.mod h1:y8f1EMG7r+hCuFf/rXsKqMJrJAUoADZGNh5/vZPKcGc=
|
||||
cyphar.com/go-pathrs v0.2.5 h1:SnX9FBvnoyn3lUs1dkMgZ52bAETpirNu3FTRh5HlRik=
|
||||
cyphar.com/go-pathrs v0.2.5/go.mod h1:y8f1EMG7r+hCuFf/rXsKqMJrJAUoADZGNh5/vZPKcGc=
|
||||
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
|
||||
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
|
||||
@@ -28,8 +28,8 @@ github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1x
|
||||
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
|
||||
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/v7 v7.2.0 h1:qGiWA4App1gGlEfIJ68WR9jbezV9J7yZdjzglezcqKo=
|
||||
github.com/checkpoint-restore/go-criu/v7 v7.2.0/go.mod h1:u0LCWLg0w4yqqu14aXhiB4YD3a1qd8EcCEg7vda5dwo=
|
||||
github.com/cilium/ebpf v0.17.3 h1:FnP4r16PWYSE4ux6zN+//jMcW4nMVRvuTLVTvCjyyjg=
|
||||
@@ -86,8 +86,8 @@ github.com/coreos/go-systemd/v22 v22.7.0 h1:LAEzFkke61DFROc7zNLX/WA2i5J8gYqe0rSj
|
||||
github.com/coreos/go-systemd/v22 v22.7.0/go.mod h1:xNUYtjHu2EDXbsxz1i41wouACIwT7Ybq9o0BQhMwD0w=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE=
|
||||
github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc=
|
||||
github.com/cyphar/filepath-securejoin v0.7.0 h1:s0Y3ITPy6sQn5xt54DuYvTF8hu134ooYLUb58DX/HjE=
|
||||
github.com/cyphar/filepath-securejoin v0.7.0/go.mod h1:ymLGms/u3BYaviIiuKFnUx8EkQEZeK6cInNoAPJA3o4=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
|
||||
+5
-3
@@ -17,6 +17,8 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"cyphar.com/go-pathrs/internal/fdutils"
|
||||
"cyphar.com/go-pathrs/internal/libpathrs"
|
||||
)
|
||||
@@ -56,11 +58,11 @@ func HandleFromFile(file *os.File) (*Handle, error) {
|
||||
// and can be opened multiple times.
|
||||
//
|
||||
// The handle returned is only usable for reading, and this is method is
|
||||
// shorthand for [Handle.OpenFile] with os.O_RDONLY.
|
||||
// shorthand for [Handle.OpenFile] with [unix.O_RDONLY].
|
||||
//
|
||||
// TODO: Rename these to "Reopen" or something.
|
||||
func (h *Handle) Open() (*os.File, error) {
|
||||
return h.OpenFile(os.O_RDONLY)
|
||||
return h.OpenFile(unix.O_RDONLY)
|
||||
}
|
||||
|
||||
// OpenFile creates an "upgraded" file handle to the file referenced by the
|
||||
@@ -71,7 +73,7 @@ func (h *Handle) Open() (*os.File, error) {
|
||||
// handle.
|
||||
//
|
||||
// TODO: Rename these to "Reopen" or something.
|
||||
func (h *Handle) OpenFile(flags int) (*os.File, error) {
|
||||
func (h *Handle) OpenFile(flags uint64) (*os.File, error) {
|
||||
return fdutils.WithFileFd(h.inner, func(fd uintptr) (*os.File, error) {
|
||||
newFd, err := libpathrs.Reopen(fd, flags)
|
||||
if err != nil {
|
||||
|
||||
+52
-24
@@ -60,8 +60,8 @@ func OpenRoot(path string) (uintptr, error) {
|
||||
}
|
||||
|
||||
// Reopen wraps pathrs_reopen.
|
||||
func Reopen(fd uintptr, flags int) (uintptr, error) {
|
||||
newFd := C.pathrs_reopen(C.int(fd), C.int(flags))
|
||||
func Reopen(fd uintptr, flags uint64) (uintptr, error) {
|
||||
newFd := C.pathrs_reopen(C.int(fd), C.uint64_t(flags))
|
||||
return uintptr(newFd), fetchError(newFd)
|
||||
}
|
||||
|
||||
@@ -84,11 +84,11 @@ func InRootResolveNoFollow(rootFd uintptr, path string) (uintptr, error) {
|
||||
}
|
||||
|
||||
// InRootOpen wraps pathrs_inroot_open.
|
||||
func InRootOpen(rootFd uintptr, path string, flags int) (uintptr, error) {
|
||||
func InRootOpen(rootFd uintptr, path string, flags uint64) (uintptr, error) {
|
||||
cPath := C.CString(path)
|
||||
defer C.free(unsafe.Pointer(cPath))
|
||||
|
||||
fd := C.pathrs_inroot_open(C.int(rootFd), cPath, C.int(flags))
|
||||
fd := C.pathrs_inroot_open(C.int(rootFd), cPath, C.uint64_t(flags))
|
||||
return uintptr(fd), fetchError(fd)
|
||||
}
|
||||
|
||||
@@ -145,23 +145,23 @@ func InRootRemoveAll(rootFd uintptr, path string) error {
|
||||
}
|
||||
|
||||
// InRootCreat wraps pathrs_inroot_creat.
|
||||
func InRootCreat(rootFd uintptr, path string, flags int, mode uint32) (uintptr, error) {
|
||||
func InRootCreat(rootFd uintptr, path string, flags uint64, mode uint32) (uintptr, error) {
|
||||
cPath := C.CString(path)
|
||||
defer C.free(unsafe.Pointer(cPath))
|
||||
|
||||
fd := C.pathrs_inroot_creat(C.int(rootFd), cPath, C.int(flags), C.uint(mode))
|
||||
fd := C.pathrs_inroot_creat(C.int(rootFd), cPath, C.uint64_t(flags), C.uint(mode))
|
||||
return uintptr(fd), fetchError(fd)
|
||||
}
|
||||
|
||||
// InRootRename wraps pathrs_inroot_rename.
|
||||
func InRootRename(rootFd uintptr, src, dst string, flags uint) error {
|
||||
cSrc := C.CString(src)
|
||||
defer C.free(unsafe.Pointer(cSrc))
|
||||
func InRootRename(oldRootFd uintptr, oldPath string, newRootFd uintptr, newPath string, flags uint64) error {
|
||||
cOldPath := C.CString(oldPath)
|
||||
defer C.free(unsafe.Pointer(cOldPath))
|
||||
|
||||
cDst := C.CString(dst)
|
||||
defer C.free(unsafe.Pointer(cDst))
|
||||
cNewPath := C.CString(newPath)
|
||||
defer C.free(unsafe.Pointer(cNewPath))
|
||||
|
||||
err := C.pathrs_inroot_rename(C.int(rootFd), cSrc, cDst, C.uint(flags))
|
||||
err := C.pathrs_inroot_rename(C.int(oldRootFd), cOldPath, C.int(newRootFd), cNewPath, C.uint64_t(flags))
|
||||
return fetchError(err)
|
||||
}
|
||||
|
||||
@@ -193,26 +193,26 @@ func InRootMknod(rootFd uintptr, path string, mode uint32, dev uint64) error {
|
||||
}
|
||||
|
||||
// InRootSymlink wraps pathrs_inroot_symlink.
|
||||
func InRootSymlink(rootFd uintptr, path, target string) error {
|
||||
cPath := C.CString(path)
|
||||
defer C.free(unsafe.Pointer(cPath))
|
||||
func InRootSymlink(target string, rootFd uintptr, linkpath string) error {
|
||||
cLinkpath := C.CString(linkpath)
|
||||
defer C.free(unsafe.Pointer(cLinkpath))
|
||||
|
||||
cTarget := C.CString(target)
|
||||
defer C.free(unsafe.Pointer(cTarget))
|
||||
|
||||
err := C.pathrs_inroot_symlink(C.int(rootFd), cPath, cTarget)
|
||||
err := C.pathrs_inroot_symlink(cTarget, C.int(rootFd), cLinkpath)
|
||||
return fetchError(err)
|
||||
}
|
||||
|
||||
// InRootHardlink wraps pathrs_inroot_hardlink.
|
||||
func InRootHardlink(rootFd uintptr, path, target string) error {
|
||||
cPath := C.CString(path)
|
||||
defer C.free(unsafe.Pointer(cPath))
|
||||
func InRootHardlink(oldRootFd uintptr, oldPath string, newRootFd uintptr, newPath string, flags uint64) error {
|
||||
cNewPath := C.CString(newPath)
|
||||
defer C.free(unsafe.Pointer(cNewPath))
|
||||
|
||||
cTarget := C.CString(target)
|
||||
defer C.free(unsafe.Pointer(cTarget))
|
||||
cOldPath := C.CString(oldPath)
|
||||
defer C.free(unsafe.Pointer(cOldPath))
|
||||
|
||||
err := C.pathrs_inroot_hardlink(C.int(rootFd), cPath, cTarget)
|
||||
err := C.pathrs_inroot_hardlink(C.int(oldRootFd), cOldPath, C.int(newRootFd), cNewPath, C.uint64_t(flags))
|
||||
return fetchError(err)
|
||||
}
|
||||
|
||||
@@ -277,13 +277,13 @@ func init() {
|
||||
func ProcPid(pid uint32) ProcBase { return ProcBaseTypePid | ProcBase(pid) }
|
||||
|
||||
// ProcOpenat wraps pathrs_proc_openat.
|
||||
func ProcOpenat(procRootFd int, base ProcBase, path string, flags int) (uintptr, error) {
|
||||
func ProcOpenat(procRootFd int, base ProcBase, path string, flags uint64) (uintptr, error) {
|
||||
cBase := C.pathrs_proc_base_t(base)
|
||||
|
||||
cPath := C.CString(path)
|
||||
defer C.free(unsafe.Pointer(cPath))
|
||||
|
||||
fd := C.pathrs_proc_openat(C.int(procRootFd), cBase, cPath, C.int(flags))
|
||||
fd := C.pathrs_proc_openat(C.int(procRootFd), cBase, cPath, C.uint64_t(flags))
|
||||
return uintptr(fd), fetchError(fd)
|
||||
}
|
||||
|
||||
@@ -335,3 +335,31 @@ func ProcfsOpen(how *ProcfsOpenHow) (uintptr, error) {
|
||||
fd := C.pathrs_procfs_open((*C.pathrs_procfs_open_how)(how), C.size_t(unsafe.Sizeof(*how)))
|
||||
return uintptr(fd), fetchError(fd)
|
||||
}
|
||||
|
||||
// VersionInfo is a Go-friendly form of pathrs_version_info_t (struct).
|
||||
type VersionInfo struct {
|
||||
VersionString string
|
||||
}
|
||||
|
||||
// versionInfo is pathrs_version_info_t (struct).
|
||||
type versionInfo C.pathrs_version_info_t
|
||||
|
||||
// Version is pathrs_version_info_t (sizeof(version) is passed automatically).
|
||||
func Version() (*VersionInfo, error) {
|
||||
var rawVersion versionInfo
|
||||
size := C.pathrs_version((*C.pathrs_version_info_t)(&rawVersion), C.size_t(unsafe.Sizeof(rawVersion)))
|
||||
switch {
|
||||
case size < 0:
|
||||
return nil, fetchError(size)
|
||||
case size > 0:
|
||||
// TODO(log): Logging?
|
||||
fallthrough
|
||||
default:
|
||||
// TODO(log): Add a log statement if sizeof(rawVersion) is bigger than
|
||||
// the number of fields we store in VersionInfo. Otherwise a rebuild
|
||||
// will mask that Go callers cannot see any new fields.
|
||||
return &VersionInfo{
|
||||
VersionString: C.GoString(rawVersion.version_string),
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -127,7 +127,7 @@ func (proc *Handle) fd() int {
|
||||
}
|
||||
|
||||
// TODO: Should we expose open?
|
||||
func (proc *Handle) open(base ProcBase, path string, flags int) (_ *os.File, Closer ThreadCloser, Err error) {
|
||||
func (proc *Handle) open(base ProcBase, path string, flags uint64) (_ *os.File, Closer ThreadCloser, Err error) {
|
||||
var closer ThreadCloser
|
||||
if base == ProcThreadSelf {
|
||||
runtime.LockOSThread()
|
||||
@@ -154,7 +154,7 @@ func (proc *Handle) open(base ProcBase, path string, flags int) (_ *os.File, Clo
|
||||
// (such as /proc/cpuinfo) or information about other processes (such as
|
||||
// /proc/1). Accessing your own process information should be done using
|
||||
// [Handle.OpenSelf] or [Handle.OpenThreadSelf].
|
||||
func (proc *Handle) OpenRoot(path string, flags int) (*os.File, error) {
|
||||
func (proc *Handle) OpenRoot(path string, flags uint64) (*os.File, error) {
|
||||
file, closer, err := proc.open(ProcRoot, path, flags)
|
||||
if closer != nil {
|
||||
// should not happen
|
||||
@@ -180,7 +180,7 @@ func (proc *Handle) OpenRoot(path string, flags int) (*os.File, error) {
|
||||
// Unlike [Handle.OpenThreadSelf], this method does not involve locking
|
||||
// the goroutine to the current OS thread and so is simpler to use and
|
||||
// theoretically has slightly less overhead.
|
||||
func (proc *Handle) OpenSelf(path string, flags int) (*os.File, error) {
|
||||
func (proc *Handle) OpenSelf(path string, flags uint64) (*os.File, error) {
|
||||
file, closer, err := proc.open(ProcSelf, path, flags)
|
||||
if closer != nil {
|
||||
// should not happen
|
||||
@@ -198,7 +198,7 @@ func (proc *Handle) OpenSelf(path string, flags int) (*os.File, error) {
|
||||
// Be aware that due to PID recycling, using this is generally not safe except
|
||||
// in certain circumstances. See the documentation of [ProcPid] for more
|
||||
// details.
|
||||
func (proc *Handle) OpenPid(pid int, path string, flags int) (*os.File, error) {
|
||||
func (proc *Handle) OpenPid(pid int, path string, flags uint64) (*os.File, error) {
|
||||
file, closer, err := proc.open(ProcPid(pid), path, flags)
|
||||
if closer != nil {
|
||||
// should not happen
|
||||
@@ -225,7 +225,7 @@ func (proc *Handle) OpenPid(pid int, path string, flags int) (*os.File, error) {
|
||||
// callback MUST be called AFTER you have finished using the returned
|
||||
// [os.File]. This callback is completely separate to [os.File.Close], so it
|
||||
// must be called regardless of how you close the handle.
|
||||
func (proc *Handle) OpenThreadSelf(path string, flags int) (*os.File, ThreadCloser, error) {
|
||||
func (proc *Handle) OpenThreadSelf(path string, flags uint64) (*os.File, ThreadCloser, error) {
|
||||
return proc.open(ProcThreadSelf, path, flags)
|
||||
}
|
||||
|
||||
|
||||
+28
-26
@@ -19,6 +19,8 @@ import (
|
||||
"os"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"cyphar.com/go-pathrs/internal/fdutils"
|
||||
"cyphar.com/go-pathrs/internal/libpathrs"
|
||||
)
|
||||
@@ -27,7 +29,7 @@ import (
|
||||
// purpose of this "root handle" is to perform operations within the directory
|
||||
// tree, or to get a [Handle] to inodes within the directory tree.
|
||||
//
|
||||
// At time of writing, it is considered a *VERY BAD IDEA* to open a [Root]
|
||||
// At time of writing, it is considered a *VERY BAD IDEA* to open a Root
|
||||
// inside a possibly-attacker-controlled directory tree. While we do have
|
||||
// protections that should defend against it, it's far more dangerous than just
|
||||
// opening a directory tree which is not inside a potentially-untrusted
|
||||
@@ -68,7 +70,7 @@ func RootFromFile(file *os.File) (*Root, error) {
|
||||
//
|
||||
// All symlinks (including trailing symlinks) are followed, but they are
|
||||
// resolved within the rootfs. If you wish to open a handle to the symlink
|
||||
// itself, use [ResolveNoFollow].
|
||||
// itself, use [Root.ResolveNoFollow].
|
||||
func (r *Root) Resolve(path string) (*Handle, error) {
|
||||
return fdutils.WithFileFd(r.inner, func(rootFd uintptr) (*Handle, error) {
|
||||
handleFd, err := libpathrs.InRootResolve(rootFd, path)
|
||||
@@ -83,10 +85,10 @@ func (r *Root) Resolve(path string) (*Handle, error) {
|
||||
})
|
||||
}
|
||||
|
||||
// ResolveNoFollow is effectively an O_NOFOLLOW version of [Resolve]. Their
|
||||
// behaviour is identical, except that *trailing* symlinks will not be
|
||||
// followed. If the final component is a trailing symlink, an O_PATH|O_NOFOLLOW
|
||||
// handle to the symlink itself is returned.
|
||||
// ResolveNoFollow is effectively an [unix.O_NOFOLLOW] version of
|
||||
// [Root.Resolve]. Their behaviour is identical, except that *trailing*
|
||||
// symlinks will not be followed. If the final component is a trailing symlink,
|
||||
// an [unix.O_PATH]|[unix.O_NOFOLLOW] handle to the symlink itself is returned.
|
||||
func (r *Root) ResolveNoFollow(path string) (*Handle, error) {
|
||||
return fdutils.WithFileFd(r.inner, func(rootFd uintptr) (*Handle, error) {
|
||||
handleFd, err := libpathrs.InRootResolveNoFollow(rootFd, path)
|
||||
@@ -101,29 +103,29 @@ func (r *Root) ResolveNoFollow(path string) (*Handle, error) {
|
||||
})
|
||||
}
|
||||
|
||||
// Open is effectively shorthand for [Resolve] followed by [Handle.Open], but
|
||||
// can be slightly more efficient (it reduces CGo overhead and the number of
|
||||
// syscalls used when using the openat2-based resolver) and is arguably more
|
||||
// Open is effectively shorthand for [Root.Resolve] followed by [Handle.Open],
|
||||
// but can be slightly more efficient (it reduces CGo overhead and the number
|
||||
// of syscalls used when using the openat2-based resolver) and is arguably more
|
||||
// ergonomic to use.
|
||||
//
|
||||
// This is effectively equivalent to [os.Open].
|
||||
func (r *Root) Open(path string) (*os.File, error) {
|
||||
return r.OpenFile(path, os.O_RDONLY)
|
||||
return r.OpenFile(path, unix.O_RDONLY)
|
||||
}
|
||||
|
||||
// OpenFile is effectively shorthand for [Resolve] followed by
|
||||
// OpenFile is effectively shorthand for [Root.Resolve] followed by
|
||||
// [Handle.OpenFile], but can be slightly more efficient (it reduces CGo
|
||||
// overhead and the number of syscalls used when using the openat2-based
|
||||
// resolver) and is arguably more ergonomic to use.
|
||||
//
|
||||
// However, if flags contains os.O_NOFOLLOW and the path is a symlink, then
|
||||
// However, if flags contains [unix.O_NOFOLLOW] and the path is a symlink, then
|
||||
// OpenFile's behaviour will match that of openat2. In most cases an error will
|
||||
// be returned, but if os.O_PATH is provided along with os.O_NOFOLLOW then a
|
||||
// file equivalent to [ResolveNoFollow] will be returned instead.
|
||||
// be returned, but if [unix.O_PATH] is provided along with [unix.O_NOFOLLOW]
|
||||
// then a file equivalent to [Root.ResolveNoFollow] will be returned instead.
|
||||
//
|
||||
// This is effectively equivalent to [os.OpenFile], except that os.O_CREAT is
|
||||
// not supported.
|
||||
func (r *Root) OpenFile(path string, flags int) (*os.File, error) {
|
||||
// This is effectively equivalent to [os.OpenFile], except that [unix.O_CREAT]
|
||||
// is not supported.
|
||||
func (r *Root) OpenFile(path string, flags uint64) (*os.File, error) {
|
||||
return fdutils.WithFileFd(r.inner, func(rootFd uintptr) (*os.File, error) {
|
||||
fd, err := libpathrs.InRootOpen(rootFd, path, flags)
|
||||
if err != nil {
|
||||
@@ -139,7 +141,7 @@ func (r *Root) OpenFile(path string, flags int) (*os.File, error) {
|
||||
//
|
||||
// Unlike [os.Create], if the file already exists an error is created rather
|
||||
// than the file being opened and truncated.
|
||||
func (r *Root) Create(path string, flags int, mode os.FileMode) (*os.File, error) {
|
||||
func (r *Root) Create(path string, flags uint64, mode os.FileMode) (*os.File, error) {
|
||||
unixMode, err := toUnixMode(mode, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -155,9 +157,9 @@ func (r *Root) Create(path string, flags int, mode os.FileMode) (*os.File, error
|
||||
|
||||
// Rename two paths within a [Root]'s directory tree. The flags argument is
|
||||
// identical to the RENAME_* flags to the renameat2(2) system call.
|
||||
func (r *Root) Rename(src, dst string, flags uint) error {
|
||||
func (r *Root) Rename(src, dst string, flags uint64) error {
|
||||
_, err := fdutils.WithFileFd(r.inner, func(rootFd uintptr) (struct{}, error) {
|
||||
err := libpathrs.InRootRename(rootFd, src, dst, flags)
|
||||
err := libpathrs.InRootRename(rootFd, src, rootFd, dst, flags)
|
||||
return struct{}{}, err
|
||||
})
|
||||
return err
|
||||
@@ -277,26 +279,26 @@ func (r *Root) Mknod(path string, mode os.FileMode, dev uint64) error {
|
||||
}
|
||||
|
||||
// Symlink creates a symlink within a [Root]'s directory tree. The symlink is
|
||||
// created at path and is a link to target.
|
||||
// created at newname and is a link to oldname.
|
||||
//
|
||||
// This is effectively equivalent to [os.Symlink].
|
||||
func (r *Root) Symlink(path, target string) error {
|
||||
func (r *Root) Symlink(oldname, newname string) error {
|
||||
_, err := fdutils.WithFileFd(r.inner, func(rootFd uintptr) (struct{}, error) {
|
||||
err := libpathrs.InRootSymlink(rootFd, path, target)
|
||||
err := libpathrs.InRootSymlink(oldname, rootFd, newname)
|
||||
return struct{}{}, err
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// Hardlink creates a hardlink within a [Root]'s directory tree. The hardlink
|
||||
// is created at path and is a link to target. Both paths are within the
|
||||
// is created at newname and is a link to oldname. Both paths are within the
|
||||
// [Root]'s directory tree (you cannot hardlink to a different [Root] or the
|
||||
// host).
|
||||
//
|
||||
// This is effectively equivalent to [os.Link].
|
||||
func (r *Root) Hardlink(path, target string) error {
|
||||
func (r *Root) Hardlink(oldname, newname string) error {
|
||||
_, err := fdutils.WithFileFd(r.inner, func(rootFd uintptr) (struct{}, error) {
|
||||
err := libpathrs.InRootHardlink(rootFd, path, target)
|
||||
err := libpathrs.InRootHardlink(rootFd, oldname, rootFd, newname, 0)
|
||||
return struct{}{}, err
|
||||
})
|
||||
return err
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
//go:build linux
|
||||
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
/*
|
||||
* libpathrs: safe path resolution on Linux
|
||||
* Copyright (C) 2026 Aleksa Sarai <cyphar@cyphar.com>
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package pathrs
|
||||
|
||||
import (
|
||||
"cyphar.com/go-pathrs/internal/libpathrs"
|
||||
)
|
||||
|
||||
// LibraryVersionInfo contains information about the version and features
|
||||
// supported by the underlying libpathrs.so library at runtime.
|
||||
type LibraryVersionInfo = libpathrs.VersionInfo
|
||||
|
||||
// LibraryVersion returns information about the version and features supported
|
||||
// by the underlying libpathrs.so library at runtime.
|
||||
func LibraryVersion() (*LibraryVersionInfo, error) {
|
||||
return libpathrs.Version()
|
||||
}
|
||||
+3
@@ -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"
|
||||
|
||||
|
||||
+79
-1
@@ -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 {
|
||||
|
||||
+53
@@ -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
|
||||
}
|
||||
+13
@@ -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)
|
||||
}
|
||||
+26
@@ -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)
|
||||
}
|
||||
+1
-1
@@ -53,5 +53,5 @@ func Reopen(file *os.File, flags int) (*os.File, error) {
|
||||
}
|
||||
defer handle.Close() //nolint:errcheck // close failures aren't critical here
|
||||
|
||||
return handle.OpenFile(flags)
|
||||
return handle.OpenFile(uint64(flags))
|
||||
}
|
||||
Vendored
+4
-4
@@ -1,4 +1,4 @@
|
||||
# cyphar.com/go-pathrs v0.2.4
|
||||
# cyphar.com/go-pathrs v0.2.5
|
||||
## explicit; go 1.18
|
||||
cyphar.com/go-pathrs
|
||||
cyphar.com/go-pathrs/internal/fdutils
|
||||
@@ -106,8 +106,8 @@ github.com/cenkalti/backoff/v5
|
||||
# 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/v7 v7.2.0
|
||||
## explicit; go 1.20
|
||||
@@ -306,7 +306,7 @@ github.com/coreos/go-systemd/v22/dbus
|
||||
# github.com/cpuguy83/go-md2man/v2 v2.0.7
|
||||
## explicit; go 1.12
|
||||
github.com/cpuguy83/go-md2man/v2/md2man
|
||||
# github.com/cyphar/filepath-securejoin v0.6.1
|
||||
# github.com/cyphar/filepath-securejoin v0.7.0
|
||||
## explicit; go 1.18
|
||||
github.com/cyphar/filepath-securejoin/internal/consts
|
||||
github.com/cyphar/filepath-securejoin/pathrs-lite
|
||||
|
||||
Reference in new issue
Block a user