diff options
28 files changed, 200 insertions, 266 deletions
diff --git a/.github/workflows/release-artifacts.yml b/.github/workflows/release-artifacts.yml index 92a0f07e2..2f2e6b632 100644 --- a/.github/workflows/release-artifacts.yml +++ b/.github/workflows/release-artifacts.yml @@ -23,7 +23,7 @@ permissions: jobs: build: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: # If the job fails, these details are all but impossible to observe.yy - name: Provide github event JSON for examination @@ -212,7 +212,7 @@ jobs: notification: if: needs.build.outputs.uploaded == 'true' - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 needs: build steps: - name: Format release email diff --git a/.github/workflows/update-podmanio.yml b/.github/workflows/update-podmanio.yml index 8f1287cef..de5c11967 100644 --- a/.github/workflows/update-podmanio.yml +++ b/.github/workflows/update-podmanio.yml @@ -12,7 +12,7 @@ on: jobs: bump: name: Bump - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - name: Get version id: getversion diff --git a/cmd/podman/root.go b/cmd/podman/root.go index 1ad2cc18b..e48b497d7 100644 --- a/cmd/podman/root.go +++ b/cmd/podman/root.go @@ -543,7 +543,7 @@ func rootFlags(cmd *cobra.Command, podmanConfig *entities.PodmanConfig) { pFlags.StringVar(&podmanConfig.ConmonPath, conmonFlagName, "", "Path of the conmon binary") _ = cmd.RegisterFlagCompletionFunc(conmonFlagName, completion.AutocompleteDefault) - // TODO (5.0): --network-cmd-path is deprecated, remove this option with the next major release + // TODO (6.0): --network-cmd-path is deprecated, remove this option with the next major release // We need to find all the places that use r.config.Engine.NetworkCmdPath and remove it networkCmdPathFlagName := "network-cmd-path" pFlags.StringVar(&podmanConfig.ContainersConf.Engine.NetworkCmdPath, networkCmdPathFlagName, podmanConfig.ContainersConfDefaultsRO.Engine.NetworkCmdPath, "Path to the command for configuring the network") diff --git a/docs/source/markdown/options/add-host.md b/docs/source/markdown/options/add-host.md index 649bccf7b..4b4ad1e7e 100644 --- a/docs/source/markdown/options/add-host.md +++ b/docs/source/markdown/options/add-host.md @@ -2,10 +2,28 @@ ####> podman build, create, farm build, pod create, run ####> If file is edited, make sure the changes ####> are applicable to all of those. -#### **--add-host**=*host:ip* +#### **--add-host**=*hostname[;hostname[;...]]*:*ip* -Add a custom host-to-IP mapping (host:ip) -Multiple hostnames for the same IP can be separated by semicolons. +Add a custom host-to-IP mapping to the <<container|pod>>'s `/etc/hosts` file. -Add a line to /etc/hosts. The format is hostname:ip or hostname1;hostname2;hostname3:ip if you want to map multiple hostnames to the same ip without duplicating the --add-host parameter. The **--add-host** -option can be set multiple times. Conflicts with the **--no-hosts** option. +The option takes one or multiple semicolon-separated hostnames to be mapped to +a single IPv4 or IPv6 address, separated by a colon. It can also be used to +overwrite the IP addresses of hostnames Podman adds to `/etc/hosts` by default +(also see the **--name** and **--hostname** options). This option can be +specified multiple times to add additional mappings to `/etc/hosts`. It +conflicts with the **--no-hosts** option. + +Instead of an IP address, the special flag *host-gateway* can be given. This +resolves to an IP address the container can use to connect to the host. The +IP address chosen depends on your network setup, thus there's no guarantee that +Podman can determine the *host-gateway* address automatically, which will then +cause Podman to fail with an error message. You can overwrite this IP address +using the *host_containers_internal_ip* option in *containers.conf*. + +The *host-gateway* address is also used by Podman to automatically add the +`host.containers.internal` and `host.docker.internal` hostnames to `/etc/hosts`. +You can prevent that by either giving the **--no-hosts** option, or by setting +*host_containers_internal_ip="none"* in *containers.conf*. If no *host-gateway* +address was configured manually and Podman fails to determine the IP address +automatically, Podman will silently skip adding these internal hostnames to +`/etc/hosts`. diff --git a/docs/source/markdown/options/compression-format.md b/docs/source/markdown/options/compression-format.md index 0fe49d958..cd0095c9e 100644 --- a/docs/source/markdown/options/compression-format.md +++ b/docs/source/markdown/options/compression-format.md @@ -5,3 +5,4 @@ #### **--compression-format**=**gzip** | *zstd* | *zstd:chunked* Specifies the compression format to use. Supported values are: `gzip`, `zstd` and `zstd:chunked`. The default is `gzip` unless overridden in the containers.conf file. +`zstd:chunked` is incompatible with encrypting images, and will be treated as `zstd` with a warning in that case. diff --git a/docs/source/markdown/options/hostname.container.md b/docs/source/markdown/options/hostname.container.md index 4177a41c4..ab7e76c9e 100644 --- a/docs/source/markdown/options/hostname.container.md +++ b/docs/source/markdown/options/hostname.container.md @@ -4,6 +4,10 @@ ####> are applicable to all of those. #### **--hostname**, **-h**=*name* -Container host name +Set the container's hostname inside the container. -Sets the container host name that is available inside the container. Can only be used with a private UTS namespace `--uts=private` (default). If `--pod` is specified and the pod shares the UTS namespace (default) the pod's hostname is used. +This option can only be used with a private UTS namespace `--uts=private` +(default). If `--pod` is given and the pod shares the same UTS namespace +(default), the pod's hostname is used. The given hostname is also added to the +`/etc/hosts` file using the container's primary IP address (also see the +**--add-host** option). diff --git a/docs/source/markdown/options/hostname.pod.md b/docs/source/markdown/options/hostname.pod.md index 81efeaf2b..4097bc922 100644 --- a/docs/source/markdown/options/hostname.pod.md +++ b/docs/source/markdown/options/hostname.pod.md @@ -4,4 +4,7 @@ ####> are applicable to all of those. #### **--hostname**=*name* -Set a hostname to the pod. +Set the pod's hostname inside all containers. + +The given hostname is also added to the `/etc/hosts` file using the container's +primary IP address (also see the **--add-host** option). diff --git a/docs/source/markdown/options/name.container.md b/docs/source/markdown/options/name.container.md index 8f06e8d01..b7b454bc0 100644 --- a/docs/source/markdown/options/name.container.md +++ b/docs/source/markdown/options/name.container.md @@ -12,7 +12,9 @@ The operator can identify a container in three ways: - UUID short identifier (“f78375b1c487”); - Name (“jonah”). -Podman generates a UUID for each container, and if a name is not assigned -to the container with **--name** then it generates a random -string name. The name can be useful as a more human-friendly way to identify containers. -This works for both background and foreground containers. +Podman generates a UUID for each container, and if no name is assigned to the +container using **--name**, Podman generates a random string name. The name can +be useful as a more human-friendly way to identify containers. This works for +both background and foreground containers. The container's name is also added +to the `/etc/hosts` file using the container's primary IP address (also see the +**--add-host** option). diff --git a/docs/source/markdown/options/no-hosts.md b/docs/source/markdown/options/no-hosts.md index 9ed32be7a..ee033f4fe 100644 --- a/docs/source/markdown/options/no-hosts.md +++ b/docs/source/markdown/options/no-hosts.md @@ -4,6 +4,12 @@ ####> are applicable to all of those. #### **--no-hosts** -Do not create _/etc/hosts_ for the <<container|pod>>. -By default, Podman manages _/etc/hosts_, adding the container's own IP address and any hosts from **--add-host**. -**--no-hosts** disables this, and the image's _/etc/hosts_ is preserved unmodified. +Do not modify the `/etc/hosts` file in the <<container|pod>>. + +Podman assumes control over the <<container|pod>>'s `/etc/hosts` file by +default and adds entries for the container's name (see **--name** option) and +hostname (see **--hostname** option), the internal `host.containers.internal` +and `host.docker.internal` hosts, as well as any hostname added using the +**--add-host** option. Refer to the **--add-host** option for details. Passing +**--no-hosts** disables this, so that the image's `/etc/hosts` file is kept +unmodified. diff --git a/docs/source/markdown/podman.1.md b/docs/source/markdown/podman.1.md index ee62f1b52..548408061 100644 --- a/docs/source/markdown/podman.1.md +++ b/docs/source/markdown/podman.1.md @@ -101,7 +101,7 @@ Further note that the flag is a root-level flag and must be specified before any #### **--network-cmd-path**=*path* Path to the `slirp4netns(1)` command binary to use for setting up a slirp4netns network. If "" is used, then the binary will first be searched using the `helper_binaries_dir` option in `containers.conf`, and second using the `$PATH` environment variable. -**Note:** This option is deprecated and will be removed with Podman 5.0. Use the `helper_binaries_dir` option in `containers.conf` instead. +**Note:** This option is deprecated and will be removed with Podman 6.0. Use the `helper_binaries_dir` option in `containers.conf` instead. #### **--network-config-dir**=*directory* @@ -26,14 +26,14 @@ require ( github.com/coreos/stream-metadata-go v0.4.4 github.com/crc-org/crc/v2 v2.38.0 github.com/crc-org/vfkit v0.5.1 - github.com/cyphar/filepath-securejoin v0.3.2 + github.com/cyphar/filepath-securejoin v0.3.3 github.com/digitalocean/go-qemu v0.0.0-20230711162256-2e3d0186973e github.com/docker/distribution v2.8.3+incompatible github.com/docker/docker v27.3.1+incompatible github.com/docker/go-connections v0.5.0 github.com/docker/go-plugins-helpers v0.0.0-20240701071450-45e2431495c8 github.com/docker/go-units v0.5.0 - github.com/godbus/dbus/v5 v5.1.1-0.20230522191255-76236955d466 + github.com/godbus/dbus/v5 v5.1.1-0.20240921181615-a817f3cc4a9e github.com/google/gofuzz v1.2.0 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 github.com/google/uuid v1.6.0 @@ -120,8 +120,8 @@ github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f h1:eHnXnuK47UlSTOQexbzxAZfekVz6i+LKRdj1CU5DPaM= github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw= -github.com/cyphar/filepath-securejoin v0.3.2 h1:QhZu5AxQ+o1XZH0Ye05YzvJ0kAdK6VQc0z9NNMek7gc= -github.com/cyphar/filepath-securejoin v0.3.2/go.mod h1:F7i41x/9cBF7lzCrVsYs9fuzwRZm4NQsGTBdpp6mETc= +github.com/cyphar/filepath-securejoin v0.3.3 h1:lofZkCEVFIBe0KcdQOzFs8Soy9oaHOWl4gGtPI+gCFc= +github.com/cyphar/filepath-securejoin v0.3.3/go.mod h1:8s/MCNJREmFK0H02MF6Ihv1nakJe4L/w3WZLHNkvlYM= 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= @@ -220,8 +220,8 @@ github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncV github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.1.1-0.20230522191255-76236955d466 h1:sQspH8M4niEijh3PFscJRLDnkL547IeP7kpPe3uUhEg= -github.com/godbus/dbus/v5 v5.1.1-0.20230522191255-76236955d466/go.mod h1:ZiQxhyQ+bbbfxUKVvjfO498oPYvtYhZzycal3G/NHmU= +github.com/godbus/dbus/v5 v5.1.1-0.20240921181615-a817f3cc4a9e h1:znsZ+BW06LsAtZwQvY/rgWQ3o1q0mnR4SG4q8HCP+3Q= +github.com/godbus/dbus/v5 v5.1.1-0.20240921181615-a817f3cc4a9e/go.mod h1:nRJ+j259aT/CW6otoGCHPa1K/lNHLO+UGmW133FNj9s= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -642,7 +642,6 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go index 3551613a1..87d848478 100644 --- a/libpod/runtime_ctr.go +++ b/libpod/runtime_ctr.go @@ -1412,13 +1412,13 @@ func (r *Runtime) IsStorageContainerMounted(id string) (bool, string, error) { mountCnt, err := r.storageService.MountedContainerImage(id) if err != nil { - return false, "", err + return false, "", fmt.Errorf("get mount count of container: %w", err) } mounted := mountCnt > 0 if mounted { path, err = r.storageService.GetMountpoint(id) if err != nil { - return false, "", err + return false, "", fmt.Errorf("get container mount point: %w", err) } } return mounted, path, nil diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go index 6c9a82099..b6a7baa04 100644 --- a/pkg/domain/infra/abi/containers.go +++ b/pkg/domain/infra/abi/containers.go @@ -1418,10 +1418,10 @@ func (ic *ContainerEngine) ContainerMount(ctx context.Context, nameOrIDs []strin // This can only happen in a narrow race because we first create the storage // container and then the libpod container so the StorageContainers() call // above would need to happen in that interval. - if errors.Is(err, types.ErrContainerUnknown) || errors.Is(err, define.ErrCtrExists) { + if errors.Is(err, types.ErrContainerUnknown) || errors.Is(err, types.ErrLayerUnknown) || errors.Is(err, define.ErrCtrExists) { continue } - return nil, err + return nil, fmt.Errorf("check if storage container is mounted: %w", err) } var name string @@ -1449,7 +1449,7 @@ func (ic *ContainerEngine) ContainerMount(ctx context.Context, nameOrIDs []strin errors.Is(err, define.ErrCtrRemoved) { continue } - return nil, err + return nil, fmt.Errorf("check if container is mounted: %w", err) } if mounted { diff --git a/vendor/github.com/cyphar/filepath-securejoin/CHANGELOG.md b/vendor/github.com/cyphar/filepath-securejoin/CHANGELOG.md index 98172cedd..23f7bc7f6 100644 --- a/vendor/github.com/cyphar/filepath-securejoin/CHANGELOG.md +++ b/vendor/github.com/cyphar/filepath-securejoin/CHANGELOG.md @@ -6,6 +6,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] ## +## [0.3.3] - 2024-09-30 ## + +### Fixed ### +- The mode and owner verification logic in `MkdirAll` has been removed. This + was originally intended to protect against some theoretical attacks but upon + further consideration these protections don't actually buy us anything and + they were causing spurious errors with more complicated filesystem setups. +- The "is the created directory empty" logic in `MkdirAll` has also been + removed. This was not causing us issues yet, but some pseudofilesystems (such + as `cgroup`) create non-empty directories and so this logic would've been + wrong for such cases. + ## [0.3.2] - 2024-09-13 ## ### Changed ### @@ -145,7 +157,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.3.2...HEAD +[Unreleased]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.3...HEAD +[0.3.3]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.2...v0.3.3 [0.3.2]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.1...v0.3.2 [0.3.1]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.0...v0.3.1 [0.3.0]: https://github.com/cyphar/filepath-securejoin/compare/v0.2.5...v0.3.0 diff --git a/vendor/github.com/cyphar/filepath-securejoin/VERSION b/vendor/github.com/cyphar/filepath-securejoin/VERSION index d15723fbe..1c09c74e2 100644 --- a/vendor/github.com/cyphar/filepath-securejoin/VERSION +++ b/vendor/github.com/cyphar/filepath-securejoin/VERSION @@ -1 +1 @@ -0.3.2 +0.3.3 diff --git a/vendor/github.com/cyphar/filepath-securejoin/join.go b/vendor/github.com/cyphar/filepath-securejoin/join.go index bd86a48b0..ca4ce1f29 100644 --- a/vendor/github.com/cyphar/filepath-securejoin/join.go +++ b/vendor/github.com/cyphar/filepath-securejoin/join.go @@ -22,27 +22,27 @@ const maxSymlinkLimit = 255 // IsNotExist tells you if err is an error that implies that either the path // accessed does not exist (or path components don't exist). This is -// effectively a more broad version of os.IsNotExist. +// effectively a more broad version of [os.IsNotExist]. func IsNotExist(err error) bool { // Check that it's not actually an ENOTDIR, which in some cases is a more // convoluted case of ENOENT (usually involving weird paths). return errors.Is(err, os.ErrNotExist) || errors.Is(err, syscall.ENOTDIR) || errors.Is(err, syscall.ENOENT) } -// SecureJoinVFS joins the two given path components (similar to Join) except +// SecureJoinVFS joins the two given path components (similar to [filepath.Join]) except // that the returned path is guaranteed to be scoped inside the provided root // path (when evaluated). Any symbolic links in the path are evaluated with the // given root treated as the root of the filesystem, similar to a chroot. The -// filesystem state is evaluated through the given VFS interface (if nil, the -// standard os.* family of functions are used). +// filesystem state is evaluated through the given [VFS] interface (if nil, the +// standard [os].* family of functions are used). // // Note that the guarantees provided by this function only apply if the path // components in the returned string are not modified (in other words are not // replaced with symlinks on the filesystem) after this function has returned. -// Such a symlink race is necessarily out-of-scope of SecureJoin. +// Such a symlink race is necessarily out-of-scope of SecureJoinVFS. // // NOTE: Due to the above limitation, Linux users are strongly encouraged to -// use OpenInRoot instead, which does safely protect against these kinds of +// use [OpenInRoot] instead, which does safely protect against these kinds of // attacks. There is no way to solve this problem with SecureJoinVFS because // the API is fundamentally wrong (you cannot return a "safe" path string and // guarantee it won't be modified afterwards). @@ -123,8 +123,8 @@ func SecureJoinVFS(root, unsafePath string, vfs VFS) (string, error) { return filepath.Join(root, finalPath), nil } -// SecureJoin is a wrapper around SecureJoinVFS that just uses the os.* library -// of functions as the VFS. If in doubt, use this function over SecureJoinVFS. +// SecureJoin is a wrapper around [SecureJoinVFS] that just uses the [os].* library +// of functions as the [VFS]. If in doubt, use this function over [SecureJoinVFS]. func SecureJoin(root, unsafePath string) (string, error) { return SecureJoinVFS(root, unsafePath, nil) } diff --git a/vendor/github.com/cyphar/filepath-securejoin/mkdir_linux.go b/vendor/github.com/cyphar/filepath-securejoin/mkdir_linux.go index 49ffdbe02..b5f674524 100644 --- a/vendor/github.com/cyphar/filepath-securejoin/mkdir_linux.go +++ b/vendor/github.com/cyphar/filepath-securejoin/mkdir_linux.go @@ -9,7 +9,6 @@ package securejoin import ( "errors" "fmt" - "io" "os" "path/filepath" "slices" @@ -23,23 +22,23 @@ var ( errPossibleAttack = errors.New("possible attack detected") ) -// MkdirAllHandle is equivalent to MkdirAll, except that it is safer to use in -// two respects: +// MkdirAllHandle is equivalent to [MkdirAll], except that it is safer to use +// in two respects: // -// - The caller provides the root directory as an *os.File (preferably O_PATH) +// - The caller provides the root directory as an *[os.File] (preferably O_PATH) // handle. This means that the caller can be sure which root directory is // being used. Note that this can be emulated by using /proc/self/fd/... as -// the root path with MkdirAll. +// the root path with [os.MkdirAll]. // -// - Once all of the directories have been created, an *os.File (O_PATH) handle +// - Once all of the directories have been created, an *[os.File] O_PATH handle // to the directory at unsafePath is returned to the caller. This is done in // an effectively-race-free way (an attacker would only be able to swap the // final directory component), which is not possible to emulate with -// MkdirAll. +// [MkdirAll]. // // In addition, the returned handle is obtained far more efficiently than doing -// a brand new lookup of unsafePath (such as with SecureJoin or openat2) after -// doing MkdirAll. If you intend to open the directory after creating it, you +// a brand new lookup of unsafePath (such as with [SecureJoin] or openat2) after +// doing [MkdirAll]. If you intend to open the directory after creating it, you // should use MkdirAllHandle. func MkdirAllHandle(root *os.File, unsafePath string, mode int) (_ *os.File, Err error) { // Make sure there are no os.FileMode bits set. @@ -108,35 +107,6 @@ func MkdirAllHandle(root *os.File, unsafePath string, mode int) (_ *os.File, Err // Make sure the mode doesn't have any type bits. mode &^= unix.S_IFMT - // What properties do we expect any newly created directories to have? - var ( - // While umask(2) is a per-thread property, and thus this value could - // vary between threads, a functioning Go program would LockOSThread - // threads with different umasks and so we don't need to LockOSThread - // for this entire mkdirat loop (if we are in the locked thread with a - // different umask, we are already locked and there's nothing for us to - // do -- and if not then it doesn't matter which thread we run on and - // there's nothing for us to do). - expectedMode = uint32(unix.S_IFDIR | (mode &^ getUmask())) - - // We would want to get the fs[ug]id here, but we can't access those - // from userspace. In practice, nobody uses setfs[ug]id() anymore, so - // just use the effective [ug]id (which is equivalent to the fs[ug]id - // for programs that don't use setfs[ug]id). - expectedUid = uint32(unix.Geteuid()) - expectedGid = uint32(unix.Getegid()) - ) - - // The setgid bit (S_ISGID = 0o2000) is inherited to child directories and - // affects the group of any inodes created in said directory, so if the - // starting directory has it set we need to adjust our expected mode and - // owner to match. - if st, err := fstatFile(currentDir); err != nil { - return nil, fmt.Errorf("failed to stat starting path for mkdir %q: %w", currentDir.Name(), err) - } else if st.Mode&unix.S_ISGID == unix.S_ISGID { - expectedMode |= unix.S_ISGID - expectedGid = st.Gid - } // Create the remaining components. for _, part := range remainingParts { @@ -147,7 +117,7 @@ func MkdirAllHandle(root *os.File, unsafePath string, mode int) (_ *os.File, Err } // NOTE: mkdir(2) will not follow trailing symlinks, so we can safely - // create the finaly component without worrying about symlink-exchange + // create the final component without worrying about symlink-exchange // attacks. if err := unix.Mkdirat(int(currentDir.Fd()), part, uint32(mode)); err != nil { err = &os.PathError{Op: "mkdirat", Path: currentDir.Name() + "/" + part, Err: err} @@ -175,40 +145,30 @@ func MkdirAllHandle(root *os.File, unsafePath string, mode int) (_ *os.File, Err _ = currentDir.Close() currentDir = nextDir - // Make sure that the directory matches what we expect. An attacker - // could have swapped the directory between us making it and opening - // it. There's no way for us to be sure that the directory is - // _precisely_ the same as the directory we created, but if we are in - // an empty directory with the same owner and mode as the one we - // created then there is nothing the attacker could do with this new - // directory that they couldn't do with the old one. - if stat, err := fstat(currentDir); err != nil { - return nil, fmt.Errorf("check newly created directory: %w", err) - } else { - if stat.Mode != expectedMode { - return nil, fmt.Errorf("%w: newly created directory %q has incorrect mode 0o%.3o (expected 0o%.3o)", errPossibleAttack, currentDir.Name(), stat.Mode, expectedMode) - } - if stat.Uid != expectedUid || stat.Gid != expectedGid { - return nil, fmt.Errorf("%w: newly created directory %q has incorrect owner %d:%d (expected %d:%d)", errPossibleAttack, currentDir.Name(), stat.Uid, stat.Gid, expectedUid, expectedGid) - } - // Check that the directory is empty. We only need to check for - // a single entry, and we should get EOF if the directory is - // empty. - _, err := currentDir.Readdirnames(1) - if !errors.Is(err, io.EOF) { - if err == nil { - err = fmt.Errorf("%w: newly created directory %q is non-empty", errPossibleAttack, currentDir.Name()) - } - return nil, fmt.Errorf("check if newly created directory %q is empty: %w", currentDir.Name(), err) - } - // Reset the offset. - _, _ = currentDir.Seek(0, unix.SEEK_SET) - } + // It's possible that the directory we just opened was swapped by an + // attacker. Unfortunately there isn't much we can do to protect + // against this, and MkdirAll's behaviour is that we will reuse + // existing directories anyway so the need to protect against this is + // incredibly limited (and arguably doesn't even deserve mention here). + // + // Ideally we might want to check that the owner and mode match what we + // would've created -- unfortunately, it is non-trivial to verify that + // the owner and mode of the created directory match. While plain Unix + // DAC rules seem simple enough to emulate, there are a bunch of other + // factors that can change the mode or owner of created directories + // (default POSIX ACLs, mount options like uid=1,gid=2,umask=0 on + // filesystems like vfat, etc etc). We used to try to verify this but + // it just lead to a series of spurious errors. + // + // We could also check that the directory is non-empty, but + // unfortunately some pseduofilesystems (like cgroupfs) create + // non-empty directories, which would result in different spurious + // errors. } return currentDir, nil } -// MkdirAll is a race-safe alternative to the Go stdlib's os.MkdirAll function, +// MkdirAll is a race-safe alternative to the [os.MkdirAll] function, // where the new directory is guaranteed to be within the root directory (if an // attacker can move directories from inside the root to outside the root, the // created directory tree might be outside of the root but the key constraint @@ -221,16 +181,16 @@ func MkdirAllHandle(root *os.File, unsafePath string, mode int) (_ *os.File, Err // err := os.MkdirAll(path, mode) // // But is much safer. The above implementation is unsafe because if an attacker -// can modify the filesystem tree between SecureJoin and MkdirAll, it is +// can modify the filesystem tree between [SecureJoin] and [os.MkdirAll], it is // possible for MkdirAll to resolve unsafe symlink components and create // directories outside of the root. // // If you plan to open the directory after you have created it or want to use -// an open directory handle as the root, you should use MkdirAllHandle instead. -// This function is a wrapper around MkdirAllHandle. +// an open directory handle as the root, you should use [MkdirAllHandle] instead. +// This function is a wrapper around [MkdirAllHandle]. // // NOTE: The mode argument must be set the unix mode bits (unix.S_I...), not -// the Go generic mode bits (os.Mode...). +// the Go generic mode bits ([os.FileMode]...). func MkdirAll(root, unsafePath string, mode int) error { rootDir, err := os.OpenFile(root, unix.O_PATH|unix.O_DIRECTORY|unix.O_CLOEXEC, 0) if err != nil { diff --git a/vendor/github.com/cyphar/filepath-securejoin/open_linux.go b/vendor/github.com/cyphar/filepath-securejoin/open_linux.go index 52dce76f3..230be73f0 100644 --- a/vendor/github.com/cyphar/filepath-securejoin/open_linux.go +++ b/vendor/github.com/cyphar/filepath-securejoin/open_linux.go @@ -14,8 +14,8 @@ import ( "golang.org/x/sys/unix" ) -// OpenatInRoot is equivalent to OpenInRoot, except that the root is provided -// using an *os.File handle, to ensure that the correct root directory is used. +// OpenatInRoot is equivalent to [OpenInRoot], except that the root is provided +// using an *[os.File] handle, to ensure that the correct root directory is used. func OpenatInRoot(root *os.File, unsafePath string) (*os.File, error) { handle, err := completeLookupInRoot(root, unsafePath) if err != nil { @@ -31,7 +31,7 @@ func OpenatInRoot(root *os.File, unsafePath string) (*os.File, error) { // handle, err := os.OpenFile(path, unix.O_PATH|unix.O_CLOEXEC) // // But is much safer. The above implementation is unsafe because if an attacker -// can modify the filesystem tree between SecureJoin and OpenFile, it is +// can modify the filesystem tree between [SecureJoin] and [os.OpenFile], it is // possible for the returned file to be outside of the root. // // Note that the returned handle is an O_PATH handle, meaning that only a very @@ -39,7 +39,7 @@ func OpenatInRoot(root *os.File, unsafePath string) (*os.File, error) { // accidentally opening an untrusted file that could cause issues (such as a // disconnected TTY that could cause a DoS, or some other issue). In order to // use the returned handle, you can "upgrade" it to a proper handle using -// Reopen. +// [Reopen]. func OpenInRoot(root, unsafePath string) (*os.File, error) { rootDir, err := os.OpenFile(root, unix.O_PATH|unix.O_DIRECTORY|unix.O_CLOEXEC, 0) if err != nil { @@ -49,7 +49,7 @@ func OpenInRoot(root, unsafePath string) (*os.File, error) { return OpenatInRoot(rootDir, unsafePath) } -// Reopen takes an *os.File handle and re-opens it through /proc/self/fd. +// Reopen takes an *[os.File] handle and re-opens it through /proc/self/fd. // Reopen(file, flags) is effectively equivalent to // // fdPath := fmt.Sprintf("/proc/self/fd/%d", file.Fd()) @@ -59,7 +59,9 @@ func OpenInRoot(root, unsafePath string) (*os.File, error) { // maliciously-configured /proc mount. While this attack scenario is not // common, in container runtimes it is possible for higher-level runtimes to be // tricked into configuring an unsafe /proc that can be used to attack file -// operations. See CVE-2019-19921 for more details. +// operations. See [CVE-2019-19921] for more details. +// +// [CVE-2019-19921]: https://github.com/advisories/GHSA-fh74-hm69-rqjw func Reopen(handle *os.File, flags int) (*os.File, error) { procRoot, err := getProcRoot() if err != nil { diff --git a/vendor/github.com/cyphar/filepath-securejoin/openat2_linux.go b/vendor/github.com/cyphar/filepath-securejoin/openat2_linux.go index 921b3e1d4..ae3b381ef 100644 --- a/vendor/github.com/cyphar/filepath-securejoin/openat2_linux.go +++ b/vendor/github.com/cyphar/filepath-securejoin/openat2_linux.go @@ -13,34 +13,21 @@ import ( "path/filepath" "strings" "sync" - "testing" "golang.org/x/sys/unix" ) -var ( - hasOpenat2Bool bool - hasOpenat2Once sync.Once - - testingForceHasOpenat2 *bool -) - -func hasOpenat2() bool { - if testing.Testing() && testingForceHasOpenat2 != nil { - return *testingForceHasOpenat2 - } - hasOpenat2Once.Do(func() { - 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 { - hasOpenat2Bool = true - _ = unix.Close(fd) - } +var hasOpenat2 = sync.OnceValue(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, }) - return hasOpenat2Bool -} + if err != nil { + return false + } + _ = unix.Close(fd) + return true +}) func scopedLookupShouldRetry(how *unix.OpenHow, err error) bool { // RESOLVE_IN_ROOT (and RESOLVE_BENEATH) can return -EAGAIN if we resolve diff --git a/vendor/github.com/cyphar/filepath-securejoin/procfs_linux.go b/vendor/github.com/cyphar/filepath-securejoin/procfs_linux.go index adf0bd08f..fa7929a52 100644 --- a/vendor/github.com/cyphar/filepath-securejoin/procfs_linux.go +++ b/vendor/github.com/cyphar/filepath-securejoin/procfs_linux.go @@ -54,33 +54,26 @@ func verifyProcRoot(procRoot *os.File) error { return nil } -var ( - hasNewMountApiBool bool - hasNewMountApiOnce sync.Once -) - -func hasNewMountApi() bool { - hasNewMountApiOnce.Do(func() { - // All of the pieces of the new mount API we use (fsopen, fsconfig, - // fsmount, open_tree) were added together in Linux 5.1[1,2], so we can - // just check for one of the syscalls and the others should also be - // available. - // - // Just try to use open_tree(2) to open a file without OPEN_TREE_CLONE. - // This is equivalent to openat(2), but tells us if open_tree is - // available (and thus all of the other basic new mount API syscalls). - // open_tree(2) is most light-weight syscall to test here. - // - // [1]: merge commit 400913252d09 - // [2]: <https://lore.kernel.org/lkml/153754740781.17872.7869536526927736855.stgit@warthog.procyon.org.uk/> - fd, err := unix.OpenTree(-int(unix.EBADF), "/", unix.OPEN_TREE_CLOEXEC) - if err == nil { - hasNewMountApiBool = true - _ = unix.Close(fd) - } - }) - return hasNewMountApiBool -} +var hasNewMountApi = sync.OnceValue(func() bool { + // All of the pieces of the new mount API we use (fsopen, fsconfig, + // fsmount, open_tree) were added together in Linux 5.1[1,2], so we can + // just check for one of the syscalls and the others should also be + // available. + // + // Just try to use open_tree(2) to open a file without OPEN_TREE_CLONE. + // This is equivalent to openat(2), but tells us if open_tree is + // available (and thus all of the other basic new mount API syscalls). + // open_tree(2) is most light-weight syscall to test here. + // + // [1]: merge commit 400913252d09 + // [2]: <https://lore.kernel.org/lkml/153754740781.17872.7869536526927736855.stgit@warthog.procyon.org.uk/> + fd, err := unix.OpenTree(-int(unix.EBADF), "/", unix.OPEN_TREE_CLOEXEC) + if err != nil { + return false + } + _ = unix.Close(fd) + return true +}) func fsopen(fsName string, flags int) (*os.File, error) { // Make sure we always set O_CLOEXEC. @@ -172,14 +165,6 @@ func privateProcRoot() (*os.File, error) { return procRoot, err } -var ( - procRootHandle *os.File - procRootError error - procRootOnce sync.Once - - errUnsafeProcfs = errors.New("unsafe procfs detected") -) - func unsafeHostProcRoot() (_ *os.File, Err error) { procRoot, err := os.OpenFile("/proc", unix.O_PATH|unix.O_NOFOLLOW|unix.O_DIRECTORY|unix.O_CLOEXEC, 0) if err != nil { @@ -207,17 +192,15 @@ func doGetProcRoot() (*os.File, error) { return procRoot, err } -func getProcRoot() (*os.File, error) { - procRootOnce.Do(func() { - procRootHandle, procRootError = doGetProcRoot() - }) - return procRootHandle, procRootError -} +var getProcRoot = sync.OnceValues(func() (*os.File, error) { + return doGetProcRoot() +}) -var ( - haveProcThreadSelf bool - haveProcThreadSelfOnce sync.Once -) +var hasProcThreadSelf = sync.OnceValue(func() bool { + return unix.Access("/proc/thread-self/", unix.F_OK) == nil +}) + +var errUnsafeProcfs = errors.New("unsafe procfs detected") type procThreadSelfCloser func() @@ -230,13 +213,6 @@ type procThreadSelfCloser func() // This is similar to ProcThreadSelf from runc, but with extra hardening // applied and using *os.File. func procThreadSelf(procRoot *os.File, subpath string) (_ *os.File, _ procThreadSelfCloser, Err error) { - haveProcThreadSelfOnce.Do(func() { - // If the kernel doesn't support thread-self, it doesn't matter which - // /proc handle we use. - _, err := fstatatFile(procRoot, "thread-self", unix.AT_SYMLINK_NOFOLLOW) - haveProcThreadSelf = (err == nil) - }) - // We need to lock our thread until the caller is done with the handle // because between getting the handle and using it we could get interrupted // by the Go runtime and hit the case where the underlying thread is @@ -251,7 +227,7 @@ func procThreadSelf(procRoot *os.File, subpath string) (_ *os.File, _ procThread // Figure out what prefix we want to use. threadSelf := "thread-self/" - if !haveProcThreadSelf || testingForceProcSelfTask() { + if !hasProcThreadSelf() || testingForceProcSelfTask() { /// Pre-3.17 kernels don't have /proc/thread-self, so do it manually. threadSelf = "self/task/" + strconv.Itoa(unix.Gettid()) + "/" if _, err := fstatatFile(procRoot, threadSelf, unix.AT_SYMLINK_NOFOLLOW); err != nil || testingForceProcSelf() { @@ -275,7 +251,7 @@ func procThreadSelf(procRoot *os.File, subpath string) (_ *os.File, _ procThread // absolutely sure we are operating on a clean /proc handle that // doesn't have any cheeky overmounts that could trick us (including // symlink mounts on top of /proc/thread-self). RESOLVE_BENEATH isn't - // stricly needed, but just use it since we have it. + // strictly needed, but just use it since we have it. // // NOTE: /proc/self is technically a magic-link (the contents of the // symlink are generated dynamically), but it doesn't use @@ -313,24 +289,16 @@ func procThreadSelf(procRoot *os.File, subpath string) (_ *os.File, _ procThread return handle, runtime.UnlockOSThread, nil } -var ( - hasStatxMountIdBool bool - hasStatxMountIdOnce sync.Once -) - -func hasStatxMountId() bool { - hasStatxMountIdOnce.Do(func() { - var ( - stx unix.Statx_t - // We don't care which mount ID we get. The kernel will give us the - // unique one if it is supported. - wantStxMask uint32 = unix.STATX_MNT_ID_UNIQUE | unix.STATX_MNT_ID - ) - err := unix.Statx(-int(unix.EBADF), "/", 0, int(wantStxMask), &stx) - hasStatxMountIdBool = (err == nil && (stx.Mask&wantStxMask != 0)) - }) - return hasStatxMountIdBool -} +var hasStatxMountId = sync.OnceValue(func() bool { + var ( + stx unix.Statx_t + // We don't care which mount ID we get. The kernel will give us the + // unique one if it is supported. + wantStxMask uint32 = unix.STATX_MNT_ID_UNIQUE | unix.STATX_MNT_ID + ) + err := unix.Statx(-int(unix.EBADF), "/", 0, int(wantStxMask), &stx) + return err == nil && stx.Mask&wantStxMask != 0 +}) func getMountId(dir *os.File, path string) (uint64, error) { // If we don't have statx(STATX_MNT_ID*) support, we can't do anything. @@ -443,22 +411,6 @@ func isDeadInode(file *os.File) error { return nil } -func getUmask() int { - // umask is a per-thread property, but it is inherited by children, so we - // need to lock our OS thread to make sure that no other goroutine runs in - // this thread and no goroutines are spawned from this thread until we - // revert to the old umask. - // - // We could parse /proc/self/status to avoid this get-set problem, but - // /proc/thread-self requires LockOSThread anyway, so there's no real - // benefit over just using umask(2). - runtime.LockOSThread() - umask := unix.Umask(0) - unix.Umask(umask) - runtime.UnlockOSThread() - return umask -} - func checkProcSelfFdPath(path string, file *os.File) error { if err := isDeadInode(file); err != nil { return err diff --git a/vendor/github.com/cyphar/filepath-securejoin/vfs.go b/vendor/github.com/cyphar/filepath-securejoin/vfs.go index 6e27c7dd8..36373f8c5 100644 --- a/vendor/github.com/cyphar/filepath-securejoin/vfs.go +++ b/vendor/github.com/cyphar/filepath-securejoin/vfs.go @@ -10,19 +10,19 @@ import "os" // are several projects (umoci and go-mtree) that are using this sort of // interface. -// VFS is the minimal interface necessary to use SecureJoinVFS. A nil VFS is -// equivalent to using the standard os.* family of functions. This is mainly +// VFS is the minimal interface necessary to use [SecureJoinVFS]. A nil VFS is +// equivalent to using the standard [os].* family of functions. This is mainly // used for the purposes of mock testing, but also can be used to otherwise use -// SecureJoin with VFS-like system. +// [SecureJoinVFS] with VFS-like system. type VFS interface { - // Lstat returns a FileInfo describing the named file. If the file is a - // symbolic link, the returned FileInfo describes the symbolic link. Lstat - // makes no attempt to follow the link. These semantics are identical to - // os.Lstat. + // Lstat returns an [os.FileInfo] describing the named file. If the + // file is a symbolic link, the returned [os.FileInfo] describes the + // symbolic link. Lstat makes no attempt to follow the link. + // The semantics are identical to [os.Lstat]. Lstat(name string) (os.FileInfo, error) - // Readlink returns the destination of the named symbolic link. These - // semantics are identical to os.Readlink. + // Readlink returns the destination of the named symbolic link. + // The semantics are identical to [os.Readlink]. Readlink(name string) (string, error) } @@ -30,12 +30,6 @@ type VFS interface { // module. type osVFS struct{} -// Lstat returns a FileInfo describing the named file. If the file is a -// symbolic link, the returned FileInfo describes the symbolic link. Lstat -// makes no attempt to follow the link. These semantics are identical to -// os.Lstat. func (o osVFS) Lstat(name string) (os.FileInfo, error) { return os.Lstat(name) } -// Readlink returns the destination of the named symbolic link. These -// semantics are identical to os.Readlink. func (o osVFS) Readlink(name string) (string, error) { return os.Readlink(name) } diff --git a/vendor/github.com/godbus/dbus/v5/.cirrus.yml b/vendor/github.com/godbus/dbus/v5/.cirrus.yml index 4e900f86d..75a0d798a 100644 --- a/vendor/github.com/godbus/dbus/v5/.cirrus.yml +++ b/vendor/github.com/godbus/dbus/v5/.cirrus.yml @@ -1,10 +1,10 @@ freebsd_instance: - image_family: freebsd-13-0 + image_family: freebsd-14-0 task: name: Test on FreeBSD - install_script: pkg install -y go119 dbus + install_script: pkg install -y go122 dbus test_script: | /usr/local/etc/rc.d/dbus onestart && \ eval `dbus-launch --sh-syntax` && \ - go119 test -v ./... + go122 test -v ./... diff --git a/vendor/github.com/godbus/dbus/v5/README.md b/vendor/github.com/godbus/dbus/v5/README.md index 5c6b19655..da848a98d 100644 --- a/vendor/github.com/godbus/dbus/v5/README.md +++ b/vendor/github.com/godbus/dbus/v5/README.md @@ -14,7 +14,7 @@ D-Bus message bus system. ### Installation -This packages requires Go 1.12 or later. It can be installed by running the command below: +This packages requires Go 1.20 or later. It can be installed by running the command below: ``` go get github.com/godbus/dbus/v5 diff --git a/vendor/github.com/godbus/dbus/v5/conn_other.go b/vendor/github.com/godbus/dbus/v5/conn_other.go index 067e67cc5..1e9959446 100644 --- a/vendor/github.com/godbus/dbus/v5/conn_other.go +++ b/vendor/github.com/godbus/dbus/v5/conn_other.go @@ -7,7 +7,6 @@ import ( "bytes" "errors" "fmt" - "io/ioutil" "os" "os/exec" "os/user" @@ -61,7 +60,7 @@ func tryDiscoverDbusSessionBusAddress() string { // text file // containing the address of the socket, e.g.: // DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-E1c73yNqrG - if f, err := ioutil.ReadFile(runUserSessionDbusFile); err == nil { + if f, err := os.ReadFile(runUserSessionDbusFile); err == nil { fileContent := string(f) prefix := "DBUS_SESSION_BUS_ADDRESS=" diff --git a/vendor/github.com/godbus/dbus/v5/decoder.go b/vendor/github.com/godbus/dbus/v5/decoder.go index 97a827b83..d03bdd8e8 100644 --- a/vendor/github.com/godbus/dbus/v5/decoder.go +++ b/vendor/github.com/godbus/dbus/v5/decoder.go @@ -370,12 +370,6 @@ func (c *stringConverter) String(b []byte) string { } // toString converts a byte slice to a string without allocating. -// Starting from Go 1.20 you should use unsafe.String. func toString(b []byte) string { - var s string - h := (*reflect.StringHeader)(unsafe.Pointer(&s)) - h.Data = uintptr(unsafe.Pointer(&b[0])) - h.Len = len(b) - - return s + return unsafe.String(&b[0], len(b)) } diff --git a/vendor/github.com/godbus/dbus/v5/transport_nonce_tcp.go b/vendor/github.com/godbus/dbus/v5/transport_nonce_tcp.go index a61a82084..a08d0891c 100644 --- a/vendor/github.com/godbus/dbus/v5/transport_nonce_tcp.go +++ b/vendor/github.com/godbus/dbus/v5/transport_nonce_tcp.go @@ -5,8 +5,8 @@ package dbus import ( "errors" - "io/ioutil" "net" + "os" ) func init() { @@ -28,7 +28,7 @@ func newNonceTcpTransport(keys string) (transport, error) { if err != nil { return nil, err } - b, err := ioutil.ReadFile(noncefile) + b, err := os.ReadFile(noncefile) if err != nil { return nil, err } diff --git a/vendor/modules.txt b/vendor/modules.txt index a57610d65..130a8d38c 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -440,8 +440,8 @@ github.com/crc-org/vfkit/pkg/util # github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f ## explicit github.com/cyberphone/json-canonicalization/go/src/webpki.org/jsoncanonicalizer -# github.com/cyphar/filepath-securejoin v0.3.2 -## explicit; go 1.20 +# github.com/cyphar/filepath-securejoin v0.3.3 +## explicit; go 1.21 github.com/cyphar/filepath-securejoin # github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc ## explicit @@ -636,8 +636,8 @@ github.com/goccy/go-json/internal/encoder/vm_color_indent github.com/goccy/go-json/internal/encoder/vm_indent github.com/goccy/go-json/internal/errors github.com/goccy/go-json/internal/runtime -# github.com/godbus/dbus/v5 v5.1.1-0.20230522191255-76236955d466 -## explicit; go 1.12 +# github.com/godbus/dbus/v5 v5.1.1-0.20240921181615-a817f3cc4a9e +## explicit; go 1.20 github.com/godbus/dbus/v5 # github.com/gogo/protobuf v1.3.2 ## explicit; go 1.15 |