diff --git a/go.mod b/go.mod index de50b98bab2d..9e46a4186654 100644 --- a/go.mod +++ b/go.mod @@ -413,11 +413,6 @@ require ( ) replace ( - // filepath-securejoin v0.6.0 removed MkdirAllHandle from the root package (moved to pathrs-lite). - // opencontainers/runc v1.2.5 still calls securejoin.MkdirAllHandle from root. - // Point to a patched fork that re-exports MkdirAllHandle from root for compatibility. - // TODO: Remove once opencontainers/runc is updated to use pathrs-lite directly. - github.com/cyphar/filepath-securejoin => github.com/wangke19/filepath-securejoin-1 v0.6.2-0.20260309113322-d8b3e820b3d6 github.com/onsi/ginkgo/v2 => github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20251001123353-fd5b1fb35db1 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc => go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 k8s.io/api => github.com/openshift/kubernetes/staging/src/k8s.io/api v0.0.0-20251017123720-96593f323733 diff --git a/go.sum b/go.sum index 7dc4fb9dfe5c..bd2c1895049e 100644 --- a/go.sum +++ b/go.sum @@ -284,6 +284,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6N github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +github.com/cyphar/filepath-securejoin v0.6.0 h1:BtGB77njd6SVO6VztOHfPxKitJvd/VPT+OFBFMOi1Is= +github.com/cyphar/filepath-securejoin v0.6.0/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc= 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= @@ -1027,8 +1029,6 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 h1:6fotK7 github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75/go.mod h1:KO6IkyS8Y3j8OdNO85qEYBsRPuteD+YciPomcXdrMnk= github.com/vmware/govmomi v0.51.0 h1:n3RLS9aw/irTOKbiIyJzAb6rOat4YOVv/uDoRsNTSQI= github.com/vmware/govmomi v0.51.0/go.mod h1:3ywivawGRfMP2SDCeyKqxTl2xNIHTXF0ilvp72dot5A= -github.com/wangke19/filepath-securejoin-1 v0.6.2-0.20260309113322-d8b3e820b3d6 h1:prZrj2ZRa0wugbd/r6qGFHRMxCYwhamQG/Xk8+zCKjc= -github.com/wangke19/filepath-securejoin-1 v0.6.2-0.20260309113322-d8b3e820b3d6/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= diff --git a/vendor/github.com/cyphar/filepath-securejoin/CHANGELOG.md b/vendor/github.com/cyphar/filepath-securejoin/CHANGELOG.md index 6d016d05c00e..734cf61e3226 100644 --- a/vendor/github.com/cyphar/filepath-securejoin/CHANGELOG.md +++ b/vendor/github.com/cyphar/filepath-securejoin/CHANGELOG.md @@ -6,52 +6,62 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] ## -## [0.6.1] - 2025-11-19 ## - -> At last up jumped the cunning spider, and fiercely held her fast. - -### Fixed ### -- Our logic for deciding whether to use `openat2(2)` or fallback to an `O_PATH` - resolver would cache the result to avoid doing needless test runs of - `openat2(2)`. However, this causes issues when `pathrs-lite` is being used by - a program that applies new seccomp-bpf filters onto itself -- if the filter - denies `openat2(2)` then we would return that error rather than falling back - to the `O_PATH` resolver. To resolve this issue, we no longer cache the - result if `openat2(2)` was successful, only if there was an error. -- A file descriptor leak in our `openat2` wrapper (when doing the necessary - `dup` for `RESOLVE_IN_ROOT`) has been removed. - -## [0.5.2] - 2025-11-19 ## - -> "Will you walk into my parlour?" said a spider to a fly. - -### Fixed ### -- Our logic for deciding whether to use `openat2(2)` or fallback to an `O_PATH` - resolver would cache the result to avoid doing needless test runs of - `openat2(2)`. However, this causes issues when `pathrs-lite` is being used by - a program that applies new seccomp-bpf filters onto itself -- if the filter - denies `openat2(2)` then we would return that error rather than falling back - to the `O_PATH` resolver. To resolve this issue, we no longer cache the - result if `openat2(2)` was successful, only if there was an error. -- A file descriptor leak in our `openat2` wrapper (when doing the necessary - `dup` for `RESOLVE_IN_ROOT`) has been removed. - ## [0.6.0] - 2025-11-03 ## > By the Power of Greyskull! +While quite small code-wise, this release marks a very key point in the +development of filepath-securejoin. + +filepath-securejoin was originally intended (back in 2017) to simply be a +single-purpose library that would take some common code used in container +runtimes (specifically, Docker's `FollowSymlinksInScope`) and make it more +general-purpose (with the eventual goals of it ending up in the Go stdlib). + +Of course, I quickly discovered that this problem was actually far more +complicated to solve when dealing with racing attackers, which lead to me +developing `openat2(2)` and [libpathrs][]. I had originally planned for +libpathrs to completely replace filepath-securejoin "once it was ready" but in +the interim we needed to fix several race attacks in runc as part of security +advisories. Obviously we couldn't require the usage of a pre-0.1 Rust library +in runc so it was necessary to port bits of libpathrs into filepath-securejoin. +(Ironically the first prototypes of libpathrs were originally written in Go and +then rewritten to Rust, so the code in filepath-securejoin is actually Go code +that was rewritten to Rust then re-rewritten to Go.) + +It then became clear that pure-Go libraries will likely not be willing to +require CGo for all of their builds, so it was necessary to accept that +filepath-securejoin will need to stay. As such, in v0.5.0 we provided more +pure-Go implementations of features from libpathrs but moved them into +`pathrs-lite` subpackage to clarify what purpose these helpers serve. + +This release finally closes the loop and makes it so that pathrs-lite can +transparently use libpathrs (via a `libpathrs` build-tag). This means that +upstream libraries can use the pure Go version if they prefer, but downstreams +(either downstream library users or even downstream distributions) are able to +migrate to libpathrs for all usages of pathrs-lite in an entire Go binary. + +I should make it clear that I do not plan to port the rest of libpathrs to Go, +as I do not wish to maintain two copies of the same codebase. pathrs-lite +already provides the core essentials necessary to operate on paths safely for +most modern systems. Users who want additional hardening or more ergonomic APIs +are free to use [`cyphar.com/go-pathrs`][go-pathrs] (libpathrs's Go bindings). + +[libpathrs]: https://github.com/cyphar/libpathrs +[go-pathrs]: https://cyphar.com/go-pathrs + ### Breaking ### - The deprecated `MkdirAll`, `MkdirAllHandle`, `OpenInRoot`, `OpenatInRoot` and `Reopen` wrappers have been removed. Please switch to using `pathrs-lite` directly. ### Added ### -- `pathrs-lite` now has support for using libpathrs as a backend. This is - opt-in and can be enabled at build time with the `libpathrs` build tag. The - intention is to allow for downstream libraries and other projects to make use - of the pure-Go `github.com/cyphar/filepath-securejoin/pathrs-lite` package - and distributors can then opt-in to using `libpathrs` for the entire binary - if they wish. +- `pathrs-lite` now has support for using [libpathrs][libpathrs] as a backend. + This is opt-in and can be enabled at build time with the `libpathrs` build + tag. The intention is to allow for downstream libraries and other projects to + make use of the pure-Go `github.com/cyphar/filepath-securejoin/pathrs-lite` + package and distributors can then opt-in to using `libpathrs` for the entire + binary if they wish. ## [0.5.1] - 2025-10-31 ## @@ -430,10 +440,8 @@ This is our first release of `github.com/cyphar/filepath-securejoin`, containing a full implementation with a coverage of 93.5% (the only missing cases are the error cases, which are hard to mocktest at the moment). -[Unreleased]: https://github.com/cyphar/filepath-securejoin/compare/v0.6.1...HEAD -[0.6.1]: https://github.com/cyphar/filepath-securejoin/compare/v0.6.0...v0.6.1 -[0.6.0]: https://github.com/cyphar/filepath-securejoin/compare/v0.5.0...v0.6.0 -[0.5.2]: https://github.com/cyphar/filepath-securejoin/compare/v0.5.1...v0.5.2 +[Unreleased]: https://github.com/cyphar/filepath-securejoin/compare/v0.6.0...HEAD +[0.6.0]: https://github.com/cyphar/filepath-securejoin/compare/v0.5.1...v0.6.0 [0.5.1]: https://github.com/cyphar/filepath-securejoin/compare/v0.5.0...v0.5.1 [0.5.0]: https://github.com/cyphar/filepath-securejoin/compare/v0.4.1...v0.5.0 [0.4.1]: https://github.com/cyphar/filepath-securejoin/compare/v0.4.0...v0.4.1 diff --git a/vendor/github.com/cyphar/filepath-securejoin/VERSION b/vendor/github.com/cyphar/filepath-securejoin/VERSION index ee6cdce3c290..a918a2aa18d5 100644 --- a/vendor/github.com/cyphar/filepath-securejoin/VERSION +++ b/vendor/github.com/cyphar/filepath-securejoin/VERSION @@ -1 +1 @@ -0.6.1 +0.6.0 diff --git a/vendor/github.com/cyphar/filepath-securejoin/mkdirall_compat_linux.go b/vendor/github.com/cyphar/filepath-securejoin/mkdirall_compat_linux.go deleted file mode 100644 index 795428f5abaf..000000000000 --- a/vendor/github.com/cyphar/filepath-securejoin/mkdirall_compat_linux.go +++ /dev/null @@ -1,20 +0,0 @@ -// This file provides backward compatibility for callers that still reference -// MkdirAllHandle from the root package (e.g., opencontainers/runc v1.2.5). -// MkdirAllHandle moved to the pathrs-lite sub-package in v0.6.0. -// TODO: Remove once opencontainers/runc is updated. - -package securejoin - -import ( - "os" - - securejoinpathrs "github.com/cyphar/filepath-securejoin/pathrs-lite" -) - -// MkdirAllHandle is a compatibility shim for callers that import MkdirAllHandle -// from the root package. It delegates to pathrs-lite.MkdirAllHandle. -// -// Deprecated: Use github.com/cyphar/filepath-securejoin/pathrs-lite.MkdirAllHandle directly. -func MkdirAllHandle(root *os.File, unsafePath string, mode os.FileMode) (*os.File, error) { - return securejoinpathrs.MkdirAllHandle(root, unsafePath, mode) -} diff --git a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/fd/openat2_linux.go b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/fd/openat2_linux.go index 63863647d5b1..3e937fe3c161 100644 --- a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/fd/openat2_linux.go +++ b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/fd/openat2_linux.go @@ -39,9 +39,7 @@ const scopedLookupMaxRetries = 128 // Openat2 is an [Fd]-based wrapper around unix.Openat2, but with some retry // logic in case of EAGAIN errors. -// -// NOTE: This is a variable so that the lookup tests can force openat2 to fail. -var Openat2 = func(dir Fd, path string, how *unix.OpenHow) (*os.File, error) { +func Openat2(dir Fd, path string, how *unix.OpenHow) (*os.File, error) { dirFd, fullPath := prepareAt(dir, path) // Make sure we always set O_CLOEXEC. how.Flags |= unix.O_CLOEXEC diff --git a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gocompat/gocompat_atomic_go119.go b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gocompat/gocompat_atomic_go119.go deleted file mode 100644 index ac93cb045e16..000000000000 --- a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gocompat/gocompat_atomic_go119.go +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause - -//go:build linux && go1.19 - -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gocompat - -import ( - "sync/atomic" -) - -// A Bool is an atomic boolean value. -// The zero value is false. -// -// Bool must not be copied after first use. -type Bool = atomic.Bool diff --git a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gocompat/gocompat_atomic_unsupported.go b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gocompat/gocompat_atomic_unsupported.go deleted file mode 100644 index 21b5b29ada9f..000000000000 --- a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gocompat/gocompat_atomic_unsupported.go +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause - -//go:build linux && !go1.19 - -// Copyright (C) 2024-2025 SUSE LLC. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gocompat - -import ( - "sync/atomic" -) - -// noCopy may be added to structs which must not be copied -// after the first use. -// -// See https://golang.org/issues/8005#issuecomment-190753527 -// for details. -// -// Note that it must not be embedded, due to the Lock and Unlock methods. -type noCopy struct{} - -// Lock is a no-op used by -copylocks checker from `go vet`. -func (*noCopy) Lock() {} - -// b32 returns a uint32 0 or 1 representing b. -func b32(b bool) uint32 { - if b { - return 1 - } - return 0 -} - -// A Bool is an atomic boolean value. -// The zero value is false. -// -// Bool must not be copied after first use. -type Bool struct { - _ noCopy - v uint32 -} - -// Load atomically loads and returns the value stored in x. -func (x *Bool) Load() bool { return atomic.LoadUint32(&x.v) != 0 } - -// Store atomically stores val into x. -func (x *Bool) Store(val bool) { atomic.StoreUint32(&x.v, b32(val)) } diff --git a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gopathrs/lookup_linux.go b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gopathrs/lookup_linux.go index ad233f140536..56480f0cee11 100644 --- a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gopathrs/lookup_linux.go +++ b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gopathrs/lookup_linux.go @@ -193,13 +193,8 @@ func lookupInRoot(root fd.Fd, unsafePath string, partial bool) (Handle *os.File, // managed open, along with the remaining path components not opened. // Try to use openat2 if possible. - // - // NOTE: If openat2(2) works normally but fails for this lookup, it is - // probably not a good idea to fall-back to the O_PATH resolver. An - // attacker could find a bug in the O_PATH resolver and uncontionally - // falling back to the O_PATH resolver would form a downgrade attack. - if handle, remainingPath, err := lookupOpenat2(root, unsafePath, partial); err == nil || linux.HasOpenat2() { - return handle, remainingPath, err + if linux.HasOpenat2() { + return lookupOpenat2(root, unsafePath, partial) } // Get the "actual" root path from /proc/self/fd. This is necessary if the diff --git a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gopathrs/openat2_linux.go b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gopathrs/openat2_linux.go index 9c5c268f6654..b80ecd08953f 100644 --- a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gopathrs/openat2_linux.go +++ b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gopathrs/openat2_linux.go @@ -41,7 +41,6 @@ func openat2(dir fd.Fd, path string, how *unix.OpenHow) (*os.File, error) { if err != nil { return nil, err } - _ = file.Close() file = newFile } } diff --git a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/linux/openat2_linux.go b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/linux/openat2_linux.go index dc5f65cef7f1..399609dc3617 100644 --- a/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/linux/openat2_linux.go +++ b/vendor/github.com/cyphar/filepath-securejoin/pathrs-lite/internal/linux/openat2_linux.go @@ -17,27 +17,15 @@ import ( "github.com/cyphar/filepath-securejoin/pathrs-lite/internal/gocompat" ) -// sawOpenat2Error stores whether we have seen an error from HasOpenat2. This -// is a one-way toggle, so as soon as we see an error we "lock" into that mode. -// We cannot use sync.OnceValue to store the success/fail state once because it -// is possible for the program we are running in to apply a seccomp-bpf filter -// and thus disable openat2 during execution. -var sawOpenat2Error gocompat.Bool - // HasOpenat2 returns whether openat2(2) is supported on the running kernel. -var HasOpenat2 = func() bool { - if sawOpenat2Error.Load() { - return false - } - +var HasOpenat2 = gocompat.SyncOnceValue(func() bool { fd, err := unix.Openat2(unix.AT_FDCWD, ".", &unix.OpenHow{ Flags: unix.O_PATH | unix.O_CLOEXEC, Resolve: unix.RESOLVE_NO_SYMLINKS | unix.RESOLVE_IN_ROOT, }) if err != nil { - sawOpenat2Error.Store(true) // doesn't matter if we race here return false } _ = unix.Close(fd) return true -} +}) diff --git a/vendor/modules.txt b/vendor/modules.txt index d94d720beade..cc7e0c1e8226 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -532,7 +532,7 @@ github.com/coreos/go-systemd/v22/journal ## explicit; go 1.18 github.com/coreos/stream-metadata-go/stream github.com/coreos/stream-metadata-go/stream/rhcos -# github.com/cyphar/filepath-securejoin v0.6.0 => github.com/wangke19/filepath-securejoin-1 v0.6.2-0.20260309113322-d8b3e820b3d6 +# github.com/cyphar/filepath-securejoin v0.6.0 ## explicit; go 1.18 github.com/cyphar/filepath-securejoin github.com/cyphar/filepath-securejoin/internal/consts @@ -4923,7 +4923,6 @@ sigs.k8s.io/structured-merge-diff/v6/value sigs.k8s.io/yaml sigs.k8s.io/yaml/goyaml.v2 sigs.k8s.io/yaml/kyaml -# github.com/cyphar/filepath-securejoin => github.com/wangke19/filepath-securejoin-1 v0.6.2-0.20260309113322-d8b3e820b3d6 # github.com/onsi/ginkgo/v2 => github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20251001123353-fd5b1fb35db1 # go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc => go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 # k8s.io/api => github.com/openshift/kubernetes/staging/src/k8s.io/api v0.0.0-20251017123720-96593f323733