From a018ec2b0ca6b91fcf624040aaa7ef6fd44e2918 Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Wed, 2 Oct 2024 10:48:45 +0200 Subject: [PATCH] vendor: update c/common to latest Contains a fix for CVE-2024-9341 Signed-off-by: Paul Holzinger --- go.mod | 11 +- go.sum | 26 +- .../containers/common/libimage/copier.go | 40 +- .../containers/common/libimage/import.go | 4 +- .../common/libimage/manifest_list.go | 164 +++++- .../common/libimage/manifests/manifests.go | 28 +- .../containers/common/libimage/pull.go | 12 +- .../containers/common/libimage/push.go | 4 +- .../containers/common/libimage/save.go | 8 +- .../common/pkg/capabilities/capabilities.go | 115 ++-- .../common/pkg/cgroups/cgroups_linux.go | 52 +- .../common/pkg/config/containers.conf | 4 + .../common/pkg/config/containers.conf-freebsd | 2 + .../common/pkg/netns/netns_linux.go | 154 +++-- .../common/pkg/subscriptions/subscriptions.go | 6 +- .../github.com/docker/docker/api/swagger.yaml | 49 +- .../docker/docker/api/types/filters/parse.go | 2 +- .../docker/docker/api/types/image/summary.go | 2 +- .../docker/docker/api/types/swarm/swarm.go | 2 +- .../docker/api/types/volume/cluster_volume.go | 2 +- .../docker/pkg/jsonmessage/jsonmessage.go | 2 +- .../docker/docker/pkg/pools/pools.go | 2 +- .../docker/docker/pkg/system/xattrs_linux.go | 2 +- .../moby/sys/capability/.codespellrc | 3 + .../moby/sys/capability/.golangci.yml | 6 + .../moby/sys/capability/CHANGELOG.md | 90 +++ vendor/github.com/moby/sys/capability/LICENSE | 25 + .../github.com/moby/sys/capability/README.md | 13 + .../moby/sys/capability/capability.go | 144 +++++ .../moby/sys/capability/capability_linux.go | 541 ++++++++++++++++++ .../moby/sys/capability/capability_noop.go | 26 + vendor/github.com/moby/sys/capability/enum.go | 330 +++++++++++ .../moby/sys/capability/enum_gen.go | 137 +++++ .../moby/sys/capability/syscall_linux.go | 153 +++++ vendor/modules.txt | 17 +- 35 files changed, 1984 insertions(+), 194 deletions(-) create mode 100644 vendor/github.com/moby/sys/capability/.codespellrc create mode 100644 vendor/github.com/moby/sys/capability/.golangci.yml create mode 100644 vendor/github.com/moby/sys/capability/CHANGELOG.md create mode 100644 vendor/github.com/moby/sys/capability/LICENSE create mode 100644 vendor/github.com/moby/sys/capability/README.md create mode 100644 vendor/github.com/moby/sys/capability/capability.go create mode 100644 vendor/github.com/moby/sys/capability/capability_linux.go create mode 100644 vendor/github.com/moby/sys/capability/capability_noop.go create mode 100644 vendor/github.com/moby/sys/capability/enum.go create mode 100644 vendor/github.com/moby/sys/capability/enum_gen.go create mode 100644 vendor/github.com/moby/sys/capability/syscall_linux.go diff --git a/go.mod b/go.mod index 0d5b25cb0f0..cb8a251a38d 100644 --- a/go.mod +++ b/go.mod @@ -7,14 +7,14 @@ go 1.22.0 require ( github.com/containerd/platforms v0.2.1 github.com/containernetworking/cni v1.2.3 - github.com/containers/common v0.60.1-0.20240906123248-5298b838dcbd + github.com/containers/common v0.60.1-0.20241001171026-c3edf18f3339 github.com/containers/image/v5 v5.32.2 github.com/containers/luksy v0.0.0-20240812184316-2e7307c02f06 github.com/containers/ocicrypt v1.2.0 github.com/containers/storage v1.55.1-0.20240829103427-8bc8379af275 github.com/cyphar/filepath-securejoin v0.3.3 github.com/docker/distribution v2.8.3+incompatible - github.com/docker/docker v27.2.1+incompatible + github.com/docker/docker v27.3.1+incompatible github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 github.com/fsouza/go-dockerclient v1.12.0 @@ -36,7 +36,7 @@ require ( github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 go.etcd.io/bbolt v1.3.11 golang.org/x/crypto v0.27.0 - golang.org/x/exp v0.0.0-20240823005443-9b4947da3948 + golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 golang.org/x/sync v0.8.0 golang.org/x/sys v0.25.0 golang.org/x/term v0.24.0 @@ -108,6 +108,7 @@ require ( github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/patternmatcher v0.6.0 // indirect + github.com/moby/sys/capability v0.3.0 // indirect github.com/moby/sys/mountinfo v0.7.2 // indirect github.com/moby/sys/sequential v0.5.0 // indirect github.com/moby/sys/user v0.3.0 // indirect @@ -142,8 +143,8 @@ require ( go.opentelemetry.io/otel v1.28.0 // indirect go.opentelemetry.io/otel/metric v1.28.0 // indirect go.opentelemetry.io/otel/trace v1.28.0 // indirect - golang.org/x/mod v0.20.0 // indirect - golang.org/x/net v0.28.0 // indirect + golang.org/x/mod v0.21.0 // indirect + golang.org/x/net v0.29.0 // indirect golang.org/x/text v0.18.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect google.golang.org/grpc v1.65.0 // indirect diff --git a/go.sum b/go.sum index 255aaf96b6c..0a8bfe7d77c 100644 --- a/go.sum +++ b/go.sum @@ -61,8 +61,8 @@ github.com/containernetworking/cni v1.2.3 h1:hhOcjNVUQTnzdRJ6alC5XF+wd9mfGIUaj8F github.com/containernetworking/cni v1.2.3/go.mod h1:DuLgF+aPd3DzcTQTtp/Nvl1Kim23oFKdm2okJzBQA5M= github.com/containernetworking/plugins v1.5.1 h1:T5ji+LPYjjgW0QM+KyrigZbLsZ8jaX+E5J/EcKOE4gQ= github.com/containernetworking/plugins v1.5.1/go.mod h1:MIQfgMayGuHYs0XdNudf31cLLAC+i242hNm6KuDGqCM= -github.com/containers/common v0.60.1-0.20240906123248-5298b838dcbd h1:eUzsKokkxMAxqBwCD1agfKf6lIZEQ/ayPru7Tb/oW9Y= -github.com/containers/common v0.60.1-0.20240906123248-5298b838dcbd/go.mod h1:f/n9w0F2lW52S3ppXjQlSVazsyNdilFZ80AyrFl4zn4= +github.com/containers/common v0.60.1-0.20241001171026-c3edf18f3339 h1:VjK9wBKZTbmZqZ0qW2QlbW81xOu8YxXecek5MUSLGKc= +github.com/containers/common v0.60.1-0.20241001171026-c3edf18f3339/go.mod h1:vuBEtzP83Fa7mgk0BJdHF2BDfFRfNayeYyVHRJw8hSM= github.com/containers/image/v5 v5.32.2 h1:SzNE2Y6sf9b1GJoC8qjCuMBXwQrACFp4p0RK15+4gmQ= github.com/containers/image/v5 v5.32.2/go.mod h1:v1l73VeMugfj/QtKI+jhYbwnwFCFnNGckvbST3rQ5Hk= github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 h1:Qzk5C6cYglewc+UyGf6lc8Mj2UaPTHy/iF2De0/77CA= @@ -94,8 +94,8 @@ github.com/docker/cli v27.2.1+incompatible h1:U5BPtiD0viUzjGAjV1p0MGB8eVA3L3cbIr github.com/docker/cli v27.2.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v27.2.1+incompatible h1:fQdiLfW7VLscyoeYEBz7/J8soYFDZV1u6VW6gJEjNMI= -github.com/docker/docker v27.2.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.3.1+incompatible h1:KttF0XoteNTicmUtBO0L2tP+J7FGRFTjaEF4k6WdhfI= +github.com/docker/docker v27.3.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= @@ -240,6 +240,8 @@ github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3N github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= +github.com/moby/sys/capability v0.3.0 h1:kEP+y6te0gEXIaeQhIi0s7vKs/w0RPoH1qPa6jROcVg= +github.com/moby/sys/capability v0.3.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I= github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= @@ -389,15 +391,15 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20240823005443-9b4947da3948 h1:kx6Ds3MlpiUHKj7syVnbp57++8WpuKPcR5yjLBjvLEA= -golang.org/x/exp v0.0.0-20240823005443-9b4947da3948/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ= +golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= +golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= -golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= +golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -407,8 +409,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= -golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -445,8 +447,8 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= -golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= +golang.org/x/tools v0.25.0 h1:oFU9pkj/iJgs+0DT+VMHrx+oBKs/LJMV+Uvg78sl+fE= +golang.org/x/tools v0.25.0/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/vendor/github.com/containers/common/libimage/copier.go b/vendor/github.com/containers/common/libimage/copier.go index 1f4f925fe5f..b2cd6cedb31 100644 --- a/vendor/github.com/containers/common/libimage/copier.go +++ b/vendor/github.com/containers/common/libimage/copier.go @@ -60,6 +60,13 @@ type CopyOptions struct { CertDirPath string // Force layer compression when copying to a `dir` transport destination. DirForceCompress bool + + // ImageListSelection is one of CopySystemImage, CopyAllImages, or + // CopySpecificImages, to control whether, when the source reference is a list, + // copy.Image() copies only an image which matches the current runtime + // environment, or all images which match the supplied reference, or only + // specific images from the source reference. + ImageListSelection copy.ImageListSelection // Allow contacting registries over HTTP, or HTTPS with failed TLS // verification. Note that this does not affect other TLS connections. InsecureSkipTLSVerify types.OptionalBool @@ -153,8 +160,8 @@ type CopyOptions struct { extendTimeoutSocket string } -// copier is an internal helper to conveniently copy images. -type copier struct { +// Copier is a helper to conveniently copy images. +type Copier struct { extendTimeoutSocket string imageCopyOptions copy.Options retryOptions retry.Options @@ -165,6 +172,13 @@ type copier struct { destinationLookup LookupReferenceFunc } +// newCopier creates a Copier based on a runtime's system context. +// Note that fields in options *may* overwrite the counterparts of +// the specified system context. Please make sure to call `(*Copier).Close()`. +func (r *Runtime) newCopier(options *CopyOptions) (*Copier, error) { + return NewCopier(options, r.SystemContext()) +} + // storageAllowedPolicyScopes overrides the policy for local storage // to ensure that we can read images from it. var storageAllowedPolicyScopes = signature.PolicyTransportScopes{ @@ -206,12 +220,13 @@ func getDockerAuthConfig(name, passwd, creds, idToken string) (*types.DockerAuth } } -// newCopier creates a copier. Note that fields in options *may* overwrite the -// counterparts of the specified system context. Please make sure to call -// `(*copier).close()`. -func (r *Runtime) newCopier(options *CopyOptions) (*copier, error) { - c := copier{extendTimeoutSocket: options.extendTimeoutSocket} - c.systemContext = r.systemContextCopy() +// NewCopier creates a Copier based on a provided system context. +// Note that fields in options *may* overwrite the counterparts of +// the specified system context. Please make sure to call `(*Copier).Close()`. +func NewCopier(options *CopyOptions, sc *types.SystemContext) (*Copier, error) { + c := Copier{extendTimeoutSocket: options.extendTimeoutSocket} + sysContextCopy := *sc + c.systemContext = &sysContextCopy if options.SourceLookupReferenceFunc != nil { c.sourceLookup = options.SourceLookupReferenceFunc @@ -300,6 +315,7 @@ func (r *Runtime) newCopier(options *CopyOptions) (*copier, error) { c.imageCopyOptions.ProgressInterval = time.Second } + c.imageCopyOptions.ImageListSelection = options.ImageListSelection c.imageCopyOptions.ForceCompressionFormat = options.ForceCompressionFormat c.imageCopyOptions.ForceManifestMIMEType = options.ManifestMIMEType c.imageCopyOptions.SourceCtx = c.systemContext @@ -325,14 +341,14 @@ func (r *Runtime) newCopier(options *CopyOptions) (*copier, error) { return &c, nil } -// close open resources. -func (c *copier) close() error { +// Close open resources. +func (c *Copier) Close() error { return c.policyContext.Destroy() } -// copy the source to the destination. Returns the bytes of the copied +// Copy the source to the destination. Returns the bytes of the copied // manifest which may be used for digest computation. -func (c *copier) copy(ctx context.Context, source, destination types.ImageReference) ([]byte, error) { +func (c *Copier) Copy(ctx context.Context, source, destination types.ImageReference) ([]byte, error) { logrus.Debugf("Copying source image %s to destination image %s", source.StringWithinTransport(), destination.StringWithinTransport()) // Avoid running out of time when running inside a systemd unit by diff --git a/vendor/github.com/containers/common/libimage/import.go b/vendor/github.com/containers/common/libimage/import.go index 552c48eae00..a03f288533c 100644 --- a/vendor/github.com/containers/common/libimage/import.go +++ b/vendor/github.com/containers/common/libimage/import.go @@ -108,9 +108,9 @@ func (r *Runtime) Import(ctx context.Context, path string, options *ImportOption if err != nil { return "", err } - defer c.close() + defer c.Close() - if _, err := c.copy(ctx, srcRef, destRef); err != nil { + if _, err := c.Copy(ctx, srcRef, destRef); err != nil { return "", err } diff --git a/vendor/github.com/containers/common/libimage/manifest_list.go b/vendor/github.com/containers/common/libimage/manifest_list.go index 1db0cf4dfd5..a23315da3ca 100644 --- a/vendor/github.com/containers/common/libimage/manifest_list.go +++ b/vendor/github.com/containers/common/libimage/manifest_list.go @@ -7,20 +7,28 @@ import ( "errors" "fmt" "maps" + "os" + "path/filepath" "slices" "time" "github.com/containers/common/libimage/define" "github.com/containers/common/libimage/manifests" + manifesterrors "github.com/containers/common/pkg/manifests" + "github.com/containers/common/pkg/supplemented" imageCopy "github.com/containers/image/v5/copy" "github.com/containers/image/v5/docker" "github.com/containers/image/v5/manifest" + "github.com/containers/image/v5/oci/layout" + "github.com/containers/image/v5/signature" "github.com/containers/image/v5/transports/alltransports" "github.com/containers/image/v5/types" "github.com/containers/storage" structcopier "github.com/jinzhu/copier" "github.com/opencontainers/go-digest" + imgspec "github.com/opencontainers/image-spec/specs-go" imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/sirupsen/logrus" ) // NOTE: the abstractions and APIs here are a first step to further merge @@ -101,8 +109,157 @@ func (r *Runtime) lookupManifestList(name string) (*Image, manifests.List, error return image, list, nil } +// ConvertToManifestList converts the image into a manifest list if it is not +// already also a list. An error is returned if the conversion fails. +func (i *Image) ConvertToManifestList(ctx context.Context) (*ManifestList, error) { + // If we don't need to do anything, don't do anything. + if list, err := i.ToManifestList(); err == nil || !errors.Is(err, ErrNotAManifestList) { + return list, err + } + + // Determine which type we prefer for the new manifest list or image index. + _, imageManifestType, err := i.Manifest(ctx) + if err != nil { + return nil, fmt.Errorf("reading the image's manifest: %w", err) + } + var preferredListType string + switch imageManifestType { + case manifest.DockerV2Schema2MediaType, + manifest.DockerV2Schema1SignedMediaType, + manifest.DockerV2Schema1MediaType, + manifest.DockerV2ListMediaType: + preferredListType = manifest.DockerV2ListMediaType + case imgspecv1.MediaTypeImageManifest, imgspecv1.MediaTypeImageIndex: + preferredListType = imgspecv1.MediaTypeImageIndex + default: + preferredListType = "" + } + + // Create a list and add the image's manifest to it. Use OCI format + // for now. If we need to convert it to Docker format, we'll do that + // while copying it. + list := manifests.Create() + if _, err := list.Add(ctx, &i.runtime.systemContext, i.storageReference, false); err != nil { + return nil, fmt.Errorf("generating new image index: %w", err) + } + listBytes, err := list.Serialize(imgspecv1.MediaTypeImageIndex) + if err != nil { + return nil, fmt.Errorf("serializing image index: %w", err) + } + listDigest, err := manifest.Digest(listBytes) + if err != nil { + return nil, fmt.Errorf("digesting image index: %w", err) + } + + // Build an OCI layout containing the image index as the only item. + tmp, err := os.MkdirTemp("", "") + if err != nil { + return nil, fmt.Errorf("serializing initial list: %w", err) + } + defer os.RemoveAll(tmp) + + // Drop our image index in there. + if err := os.Mkdir(filepath.Join(tmp, imgspecv1.ImageBlobsDir), 0o755); err != nil { + return nil, fmt.Errorf("creating directory for blobs: %w", err) + } + if err := os.Mkdir(filepath.Join(tmp, imgspecv1.ImageBlobsDir, listDigest.Algorithm().String()), 0o755); err != nil { + return nil, fmt.Errorf("creating directory for %s blobs: %w", listDigest.Algorithm().String(), err) + } + listFile := filepath.Join(tmp, imgspecv1.ImageBlobsDir, listDigest.Algorithm().String(), listDigest.Encoded()) + if err := os.WriteFile(listFile, listBytes, 0o644); err != nil { + return nil, fmt.Errorf("writing image index for OCI layout: %w", err) + } + + // Build the index for the layout. + index := imgspecv1.Index{ + Versioned: imgspec.Versioned{ + SchemaVersion: 2, + }, + MediaType: imgspecv1.MediaTypeImageIndex, + Manifests: []imgspecv1.Descriptor{{ + MediaType: imgspecv1.MediaTypeImageIndex, + Digest: listDigest, + Size: int64(len(listBytes)), + }}, + } + indexBytes, err := json.Marshal(&index) + if err != nil { + return nil, fmt.Errorf("encoding image index for OCI layout: %w", err) + } + + // Write the index for the layout. + indexFile := filepath.Join(tmp, imgspecv1.ImageIndexFile) + if err := os.WriteFile(indexFile, indexBytes, 0o644); err != nil { + return nil, fmt.Errorf("writing top-level index for OCI layout: %w", err) + } + + // Write the "why yes, this is an OCI layout" file. + layoutFile := filepath.Join(tmp, imgspecv1.ImageLayoutFile) + layoutBytes, err := json.Marshal(imgspecv1.ImageLayout{Version: imgspecv1.ImageLayoutVersion}) + if err != nil { + return nil, fmt.Errorf("encoding image layout structure for OCI layout: %w", err) + } + if err := os.WriteFile(layoutFile, layoutBytes, 0o644); err != nil { + return nil, fmt.Errorf("writing oci-layout file: %w", err) + } + + // Build an OCI layout reference to use as a source. + tmpRef, err := layout.NewReference(tmp, "") + if err != nil { + return nil, fmt.Errorf("creating reference to directory: %w", err) + } + bundle := supplemented.Reference(tmpRef, []types.ImageReference{i.storageReference}, imageCopy.CopySystemImage, nil) + + // Build a policy that ensures we don't prevent ourselves from reading + // this reference. + signaturePolicy, err := signature.DefaultPolicy(&i.runtime.systemContext) + if err != nil { + return nil, fmt.Errorf("obtaining default signature policy: %w", err) + } + acceptAnything := signature.PolicyTransportScopes{ + "": []signature.PolicyRequirement{signature.NewPRInsecureAcceptAnything()}, + } + signaturePolicy.Transports[i.storageReference.Transport().Name()] = acceptAnything + signaturePolicy.Transports[tmpRef.Transport().Name()] = acceptAnything + policyContext, err := signature.NewPolicyContext(signaturePolicy) + if err != nil { + return nil, fmt.Errorf("creating new signature policy context: %w", err) + } + defer func() { + if err2 := policyContext.Destroy(); err2 != nil { + logrus.Errorf("Destroying signature policy context: %v", err2) + } + }() + + // Copy from the OCI layout into the same image record, so that it gets + // both its own manifest and the image index. + copyOptions := imageCopy.Options{ + ForceManifestMIMEType: imageManifestType, + } + if _, err := imageCopy.Image(ctx, policyContext, i.storageReference, bundle, ©Options); err != nil { + return nil, fmt.Errorf("writing updates to image: %w", err) + } + + // Now explicitly write the list's manifest to the image as its "main" + // manifest. + if _, err := list.SaveToImage(i.runtime.store, i.ID(), i.storageImage.Names, preferredListType); err != nil { + return nil, fmt.Errorf("saving image index: %w", err) + } + + // Reload the record. + if err = i.reload(); err != nil { + return nil, fmt.Errorf("reloading image record: %w", err) + } + mList, err := i.runtime.LookupManifestList(i.storageImage.ID) + if err != nil { + return nil, fmt.Errorf("looking up new manifest list: %w", err) + } + + return mList, nil +} + // ToManifestList converts the image into a manifest list. An error is thrown -// if the image is no manifest list. +// if the image is not a manifest list. func (i *Image) ToManifestList() (*ManifestList, error) { list, err := i.getManifestList() if err != nil { @@ -194,6 +351,9 @@ func (m *ManifestList) reload() error { // getManifestList is a helper to obtain a manifest list func (i *Image) getManifestList() (manifests.List, error) { _, list, err := manifests.LoadFromImage(i.runtime.store, i.ID()) + if errors.Is(err, manifesterrors.ErrManifestTypeNotSupported) { + err = fmt.Errorf("%s: %w", err.Error(), ErrNotAManifestList) + } return list, err } @@ -636,7 +796,7 @@ func (m *ManifestList) Push(ctx context.Context, destination string, options *Ma if err != nil { return "", err } - defer copier.close() + defer copier.Close() pushOptions := manifests.PushOptions{ AddCompression: options.AddCompression, diff --git a/vendor/github.com/containers/common/libimage/manifests/manifests.go b/vendor/github.com/containers/common/libimage/manifests/manifests.go index a1625bb1bf3..50c32569ac2 100644 --- a/vendor/github.com/containers/common/libimage/manifests/manifests.go +++ b/vendor/github.com/containers/common/libimage/manifests/manifests.go @@ -342,8 +342,7 @@ func (l *list) Reference(store storage.Store, multiple cp.ImageListSelection, in } } // write the index that refers to this one artifact image - tag := "latest" - indexFile := filepath.Join(tmp, "index.json") + indexFile := filepath.Join(tmp, v1.ImageIndexFile) index := v1.Index{ Versioned: imgspec.Versioned{ SchemaVersion: 2, @@ -353,9 +352,6 @@ func (l *list) Reference(store storage.Store, multiple cp.ImageListSelection, in MediaType: v1.MediaTypeImageManifest, Digest: artifactManifestDigest, Size: int64(len(contents)), - Annotations: map[string]string{ - v1.AnnotationRefName: tag, - }, }}, } indexBytes, err := json.Marshal(&index) @@ -366,12 +362,16 @@ func (l *list) Reference(store storage.Store, multiple cp.ImageListSelection, in return nil, fmt.Errorf("writing image index for OCI layout: %w", err) } // write the layout file - layoutFile := filepath.Join(tmp, "oci-layout") - if err := os.WriteFile(layoutFile, []byte(`{"imageLayoutVersion": "1.0.0"}`), 0o644); err != nil { + layoutFile := filepath.Join(tmp, v1.ImageLayoutFile) + layoutBytes, err := json.Marshal(v1.ImageLayout{Version: v1.ImageLayoutVersion}) + if err != nil { + return nil, fmt.Errorf("encoding image layout for OCI layout: %w", err) + } + if err := os.WriteFile(layoutFile, layoutBytes, 0o644); err != nil { return nil, fmt.Errorf("writing oci-layout file: %w", err) } // build the reference to this artifact image's oci layout - ref, err := ocilayout.NewReference(tmp, tag) + ref, err := ocilayout.NewReference(tmp, "") if err != nil { return nil, fmt.Errorf("creating ImageReference for artifact with files %q: %w", symlinkedFiles, err) } @@ -676,14 +676,14 @@ func (l *list) Add(ctx context.Context, sys *types.SystemContext, ref types.Imag // This should provide for all of the ways to construct a manifest outlined in // https://github.com/opencontainers/image-spec/blob/main/manifest.md#guidelines-for-artifact-usage -// * no blobs → set ManifestArtifactType -// * blobs, no configuration → set ManifestArtifactType and possibly LayerMediaType, and provide file names -// * blobs and configuration → set ManifestArtifactType, possibly LayerMediaType, and ConfigDescriptor, and provide file names +// - no blobs → set ManifestArtifactType +// - blobs, no configuration → set ManifestArtifactType and possibly LayerMediaType, and provide file names +// - blobs and configuration → set ManifestArtifactType, possibly LayerMediaType, and ConfigDescriptor, and provide file names // // The older style of describing artifacts: -// * leave ManifestArtifactType blank -// * specify a zero-length application/vnd.oci.image.config.v1+json config blob -// * set LayerMediaType to a custom type +// - leave ManifestArtifactType blank +// - specify a zero-length application/vnd.oci.image.config.v1+json config blob +// - set LayerMediaType to a custom type // // When reading data produced elsewhere, note that newer tooling will produce // manifests with ArtifactType set. If the manifest's ArtifactType is not set, diff --git a/vendor/github.com/containers/common/libimage/pull.go b/vendor/github.com/containers/common/libimage/pull.go index 3db1b2992bb..c4ad5df0c77 100644 --- a/vendor/github.com/containers/common/libimage/pull.go +++ b/vendor/github.com/containers/common/libimage/pull.go @@ -235,7 +235,7 @@ func (r *Runtime) copyFromDefault(ctx context.Context, ref types.ImageReference, if err != nil { return nil, err } - defer c.close() + defer c.Close() // Figure out a name for the storage destination. var storageName, imageName string @@ -321,7 +321,7 @@ func (r *Runtime) copyFromDefault(ctx context.Context, ref types.ImageReference, return nil, fmt.Errorf("parsing %q: %w", storageName, err) } - _, err = c.copy(ctx, ref, destRef) + _, err = c.Copy(ctx, ref, destRef) return []string{imageName}, err } @@ -391,7 +391,7 @@ func (r *Runtime) copyFromDockerArchiveReaderReference(ctx context.Context, read if err != nil { return nil, err } - defer c.close() + defer c.Close() // Get a slice of storage references we can copy. references, destNames, err := r.storageReferencesReferencesFromArchiveReader(ctx, readerRef, reader) @@ -401,7 +401,7 @@ func (r *Runtime) copyFromDockerArchiveReaderReference(ctx context.Context, read // Now copy all of the images. Use readerRef for performance. for _, destRef := range references { - if _, err := c.copy(ctx, readerRef, destRef); err != nil { + if _, err := c.Copy(ctx, readerRef, destRef); err != nil { return nil, err } } @@ -640,7 +640,7 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str if err != nil { return nil, err } - defer c.close() + defer c.Close() var pullErrors []error for _, candidate := range resolved.PullCandidates { @@ -678,7 +678,7 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str } } var manifestBytes []byte - if manifestBytes, err = c.copy(ctx, srcRef, destRef); err != nil { + if manifestBytes, err = c.Copy(ctx, srcRef, destRef); err != nil { logrus.Debugf("Error pulling candidate %s: %v", candidateString, err) pullErrors = append(pullErrors, err) continue diff --git a/vendor/github.com/containers/common/libimage/push.go b/vendor/github.com/containers/common/libimage/push.go index f89b8fc0709..5db6cfbcfe7 100644 --- a/vendor/github.com/containers/common/libimage/push.go +++ b/vendor/github.com/containers/common/libimage/push.go @@ -114,7 +114,7 @@ func (r *Runtime) Push(ctx context.Context, source, destination string, options return nil, err } - defer c.close() + defer c.Close() - return c.copy(ctx, srcRef, destRef) + return c.Copy(ctx, srcRef, destRef) } diff --git a/vendor/github.com/containers/common/libimage/save.go b/vendor/github.com/containers/common/libimage/save.go index 62cad3288dd..46529d10f34 100644 --- a/vendor/github.com/containers/common/libimage/save.go +++ b/vendor/github.com/containers/common/libimage/save.go @@ -123,9 +123,9 @@ func (r *Runtime) saveSingleImage(ctx context.Context, name, format, path string if err != nil { return err } - defer c.close() + defer c.Close() - _, err = c.copy(ctx, srcRef, destRef) + _, err = c.Copy(ctx, srcRef, destRef) return err } @@ -208,7 +208,7 @@ func (r *Runtime) saveDockerArchive(ctx context.Context, names []string, path st if err != nil { return err } - defer c.close() + defer c.Close() destRef, err := writer.NewReference(nil) if err != nil { @@ -220,7 +220,7 @@ func (r *Runtime) saveDockerArchive(ctx context.Context, names []string, path st return err } - if _, err := c.copy(ctx, srcRef, destRef); err != nil { + if _, err := c.Copy(ctx, srcRef, destRef); err != nil { return err } } diff --git a/vendor/github.com/containers/common/pkg/capabilities/capabilities.go b/vendor/github.com/containers/common/pkg/capabilities/capabilities.go index 43fd2c1b58a..371fbba9a1b 100644 --- a/vendor/github.com/containers/common/pkg/capabilities/capabilities.go +++ b/vendor/github.com/containers/common/pkg/capabilities/capabilities.go @@ -9,20 +9,13 @@ import ( "errors" "fmt" "slices" - "sort" "strings" "sync" - "github.com/syndtr/gocapability/capability" + "github.com/moby/sys/capability" ) var ( - // Used internally and populated during init(). - capabilityList []string - - // Used internally and populated during init(). - capsList []capability.Cap - // ErrUnknownCapability is thrown when an unknown capability is processed. ErrUnknownCapability = errors.New("unknown capability") @@ -35,67 +28,67 @@ var ( // Useful on the CLI for `--cap-add=all` etc. const All = "ALL" -func getCapName(c capability.Cap) string { +func capName(c capability.Cap) string { return "CAP_" + strings.ToUpper(c.String()) } -func init() { - last := capability.CAP_LAST_CAP - // hack for RHEL6 which has no /proc/sys/kernel/cap_last_cap - if last == capability.Cap(63) { - last = capability.CAP_BLOCK_SUSPEND +// capStrList returns all capabilities supported by the currently running kernel, +// or an error if the list can not be obtained. +var capStrList = sync.OnceValues(func() ([]string, error) { + list, err := capability.ListSupported() + if err != nil { + return nil, err } - for _, cap := range capability.List() { - if cap > last { - continue - } - capsList = append(capsList, cap) - capabilityList = append(capabilityList, getCapName(cap)) - sort.Strings(capabilityList) + caps := make([]string, len(list)) + for i, c := range list { + caps[i] = capName(c) } -} - -var ( - boundingSetOnce sync.Once - boundingSetRet []string - boundingSetErr error -) + slices.Sort(caps) + return caps, nil +}) -// BoundingSet returns the capabilities in the current bounding set +// BoundingSet returns the capabilities in the current bounding set. func BoundingSet() ([]string, error) { - boundingSetOnce.Do(func() { - currentCaps, err := capability.NewPid2(0) - if err != nil { - boundingSetErr = err - return - } - err = currentCaps.Load() - if err != nil { - boundingSetErr = err - return - } - var r []string - for _, c := range capsList { - if !currentCaps.Get(capability.BOUNDING, c) { - continue - } - r = append(r, getCapName(c)) - } - boundingSetRet = r - sort.Strings(boundingSetRet) - boundingSetErr = err - }) - return boundingSetRet, boundingSetErr + return boundingSet() } -// AllCapabilities returns all known capabilities. +var boundingSet = sync.OnceValues(func() ([]string, error) { + currentCaps, err := capability.NewPid2(0) + if err != nil { + return nil, err + } + err = currentCaps.Load() + if err != nil { + return nil, err + } + list, err := capability.ListSupported() + if err != nil { + return nil, err + } + var r []string + for _, c := range list { + if !currentCaps.Get(capability.BOUNDING, c) { + continue + } + r = append(r, capName(c)) + } + slices.Sort(r) + return r, nil +}) + +// AllCapabilities returns all capabilities supported by the running kernel. func AllCapabilities() []string { - return capabilityList + list, _ := capStrList() + return list } // NormalizeCapabilities normalizes caps by adding a "CAP_" prefix (if not yet // present). func NormalizeCapabilities(caps []string) ([]string, error) { + all, err := capStrList() + if err != nil { + return nil, err + } normalized := make([]string, 0, len(caps)) for _, c := range caps { c = strings.ToUpper(c) @@ -106,19 +99,23 @@ func NormalizeCapabilities(caps []string) ([]string, error) { if !strings.HasPrefix(c, "CAP_") { c = "CAP_" + c } - if !slices.Contains(capabilityList, c) { + if !slices.Contains(all, c) { return nil, fmt.Errorf("%q: %w", c, ErrUnknownCapability) } normalized = append(normalized, c) } - sort.Strings(normalized) + slices.Sort(normalized) return normalized, nil } // ValidateCapabilities validates if caps only contains valid capabilities. func ValidateCapabilities(caps []string) error { + all, err := capStrList() + if err != nil { + return err + } for _, c := range caps { - if !slices.Contains(capabilityList, c) { + if !slices.Contains(all, c) { return fmt.Errorf("%q: %w", c, ErrUnknownCapability) } } @@ -155,7 +152,7 @@ func MergeCapabilities(base, adds, drops []string) ([]string, error) { return nil, errors.New("adding all caps and removing all caps not allowed") } // "Drop" all capabilities; return what's in capAdd instead - sort.Strings(capAdd) + slices.Sort(capAdd) return capAdd, nil } @@ -195,6 +192,6 @@ func MergeCapabilities(base, adds, drops []string) ([]string, error) { } caps = append(caps, cap) } - sort.Strings(caps) + slices.Sort(caps) return caps, nil } diff --git a/vendor/github.com/containers/common/pkg/cgroups/cgroups_linux.go b/vendor/github.com/containers/common/pkg/cgroups/cgroups_linux.go index 717685789b6..d2c610fb154 100644 --- a/vendor/github.com/containers/common/pkg/cgroups/cgroups_linux.go +++ b/vendor/github.com/containers/common/pkg/cgroups/cgroups_linux.go @@ -95,7 +95,8 @@ func init() { func getAvailableControllers(exclude map[string]controllerHandler, cgroup2 bool) ([]controller, error) { if cgroup2 { controllers := []controller{} - controllersFile := cgroupRoot + "/cgroup.controllers" + controllersFile := filepath.Join(cgroupRoot, "cgroup.controllers") + // rootless cgroupv2: check available controllers for current user, systemd or servicescope will inherit if unshare.IsRootless() { userSlice, err := getCgroupPathForCurrentProcess() @@ -104,7 +105,7 @@ func getAvailableControllers(exclude map[string]controllerHandler, cgroup2 bool) } // userSlice already contains '/' so not adding here basePath := cgroupRoot + userSlice - controllersFile = basePath + "/cgroup.controllers" + controllersFile = filepath.Join(basePath, "cgroup.controllers") } controllersFileBytes, err := os.ReadFile(controllersFile) if err != nil { @@ -597,7 +598,7 @@ func createCgroupv2Path(path string) (deferredError error) { if !strings.HasPrefix(path, cgroupRoot+"/") { return fmt.Errorf("invalid cgroup path %s", path) } - content, err := os.ReadFile(cgroupRoot + "/cgroup.controllers") + content, err := os.ReadFile(filepath.Join(cgroupRoot, "cgroup.controllers")) if err != nil { return err } @@ -625,8 +626,43 @@ func createCgroupv2Path(path string) (deferredError error) { // We enable the controllers for all the path components except the last one. It is not allowed to add // PIDs if there are already enabled controllers. if i < len(elements[3:])-1 { - if err := os.WriteFile(filepath.Join(current, "cgroup.subtree_control"), res, 0o755); err != nil { - return err + subtreeControl := filepath.Join(current, "cgroup.subtree_control") + if err := os.WriteFile(subtreeControl, res, 0o755); err != nil { + // The kernel returns ENOENT either if the file itself is missing, or a controller + if errors.Is(err, os.ErrNotExist) { + if err2 := fileutils.Exists(subtreeControl); err2 != nil { + // If the file itself is missing, return the original error. + return err + } + repeatAttempts := 1000 + for repeatAttempts > 0 { + // store the controllers that failed to be enabled, so we can retry them + newCtrs := [][]byte{} + for _, ctr := range ctrs { + // Try to enable each controller individually, at least we can give a better error message if any fails. + if err := os.WriteFile(subtreeControl, []byte(fmt.Sprintf("+%s\n", ctr)), 0o755); err != nil { + // The kernel can return EBUSY when a process was moved to a sub-cgroup + // and the controllers are enabled in its parent cgroup. Retry a few times when + // it happens. + if errors.Is(err, unix.EBUSY) { + newCtrs = append(newCtrs, ctr) + } else { + return fmt.Errorf("enabling controller %s: %w", ctr, err) + } + } + } + if len(newCtrs) == 0 { + err = nil + break + } + ctrs = newCtrs + repeatAttempts-- + time.Sleep(time.Millisecond) + } + if err != nil { + return err + } + } } } } @@ -786,6 +822,12 @@ func UserOwnsCurrentSystemdCgroup() (bool, error) { continue } + // If we are on a cgroup v2 system and there are cgroup v1 controllers + // mounted, ignore them when the current process is at the root cgroup. + if cgroup2 && parts[1] != "" && parts[2] == "/" { + continue + } + var cgroupPath string if cgroup2 { diff --git a/vendor/github.com/containers/common/pkg/config/containers.conf b/vendor/github.com/containers/common/pkg/config/containers.conf index c00efecbb36..7f095493154 100644 --- a/vendor/github.com/containers/common/pkg/config/containers.conf +++ b/vendor/github.com/containers/common/pkg/config/containers.conf @@ -416,6 +416,8 @@ default_sysctls = [ #List of compression algorithms. If set makes sure that requested compression variant #for each platform is added to the manifest list keeping original instance intact in #the same manifest list on every `manifest push`. Supported values are (`gzip`, `zstd` and `zstd:chunked`). +#`zstd:chunked` is incompatible with encrypting images, and will be treated as `zstd` with a warning +#in that case. # #add_compression = ["gzip", "zstd", "zstd:chunked"] @@ -438,6 +440,8 @@ default_sysctls = [ # This field is ignored when pushing images to the docker-daemon and # docker-archive formats. It is also ignored when the manifest format is set # to v2s2. +# `zstd:chunked` is incompatible with encrypting images, and will be treated as `zstd` with a warning +# in that case. # #compression_format = "gzip" diff --git a/vendor/github.com/containers/common/pkg/config/containers.conf-freebsd b/vendor/github.com/containers/common/pkg/config/containers.conf-freebsd index 21753f4f25f..894153ed338 100644 --- a/vendor/github.com/containers/common/pkg/config/containers.conf-freebsd +++ b/vendor/github.com/containers/common/pkg/config/containers.conf-freebsd @@ -326,6 +326,8 @@ default_sysctls = [ # The compression format to use when pushing an image. # Valid options are: `gzip`, `zstd` and `zstd:chunked`. +# `zstd:chunked` is incompatible with encrypting images, and will be treated as `zstd` with a warning +# in that case. # #compression_format = "gzip" diff --git a/vendor/github.com/containers/common/pkg/netns/netns_linux.go b/vendor/github.com/containers/common/pkg/netns/netns_linux.go index db35fd15a11..5461b05f75f 100644 --- a/vendor/github.com/containers/common/pkg/netns/netns_linux.go +++ b/vendor/github.com/containers/common/pkg/netns/netns_linux.go @@ -40,6 +40,8 @@ import ( // threadNsPath is the /proc path to the current netns handle for the current thread const threadNsPath = "/proc/thread-self/ns/net" +var errNoFreeName = errors.New("failed to find free netns path name") + // GetNSRunDir returns the dir of where to create the netNS. When running // rootless, it needs to be at a location writable by user. func GetNSRunDir() (string, error) { @@ -60,14 +62,26 @@ func NewNSAtPath(nsPath string) (ns.NetNS, error) { // NewNS creates a new persistent (bind-mounted) network namespace and returns // an object representing that namespace, without switching to it. func NewNS() (ns.NetNS, error) { + nsRunDir, err := GetNSRunDir() + if err != nil { + return nil, err + } + + // Create the directory for mounting network namespaces + // This needs to be a shared mountpoint in case it is mounted in to + // other namespaces (containers) + err = makeNetnsDir(nsRunDir) + if err != nil { + return nil, err + } + for range 10000 { - b := make([]byte, 16) - _, err := rand.Reader.Read(b) + nsName, err := getRandomNetnsName() if err != nil { - return nil, fmt.Errorf("failed to generate random netns name: %v", err) + return nil, err } - nsName := fmt.Sprintf("netns-%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:]) - ns, err := NewNSWithName(nsName) + nsPath := path.Join(nsRunDir, nsName) + ns, err := newNSPath(nsPath) if err == nil { return ns, nil } @@ -77,62 +91,128 @@ func NewNS() (ns.NetNS, error) { } return nil, err } - return nil, errors.New("failed to find free netns path name") + return nil, errNoFreeName } -// NewNSWithName creates a new persistent (bind-mounted) network namespace and returns -// an object representing that namespace, without switching to it. -func NewNSWithName(name string) (ns.NetNS, error) { +// NewNSFrom creates a persistent (bind-mounted) network namespace from the +// given netns path, i.e. /proc//ns/net, and returns the new full path to +// the bind mounted file in the netns run dir. +func NewNSFrom(fromNetns string) (string, error) { nsRunDir, err := GetNSRunDir() if err != nil { - return nil, err + return "", err } - // Create the directory for mounting network namespaces - // This needs to be a shared mountpoint in case it is mounted in to - // other namespaces (containers) - err = os.MkdirAll(nsRunDir, 0o755) + err = makeNetnsDir(nsRunDir) if err != nil { - return nil, err + return "", err } - // Remount the namespace directory shared. This will fail if it is not - // already a mountpoint, so bind-mount it on to itself to "upgrade" it - // to a mountpoint. - err = unix.Mount("", nsRunDir, "none", unix.MS_SHARED|unix.MS_REC, "") - if err != nil { - if err != unix.EINVAL { - return nil, fmt.Errorf("mount --make-rshared %s failed: %q", nsRunDir, err) + for range 10000 { + nsName, err := getRandomNetnsName() + if err != nil { + return "", err } + nsPath := filepath.Join(nsRunDir, nsName) - // Recursively remount /run/netns on itself. The recursive flag is - // so that any existing netns bindmounts are carried over. - err = unix.Mount(nsRunDir, nsRunDir, "none", unix.MS_BIND|unix.MS_REC, "") + // create an empty file to use as at the mount point + err = createNetnsFile(nsPath) if err != nil { - return nil, fmt.Errorf("mount --rbind %s %s failed: %q", nsRunDir, nsRunDir, err) + // retry when the name already exists + if errors.Is(err, os.ErrExist) { + continue + } + return "", err } - // Now we can make it shared - err = unix.Mount("", nsRunDir, "none", unix.MS_SHARED|unix.MS_REC, "") + err = unix.Mount(fromNetns, nsPath, "none", unix.MS_BIND|unix.MS_SHARED|unix.MS_REC, "") if err != nil { - return nil, fmt.Errorf("mount --make-rshared %s failed: %q", nsRunDir, err) + // Do not leak the ns on errors + _ = os.RemoveAll(nsPath) + return "", fmt.Errorf("failed to bind mount ns at %s: %v", nsPath, err) } + return nsPath, nil } - nsPath := path.Join(nsRunDir, name) - return newNSPath(nsPath) + return "", errNoFreeName } -func newNSPath(nsPath string) (ns.NetNS, error) { - // create an empty file at the mount point - mountPointFd, err := os.OpenFile(nsPath, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0o600) +func getRandomNetnsName() (string, error) { + b := make([]byte, 16) + _, err := rand.Reader.Read(b) if err != nil { - return nil, err + return "", fmt.Errorf("failed to generate random netns name: %v", err) } - if err := mountPointFd.Close(); err != nil { - return nil, err + return fmt.Sprintf("netns-%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:]), nil +} + +func makeNetnsDir(nsRunDir string) error { + err := os.MkdirAll(nsRunDir, 0o755) + if err != nil { + return err + } + // Important, the bind mount setup is racy if two process try to set it up in parallel. + // This can have very bad consequences because we end up with two duplicated mounts + // for the netns file that then might have a different parent mounts. + // Also because as root netns dir is also created by ip netns we should not race against them. + // Use a lock on the netns dir like they do, compare the iproute2 ip netns add code. + // https://github.com/iproute2/iproute2/blob/8b9d9ea42759c91d950356ca43930a975d0c352b/ip/ipnetns.c#L806-L815 + + dirFD, err := unix.Open(nsRunDir, unix.O_RDONLY|unix.O_DIRECTORY|unix.O_CLOEXEC, 0) + if err != nil { + return &os.PathError{Op: "open", Path: nsRunDir, Err: err} + } + // closing the fd will also unlock so we do not have to call flock(fd,LOCK_UN) + defer unix.Close(dirFD) + + err = unix.Flock(dirFD, unix.LOCK_EX) + if err != nil { + return fmt.Errorf("failed to lock %s dir: %w", nsRunDir, err) + } + + // Remount the namespace directory shared. This will fail with EINVAL + // if it is not already a mountpoint, so bind-mount it on to itself + // to "upgrade" it to a mountpoint. + err = unix.Mount("", nsRunDir, "none", unix.MS_SHARED|unix.MS_REC, "") + if err == nil { + return nil + } + if err != unix.EINVAL { + return fmt.Errorf("mount --make-rshared %s failed: %q", nsRunDir, err) + } + + // Recursively remount /run/netns on itself. The recursive flag is + // so that any existing netns bindmounts are carried over. + err = unix.Mount(nsRunDir, nsRunDir, "none", unix.MS_BIND|unix.MS_REC, "") + if err != nil { + return fmt.Errorf("mount --rbind %s %s failed: %q", nsRunDir, nsRunDir, err) } + // Now we can make it shared + err = unix.Mount("", nsRunDir, "none", unix.MS_SHARED|unix.MS_REC, "") + if err != nil { + return fmt.Errorf("mount --make-rshared %s failed: %q", nsRunDir, err) + } + + return nil +} + +// createNetnsFile created the file with O_EXCL to ensure there are no conflicts with others +// Callers should check for ErrExist and loop over it to find a free file. +func createNetnsFile(path string) error { + mountPointFd, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0o600) + if err != nil { + return err + } + return mountPointFd.Close() +} + +func newNSPath(nsPath string) (ns.NetNS, error) { + // create an empty file to use as at the mount point + err := createNetnsFile(nsPath) + if err != nil { + return nil, err + } // Ensure the mount point is cleaned up on errors; if the namespace // was successfully mounted this will have no effect because the file // is in-use diff --git a/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go b/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go index ded66365bb4..a6538ffb908 100644 --- a/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go +++ b/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go @@ -11,6 +11,7 @@ import ( "github.com/containers/common/pkg/umask" "github.com/containers/storage/pkg/fileutils" "github.com/containers/storage/pkg/idtools" + securejoin "github.com/cyphar/filepath-securejoin" rspec "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/selinux/go-selinux/label" "github.com/sirupsen/logrus" @@ -346,7 +347,10 @@ func addFIPSModeSubscription(mounts *[]rspec.Mount, containerRunDir, mountPoint, srcBackendDir := "/usr/share/crypto-policies/back-ends/FIPS" destDir := "/etc/crypto-policies/back-ends" - srcOnHost := filepath.Join(mountPoint, srcBackendDir) + srcOnHost, err := securejoin.SecureJoin(mountPoint, srcBackendDir) + if err != nil { + return fmt.Errorf("resolve %s in the container: %w", srcBackendDir, err) + } if err := fileutils.Exists(srcOnHost); err != nil { if errors.Is(err, os.ErrNotExist) { return nil diff --git a/vendor/github.com/docker/docker/api/swagger.yaml b/vendor/github.com/docker/docker/api/swagger.yaml index 69ad8a37df6..7164e1eba53 100644 --- a/vendor/github.com/docker/docker/api/swagger.yaml +++ b/vendor/github.com/docker/docker/api/swagger.yaml @@ -393,7 +393,7 @@ definitions: Make the mount non-recursively read-only, but still leave the mount recursive (unless NonRecursive is set to `true` in conjunction). - Addded in v1.44, before that version all read-only mounts were + Added in v1.44, before that version all read-only mounts were non-recursive by default. To match the previous behaviour this will default to `true` for clients on versions prior to v1.44. type: "boolean" @@ -1384,7 +1384,7 @@ definitions:


> **Deprecated**: this field is not part of the image specification and is - > always empty. It must not be used, and will be removed in API v1.47. + > always empty. It must not be used, and will be removed in API v1.48. type: "string" example: "" Domainname: @@ -1394,7 +1394,7 @@ definitions:


> **Deprecated**: this field is not part of the image specification and is - > always empty. It must not be used, and will be removed in API v1.47. + > always empty. It must not be used, and will be removed in API v1.48. type: "string" example: "" User: @@ -1408,7 +1408,7 @@ definitions:


> **Deprecated**: this field is not part of the image specification and is - > always false. It must not be used, and will be removed in API v1.47. + > always false. It must not be used, and will be removed in API v1.48. type: "boolean" default: false example: false @@ -1419,7 +1419,7 @@ definitions:


> **Deprecated**: this field is not part of the image specification and is - > always false. It must not be used, and will be removed in API v1.47. + > always false. It must not be used, and will be removed in API v1.48. type: "boolean" default: false example: false @@ -1430,7 +1430,7 @@ definitions:


> **Deprecated**: this field is not part of the image specification and is - > always false. It must not be used, and will be removed in API v1.47. + > always false. It must not be used, and will be removed in API v1.48. type: "boolean" default: false example: false @@ -1457,7 +1457,7 @@ definitions:


> **Deprecated**: this field is not part of the image specification and is - > always false. It must not be used, and will be removed in API v1.47. + > always false. It must not be used, and will be removed in API v1.48. type: "boolean" default: false example: false @@ -1468,7 +1468,7 @@ definitions:


> **Deprecated**: this field is not part of the image specification and is - > always false. It must not be used, and will be removed in API v1.47. + > always false. It must not be used, and will be removed in API v1.48. type: "boolean" default: false example: false @@ -1479,7 +1479,7 @@ definitions:


> **Deprecated**: this field is not part of the image specification and is - > always false. It must not be used, and will be removed in API v1.47. + > always false. It must not be used, and will be removed in API v1.48. type: "boolean" default: false example: false @@ -1516,7 +1516,7 @@ definitions:


> **Deprecated**: this field is not part of the image specification and is - > always empty. It must not be used, and will be removed in API v1.47. + > always empty. It must not be used, and will be removed in API v1.48. type: "string" default: "" example: "" @@ -1555,7 +1555,7 @@ definitions:


> **Deprecated**: this field is not part of the image specification and is - > always omitted. It must not be used, and will be removed in API v1.47. + > always omitted. It must not be used, and will be removed in API v1.48. type: "boolean" default: false example: false @@ -1567,7 +1567,7 @@ definitions:


> **Deprecated**: this field is not part of the image specification and is - > always omitted. It must not be used, and will be removed in API v1.47. + > always omitted. It must not be used, and will be removed in API v1.48. type: "string" default: "" example: "" @@ -1601,7 +1601,7 @@ definitions:


> **Deprecated**: this field is not part of the image specification and is - > always omitted. It must not be used, and will be removed in API v1.47. + > always omitted. It must not be used, and will be removed in API v1.48. type: "integer" default: 10 x-nullable: true @@ -2216,7 +2216,7 @@ definitions: Created: description: | Date and time at which the image was created as a Unix timestamp - (number of seconds sinds EPOCH). + (number of seconds since EPOCH). type: "integer" x-nullable: false example: "1644009612" @@ -2513,7 +2513,7 @@ definitions: example: false Attachable: description: | - Wheter a global / swarm scope network is manually attachable by regular + Whether a global / swarm scope network is manually attachable by regular containers from workers in swarm mode. type: "boolean" default: false @@ -3736,7 +3736,7 @@ definitions: example: "json-file" Options: description: | - Driver-specific options for the selectd log driver, specified + Driver-specific options for the selected log driver, specified as key/value pairs. type: "object" additionalProperties: @@ -7712,7 +7712,7 @@ paths: * Memory usage % = `(used_memory / available_memory) * 100.0` * cpu_delta = `cpu_stats.cpu_usage.total_usage - precpu_stats.cpu_usage.total_usage` * system_cpu_delta = `cpu_stats.system_cpu_usage - precpu_stats.system_cpu_usage` - * number_cpus = `lenght(cpu_stats.cpu_usage.percpu_usage)` or `cpu_stats.online_cpus` + * number_cpus = `length(cpu_stats.cpu_usage.percpu_usage)` or `cpu_stats.online_cpus` * CPU usage % = `(cpu_delta / system_cpu_delta) * number_cpus * 100.0` operationId: "ContainerStats" produces: ["application/json"] @@ -9226,12 +9226,23 @@ paths: parameters: - name: "name" in: "path" - description: "Image name or ID." + description: | + Name of the image to push. For example, `registry.example.com/myimage`. + The image must be present in the local image store with the same name. + + The name should be provided without tag; if a tag is provided, it + is ignored. For example, `registry.example.com/myimage:latest` is + considered equivalent to `registry.example.com/myimage`. + + Use the `tag` parameter to specify the tag to push. type: "string" required: true - name: "tag" in: "query" - description: "The tag to associate with the image on the registry." + description: | + Tag of the image to push. For example, `latest`. If no tag is provided, + all tags of the given image that are present in the local image store + are pushed. type: "string" - name: "X-Registry-Auth" in: "header" diff --git a/vendor/github.com/docker/docker/api/types/filters/parse.go b/vendor/github.com/docker/docker/api/types/filters/parse.go index 0c39ab5f18b..0914b2a4410 100644 --- a/vendor/github.com/docker/docker/api/types/filters/parse.go +++ b/vendor/github.com/docker/docker/api/types/filters/parse.go @@ -196,7 +196,7 @@ func (args Args) Match(field, source string) bool { } // GetBoolOrDefault returns a boolean value of the key if the key is present -// and is intepretable as a boolean value. Otherwise the default value is returned. +// and is interpretable as a boolean value. Otherwise the default value is returned. // Error is not nil only if the filter values are not valid boolean or are conflicting. func (args Args) GetBoolOrDefault(key string, defaultValue bool) (bool, error) { fieldValues, ok := args.fields[key] diff --git a/vendor/github.com/docker/docker/api/types/image/summary.go b/vendor/github.com/docker/docker/api/types/image/summary.go index c7168fe62ea..e87e216a28b 100644 --- a/vendor/github.com/docker/docker/api/types/image/summary.go +++ b/vendor/github.com/docker/docker/api/types/image/summary.go @@ -12,7 +12,7 @@ type Summary struct { Containers int64 `json:"Containers"` // Date and time at which the image was created as a Unix timestamp - // (number of seconds sinds EPOCH). + // (number of seconds since EPOCH). // // Required: true Created int64 `json:"Created"` diff --git a/vendor/github.com/docker/docker/api/types/swarm/swarm.go b/vendor/github.com/docker/docker/api/types/swarm/swarm.go index 3eae4b9b297..1b4be6fffba 100644 --- a/vendor/github.com/docker/docker/api/types/swarm/swarm.go +++ b/vendor/github.com/docker/docker/api/types/swarm/swarm.go @@ -122,7 +122,7 @@ type CAConfig struct { SigningCAKey string `json:",omitempty"` // If this value changes, and there is no specified signing cert and key, - // then the swarm is forced to generate a new root certificate ane key. + // then the swarm is forced to generate a new root certificate and key. ForceRotate uint64 `json:",omitempty"` } diff --git a/vendor/github.com/docker/docker/api/types/volume/cluster_volume.go b/vendor/github.com/docker/docker/api/types/volume/cluster_volume.go index bbd9ff0b8f9..618a4816209 100644 --- a/vendor/github.com/docker/docker/api/types/volume/cluster_volume.go +++ b/vendor/github.com/docker/docker/api/types/volume/cluster_volume.go @@ -414,7 +414,7 @@ type Info struct { // the Volume has not been successfully created yet. VolumeID string `json:",omitempty"` - // AccessibleTopolgoy is the topology this volume is actually accessible + // AccessibleTopology is the topology this volume is actually accessible // from. AccessibleTopology []Topology `json:",omitempty"` } diff --git a/vendor/github.com/docker/docker/pkg/jsonmessage/jsonmessage.go b/vendor/github.com/docker/docker/pkg/jsonmessage/jsonmessage.go index 035160c834e..8d2c8857fb0 100644 --- a/vendor/github.com/docker/docker/pkg/jsonmessage/jsonmessage.go +++ b/vendor/github.com/docker/docker/pkg/jsonmessage/jsonmessage.go @@ -290,7 +290,7 @@ func DisplayJSONMessagesStream(in io.Reader, out io.Writer, terminalFd uintptr, } // Stream is an io.Writer for output with utilities to get the output's file -// descriptor and to detect wether it's a terminal. +// descriptor and to detect whether it's a terminal. // // it is subset of the streams.Out type in // https://pkg.go.dev/github.com/docker/cli@v20.10.17+incompatible/cli/streams#Out diff --git a/vendor/github.com/docker/docker/pkg/pools/pools.go b/vendor/github.com/docker/docker/pkg/pools/pools.go index 3792c67a9e4..3ea3012b188 100644 --- a/vendor/github.com/docker/docker/pkg/pools/pools.go +++ b/vendor/github.com/docker/docker/pkg/pools/pools.go @@ -124,7 +124,7 @@ func (bufPool *BufioWriterPool) Put(b *bufio.Writer) { } // NewWriteCloserWrapper returns a wrapper which puts the bufio.Writer back -// into the pool and closes the writer if it's an io.Writecloser. +// into the pool and closes the writer if it's an io.WriteCloser. func (bufPool *BufioWriterPool) NewWriteCloserWrapper(buf *bufio.Writer, w io.Writer) io.WriteCloser { return ioutils.NewWriteCloserWrapper(w, func() error { buf.Flush() diff --git a/vendor/github.com/docker/docker/pkg/system/xattrs_linux.go b/vendor/github.com/docker/docker/pkg/system/xattrs_linux.go index facfbb3126f..b877ecc5a94 100644 --- a/vendor/github.com/docker/docker/pkg/system/xattrs_linux.go +++ b/vendor/github.com/docker/docker/pkg/system/xattrs_linux.go @@ -6,7 +6,7 @@ import ( // Lgetxattr retrieves the value of the extended attribute identified by attr // and associated with the given path in the file system. -// It will returns a nil slice and nil error if the xattr is not set. +// It returns a nil slice and nil error if the xattr is not set. func Lgetxattr(path string, attr string) ([]byte, error) { sysErr := func(err error) ([]byte, error) { return nil, &XattrError{Op: "lgetxattr", Attr: attr, Path: path, Err: err} diff --git a/vendor/github.com/moby/sys/capability/.codespellrc b/vendor/github.com/moby/sys/capability/.codespellrc new file mode 100644 index 00000000000..e874be5634b --- /dev/null +++ b/vendor/github.com/moby/sys/capability/.codespellrc @@ -0,0 +1,3 @@ +[codespell] +skip = ./.git +ignore-words-list = nd diff --git a/vendor/github.com/moby/sys/capability/.golangci.yml b/vendor/github.com/moby/sys/capability/.golangci.yml new file mode 100644 index 00000000000..d775aadd6fa --- /dev/null +++ b/vendor/github.com/moby/sys/capability/.golangci.yml @@ -0,0 +1,6 @@ +linters: + enable: + - unconvert + - unparam + - gofumpt + - errorlint diff --git a/vendor/github.com/moby/sys/capability/CHANGELOG.md b/vendor/github.com/moby/sys/capability/CHANGELOG.md new file mode 100644 index 00000000000..037ef010a67 --- /dev/null +++ b/vendor/github.com/moby/sys/capability/CHANGELOG.md @@ -0,0 +1,90 @@ +# Changelog +This file documents all notable changes made to this project since the initial fork +from https://github.com/syndtr/gocapability/commit/42c35b4376354fd5. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [0.3.0] - 2024-09-25 + +### Added +* Added [ListKnown] and [ListSupported] functions. (#153) +* [LastCap] is now available on non-Linux platforms (where it returns an error). (#152) + +### Changed +* [List] is now deprecated in favor of [ListKnown] and [ListSupported]. (#153) + +### Fixed +* Various documentation improvements. (#151) +* Fix "generated code" comment. (#153) + +## [0.2.0] - 2024-09-16 + +This is the first release after the move to a new home in +github.com/moby/sys/capability. + +### Fixed + * Fixed URLs in documentation to reflect the new home. + +## [0.1.1] - 2024-08-01 + +This is a maintenance release, fixing a few minor issues. + +### Fixed + * Fixed future kernel compatibility, for real this time. [#11] + * Fixed [LastCap] to be a function. [#12] + +## [0.1.0] - 2024-07-31 + +This is an initial release since the fork. + +### Breaking changes + + * The `CAP_LAST_CAP` variable is removed; users need to modify the code to + use [LastCap] to get the value. [#6] + * The code now requires Go >= 1.21. + +### Added + * `go.mod` and `go.sum` files. [#2] + * New [LastCap] function. [#6] + * Basic CI using GHA infra. [#8], [#9] + * README and CHANGELOG. [#10] + +### Fixed + * Fixed ambient capabilities error handling in [Apply]. [#3] + * Fixed future kernel compatibility. [#1] + * Fixed various linter warnings. [#4], [#7] + +### Changed + * Go build tags changed from old-style (`+build`) to new Go 1.17+ style (`go:build`). [#2] + +### Removed + * Removed support for capabilities v1 and v2. [#1] + * Removed init function so programs that use this package start faster. [#6] + * Removed `CAP_LAST_CAP` (use [LastCap] instead). [#6] + + +[Apply]: https://pkg.go.dev/github.com/moby/sys/capability#Capabilities.Apply +[LastCap]: https://pkg.go.dev/github.com/moby/sys/capability#LastCap +[List]: https://pkg.go.dev/github.com/moby/sys/capability#List +[ListKnown]: https://pkg.go.dev/github.com/moby/sys/capability#ListKnown +[ListSupported]: https://pkg.go.dev/github.com/moby/sys/capability#ListSupported + + +[0.3.0]: https://github.com/moby/sys/releases/tag/capability%2Fv0.3.0 +[0.2.0]: https://github.com/moby/sys/releases/tag/capability%2Fv0.2.0 +[0.1.1]: https://github.com/kolyshkin/capability/compare/v0.1.0...v0.1.1 +[0.1.0]: https://github.com/kolyshkin/capability/compare/42c35b4376354fd5...v0.1.0 + + +[#1]: https://github.com/kolyshkin/capability/pull/1 +[#2]: https://github.com/kolyshkin/capability/pull/2 +[#3]: https://github.com/kolyshkin/capability/pull/3 +[#4]: https://github.com/kolyshkin/capability/pull/4 +[#6]: https://github.com/kolyshkin/capability/pull/6 +[#7]: https://github.com/kolyshkin/capability/pull/7 +[#8]: https://github.com/kolyshkin/capability/pull/8 +[#9]: https://github.com/kolyshkin/capability/pull/9 +[#10]: https://github.com/kolyshkin/capability/pull/10 +[#11]: https://github.com/kolyshkin/capability/pull/11 +[#12]: https://github.com/kolyshkin/capability/pull/12 diff --git a/vendor/github.com/moby/sys/capability/LICENSE b/vendor/github.com/moby/sys/capability/LICENSE new file mode 100644 index 00000000000..08adcd6ecfb --- /dev/null +++ b/vendor/github.com/moby/sys/capability/LICENSE @@ -0,0 +1,25 @@ +Copyright 2023 The Capability Authors. +Copyright 2013 Suryandaru Triandana +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/moby/sys/capability/README.md b/vendor/github.com/moby/sys/capability/README.md new file mode 100644 index 00000000000..84b74871aa2 --- /dev/null +++ b/vendor/github.com/moby/sys/capability/README.md @@ -0,0 +1,13 @@ +This is a fork of (apparently no longer maintained) +https://github.com/syndtr/gocapability package. It provides basic primitives to +work with [Linux capabilities][capabilities(7)]. + +For changes, see [CHANGELOG.md](./CHANGELOG.md). + +[![Go Reference](https://pkg.go.dev/badge/github.com/moby/sys/capability/capability.svg)](https://pkg.go.dev/github.com/moby/sys/capability) + +## Alternatives + + * https://pkg.go.dev/kernel.org/pub/linux/libs/security/libcap/cap + +[capabilities(7)]: https://man7.org/linux/man-pages/man7/capabilities.7.html diff --git a/vendor/github.com/moby/sys/capability/capability.go b/vendor/github.com/moby/sys/capability/capability.go new file mode 100644 index 00000000000..1b36f5f22a2 --- /dev/null +++ b/vendor/github.com/moby/sys/capability/capability.go @@ -0,0 +1,144 @@ +// Copyright 2023 The Capability Authors. +// Copyright 2013 Suryandaru Triandana +// All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package capability provides utilities for manipulating POSIX capabilities. +package capability + +type Capabilities interface { + // Get check whether a capability present in the given + // capabilities set. The 'which' value should be one of EFFECTIVE, + // PERMITTED, INHERITABLE, BOUNDING or AMBIENT. + Get(which CapType, what Cap) bool + + // Empty check whether all capability bits of the given capabilities + // set are zero. The 'which' value should be one of EFFECTIVE, + // PERMITTED, INHERITABLE, BOUNDING or AMBIENT. + Empty(which CapType) bool + + // Full check whether all capability bits of the given capabilities + // set are one. The 'which' value should be one of EFFECTIVE, + // PERMITTED, INHERITABLE, BOUNDING or AMBIENT. + Full(which CapType) bool + + // Set sets capabilities of the given capabilities sets. The + // 'which' value should be one or combination (OR'ed) of EFFECTIVE, + // PERMITTED, INHERITABLE, BOUNDING or AMBIENT. + Set(which CapType, caps ...Cap) + + // Unset unsets capabilities of the given capabilities sets. The + // 'which' value should be one or combination (OR'ed) of EFFECTIVE, + // PERMITTED, INHERITABLE, BOUNDING or AMBIENT. + Unset(which CapType, caps ...Cap) + + // Fill sets all bits of the given capabilities kind to one. The + // 'kind' value should be one or combination (OR'ed) of CAPS, + // BOUNDS or AMBS. + Fill(kind CapType) + + // Clear sets all bits of the given capabilities kind to zero. The + // 'kind' value should be one or combination (OR'ed) of CAPS, + // BOUNDS or AMBS. + Clear(kind CapType) + + // String return current capabilities state of the given capabilities + // set as string. The 'which' value should be one of EFFECTIVE, + // PERMITTED, INHERITABLE BOUNDING or AMBIENT + StringCap(which CapType) string + + // String return current capabilities state as string. + String() string + + // Load load actual capabilities value. This will overwrite all + // outstanding changes. + Load() error + + // Apply apply the capabilities settings, so all changes will take + // effect. + Apply(kind CapType) error +} + +// NewPid initializes a new [Capabilities] object for given pid when +// it is nonzero, or for the current process if pid is 0. +// +// Deprecated: Replace with [NewPid2] followed by [Capabilities.Load]. +// For example, replace: +// +// c, err := NewPid(0) +// if err != nil { +// return err +// } +// +// with: +// +// c, err := NewPid2(0) +// if err != nil { +// return err +// } +// err = c.Load() +// if err != nil { +// return err +// } +func NewPid(pid int) (Capabilities, error) { + c, err := newPid(pid) + if err != nil { + return c, err + } + err = c.Load() + return c, err +} + +// NewPid2 initializes a new [Capabilities] object for given pid when +// it is nonzero, or for the current process if pid is 0. This +// does not load the process's current capabilities; to do that you +// must call [Capabilities.Load] explicitly. +func NewPid2(pid int) (Capabilities, error) { + return newPid(pid) +} + +// NewFile initializes a new Capabilities object for given file path. +// +// Deprecated: Replace with [NewFile2] followed by [Capabilities.Load]. +// For example, replace: +// +// c, err := NewFile(path) +// if err != nil { +// return err +// } +// +// with: +// +// c, err := NewFile2(path) +// if err != nil { +// return err +// } +// err = c.Load() +// if err != nil { +// return err +// } +func NewFile(path string) (Capabilities, error) { + c, err := newFile(path) + if err != nil { + return c, err + } + err = c.Load() + return c, err +} + +// NewFile2 creates a new initialized [Capabilities] object for given +// file path. This does not load the process's current capabilities; +// to do that you must call [Capabilities.Load] explicitly. +func NewFile2(path string) (Capabilities, error) { + return newFile(path) +} + +// LastCap returns highest valid capability of the running kernel, +// or an error if it can not be obtained. +// +// See also: [ListSupported]. +func LastCap() (Cap, error) { + return lastCap() +} diff --git a/vendor/github.com/moby/sys/capability/capability_linux.go b/vendor/github.com/moby/sys/capability/capability_linux.go new file mode 100644 index 00000000000..aa600e1d9fc --- /dev/null +++ b/vendor/github.com/moby/sys/capability/capability_linux.go @@ -0,0 +1,541 @@ +// Copyright 2023 The Capability Authors. +// Copyright 2013 Suryandaru Triandana +// All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package capability + +import ( + "bufio" + "errors" + "fmt" + "io" + "os" + "strconv" + "strings" + "sync" + "syscall" +) + +const ( + linuxCapVer1 = 0x19980330 // No longer supported. + linuxCapVer2 = 0x20071026 // No longer supported. + linuxCapVer3 = 0x20080522 +) + +var lastCap = sync.OnceValues(func() (Cap, error) { + f, err := os.Open("/proc/sys/kernel/cap_last_cap") + if err != nil { + return 0, err + } + + buf := make([]byte, 11) + l, err := f.Read(buf) + f.Close() + if err != nil { + return 0, err + } + buf = buf[:l] + + last, err := strconv.Atoi(strings.TrimSpace(string(buf))) + if err != nil { + return 0, err + } + return Cap(last), nil +}) + +func capUpperMask() uint32 { + last, err := lastCap() + if err != nil || last < 32 { + return 0 + } + return (uint32(1) << (uint(last) - 31)) - 1 +} + +func mkStringCap(c Capabilities, which CapType) (ret string) { + last, err := lastCap() + if err != nil { + return "" + } + for i, first := Cap(0), true; i <= last; i++ { + if !c.Get(which, i) { + continue + } + if first { + first = false + } else { + ret += ", " + } + ret += i.String() + } + return +} + +func mkString(c Capabilities, max CapType) (ret string) { + ret = "{" + for i := CapType(1); i <= max; i <<= 1 { + ret += " " + i.String() + "=\"" + if c.Empty(i) { + ret += "empty" + } else if c.Full(i) { + ret += "full" + } else { + ret += c.StringCap(i) + } + ret += "\"" + } + ret += " }" + return +} + +var capVersion = sync.OnceValues(func() (uint32, error) { + var hdr capHeader + err := capget(&hdr, nil) + return hdr.version, err +}) + +func newPid(pid int) (c Capabilities, retErr error) { + ver, err := capVersion() + if err != nil { + retErr = fmt.Errorf("unable to get capability version from the kernel: %w", err) + return + } + switch ver { + case linuxCapVer1, linuxCapVer2: + retErr = errors.New("old/unsupported capability version (kernel older than 2.6.26?)") + default: + // Either linuxCapVer3, or an unknown/future version (such as v4). + // In the latter case, we fall back to v3 as the latest version known + // to this package, as kernel should be backward-compatible to v3. + p := new(capsV3) + p.hdr.version = linuxCapVer3 + p.hdr.pid = int32(pid) + c = p + } + return +} + +type capsV3 struct { + hdr capHeader + data [2]capData + bounds [2]uint32 + ambient [2]uint32 +} + +func (c *capsV3) Get(which CapType, what Cap) bool { + var i uint + if what > 31 { + i = uint(what) >> 5 + what %= 32 + } + + switch which { + case EFFECTIVE: + return (1< 31 { + i = uint(what) >> 5 + what %= 32 + } + + if which&EFFECTIVE != 0 { + c.data[i].effective |= 1 << uint(what) + } + if which&PERMITTED != 0 { + c.data[i].permitted |= 1 << uint(what) + } + if which&INHERITABLE != 0 { + c.data[i].inheritable |= 1 << uint(what) + } + if which&BOUNDING != 0 { + c.bounds[i] |= 1 << uint(what) + } + if which&AMBIENT != 0 { + c.ambient[i] |= 1 << uint(what) + } + } +} + +func (c *capsV3) Unset(which CapType, caps ...Cap) { + for _, what := range caps { + var i uint + if what > 31 { + i = uint(what) >> 5 + what %= 32 + } + + if which&EFFECTIVE != 0 { + c.data[i].effective &= ^(1 << uint(what)) + } + if which&PERMITTED != 0 { + c.data[i].permitted &= ^(1 << uint(what)) + } + if which&INHERITABLE != 0 { + c.data[i].inheritable &= ^(1 << uint(what)) + } + if which&BOUNDING != 0 { + c.bounds[i] &= ^(1 << uint(what)) + } + if which&AMBIENT != 0 { + c.ambient[i] &= ^(1 << uint(what)) + } + } +} + +func (c *capsV3) Fill(kind CapType) { + if kind&CAPS == CAPS { + c.data[0].effective = 0xffffffff + c.data[0].permitted = 0xffffffff + c.data[0].inheritable = 0 + c.data[1].effective = 0xffffffff + c.data[1].permitted = 0xffffffff + c.data[1].inheritable = 0 + } + + if kind&BOUNDS == BOUNDS { + c.bounds[0] = 0xffffffff + c.bounds[1] = 0xffffffff + } + if kind&AMBS == AMBS { + c.ambient[0] = 0xffffffff + c.ambient[1] = 0xffffffff + } +} + +func (c *capsV3) Clear(kind CapType) { + if kind&CAPS == CAPS { + c.data[0].effective = 0 + c.data[0].permitted = 0 + c.data[0].inheritable = 0 + c.data[1].effective = 0 + c.data[1].permitted = 0 + c.data[1].inheritable = 0 + } + + if kind&BOUNDS == BOUNDS { + c.bounds[0] = 0 + c.bounds[1] = 0 + } + if kind&AMBS == AMBS { + c.ambient[0] = 0 + c.ambient[1] = 0 + } +} + +func (c *capsV3) StringCap(which CapType) (ret string) { + return mkStringCap(c, which) +} + +func (c *capsV3) String() (ret string) { + return mkString(c, BOUNDING) +} + +func (c *capsV3) Load() (err error) { + err = capget(&c.hdr, &c.data[0]) + if err != nil { + return + } + + path := "/proc/self/status" + if c.hdr.pid != 0 { + path = fmt.Sprintf("/proc/%d/status", c.hdr.pid) + } + + f, err := os.Open(path) + if err != nil { + return + } + b := bufio.NewReader(f) + for { + line, e := b.ReadString('\n') + if e != nil { + if e != io.EOF { + err = e + } + break + } + if strings.HasPrefix(line, "CapB") { + _, err = fmt.Sscanf(line[4:], "nd: %08x%08x", &c.bounds[1], &c.bounds[0]) + if err != nil { + break + } + continue + } + if strings.HasPrefix(line, "CapA") { + _, err = fmt.Sscanf(line[4:], "mb: %08x%08x", &c.ambient[1], &c.ambient[0]) + if err != nil { + break + } + continue + } + } + f.Close() + + return +} + +func (c *capsV3) Apply(kind CapType) (err error) { + last, err := LastCap() + if err != nil { + return err + } + if kind&BOUNDS == BOUNDS { + var data [2]capData + err = capget(&c.hdr, &data[0]) + if err != nil { + return + } + if (1< 31 { + if c.data.version == 1 { + return false + } + i = uint(what) >> 5 + what %= 32 + } + + switch which { + case EFFECTIVE: + return (1< 31 { + if c.data.version == 1 { + continue + } + i = uint(what) >> 5 + what %= 32 + } + + if which&EFFECTIVE != 0 { + c.data.effective[i] |= 1 << uint(what) + } + if which&PERMITTED != 0 { + c.data.data[i].permitted |= 1 << uint(what) + } + if which&INHERITABLE != 0 { + c.data.data[i].inheritable |= 1 << uint(what) + } + } +} + +func (c *capsFile) Unset(which CapType, caps ...Cap) { + for _, what := range caps { + var i uint + if what > 31 { + if c.data.version == 1 { + continue + } + i = uint(what) >> 5 + what %= 32 + } + + if which&EFFECTIVE != 0 { + c.data.effective[i] &= ^(1 << uint(what)) + } + if which&PERMITTED != 0 { + c.data.data[i].permitted &= ^(1 << uint(what)) + } + if which&INHERITABLE != 0 { + c.data.data[i].inheritable &= ^(1 << uint(what)) + } + } +} + +func (c *capsFile) Fill(kind CapType) { + if kind&CAPS == CAPS { + c.data.effective[0] = 0xffffffff + c.data.data[0].permitted = 0xffffffff + c.data.data[0].inheritable = 0 + if c.data.version == 2 { + c.data.effective[1] = 0xffffffff + c.data.data[1].permitted = 0xffffffff + c.data.data[1].inheritable = 0 + } + } +} + +func (c *capsFile) Clear(kind CapType) { + if kind&CAPS == CAPS { + c.data.effective[0] = 0 + c.data.data[0].permitted = 0 + c.data.data[0].inheritable = 0 + if c.data.version == 2 { + c.data.effective[1] = 0 + c.data.data[1].permitted = 0 + c.data.data[1].inheritable = 0 + } + } +} + +func (c *capsFile) StringCap(which CapType) (ret string) { + return mkStringCap(c, which) +} + +func (c *capsFile) String() (ret string) { + return mkString(c, INHERITABLE) +} + +func (c *capsFile) Load() (err error) { + return getVfsCap(c.path, &c.data) +} + +func (c *capsFile) Apply(kind CapType) (err error) { + if kind&CAPS == CAPS { + return setVfsCap(c.path, &c.data) + } + return +} diff --git a/vendor/github.com/moby/sys/capability/capability_noop.go b/vendor/github.com/moby/sys/capability/capability_noop.go new file mode 100644 index 00000000000..ba819ff057e --- /dev/null +++ b/vendor/github.com/moby/sys/capability/capability_noop.go @@ -0,0 +1,26 @@ +// Copyright 2023 The Capability Authors. +// Copyright 2013 Suryandaru Triandana +// All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !linux + +package capability + +import "errors" + +var errNotSup = errors.New("not supported") + +func newPid(_ int) (Capabilities, error) { + return nil, errNotSup +} + +func newFile(_ string) (Capabilities, error) { + return nil, errNotSup +} + +func lastCap() (Cap, error) { + return -1, errNotSup +} diff --git a/vendor/github.com/moby/sys/capability/enum.go b/vendor/github.com/moby/sys/capability/enum.go new file mode 100644 index 00000000000..f89f0273aa4 --- /dev/null +++ b/vendor/github.com/moby/sys/capability/enum.go @@ -0,0 +1,330 @@ +// Copyright 2024 The Capability Authors. +// Copyright 2013 Suryandaru Triandana +// All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package capability + +import "slices" + +type CapType uint + +func (c CapType) String() string { + switch c { + case EFFECTIVE: + return "effective" + case PERMITTED: + return "permitted" + case INHERITABLE: + return "inheritable" + case BOUNDING: + return "bounding" + case CAPS: + return "caps" + case AMBIENT: + return "ambient" + } + return "unknown" +} + +const ( + EFFECTIVE CapType = 1 << iota + PERMITTED + INHERITABLE + BOUNDING + AMBIENT + + CAPS = EFFECTIVE | PERMITTED | INHERITABLE + BOUNDS = BOUNDING + AMBS = AMBIENT +) + +//go:generate go run enumgen/gen.go +type Cap int + +// POSIX-draft defined capabilities and Linux extensions. +// +// Defined in https://github.com/torvalds/linux/blob/master/include/uapi/linux/capability.h +const ( + // In a system with the [_POSIX_CHOWN_RESTRICTED] option defined, this + // overrides the restriction of changing file ownership and group + // ownership. + CAP_CHOWN = Cap(0) + + // Override all DAC access, including ACL execute access if + // [_POSIX_ACL] is defined. Excluding DAC access covered by + // CAP_LINUX_IMMUTABLE. + CAP_DAC_OVERRIDE = Cap(1) + + // Overrides all DAC restrictions regarding read and search on files + // and directories, including ACL restrictions if [_POSIX_ACL] is + // defined. Excluding DAC access covered by CAP_LINUX_IMMUTABLE. + CAP_DAC_READ_SEARCH = Cap(2) + + // Overrides all restrictions about allowed operations on files, where + // file owner ID must be equal to the user ID, except where CAP_FSETID + // is applicable. It doesn't override MAC and DAC restrictions. + CAP_FOWNER = Cap(3) + + // Overrides the following restrictions that the effective user ID + // shall match the file owner ID when setting the S_ISUID and S_ISGID + // bits on that file; that the effective group ID (or one of the + // supplementary group IDs) shall match the file owner ID when setting + // the S_ISGID bit on that file; that the S_ISUID and S_ISGID bits are + // cleared on successful return from chown(2) (not implemented). + CAP_FSETID = Cap(4) + + // Overrides the restriction that the real or effective user ID of a + // process sending a signal must match the real or effective user ID + // of the process receiving the signal. + CAP_KILL = Cap(5) + + // Allows setgid(2) manipulation + // Allows setgroups(2) + // Allows forged gids on socket credentials passing. + CAP_SETGID = Cap(6) + + // Allows set*uid(2) manipulation (including fsuid). + // Allows forged pids on socket credentials passing. + CAP_SETUID = Cap(7) + + // Linux-specific capabilities + + // Without VFS support for capabilities: + // Transfer any capability in your permitted set to any pid, + // remove any capability in your permitted set from any pid + // With VFS support for capabilities (neither of above, but) + // Add any capability from current's capability bounding set + // to the current process' inheritable set + // Allow taking bits out of capability bounding set + // Allow modification of the securebits for a process + CAP_SETPCAP = Cap(8) + + // Allow modification of S_IMMUTABLE and S_APPEND file attributes + CAP_LINUX_IMMUTABLE = Cap(9) + + // Allows binding to TCP/UDP sockets below 1024 + // Allows binding to ATM VCIs below 32 + CAP_NET_BIND_SERVICE = Cap(10) + + // Allow broadcasting, listen to multicast + CAP_NET_BROADCAST = Cap(11) + + // Allow interface configuration + // Allow administration of IP firewall, masquerading and accounting + // Allow setting debug option on sockets + // Allow modification of routing tables + // Allow setting arbitrary process / process group ownership on + // sockets + // Allow binding to any address for transparent proxying (also via NET_RAW) + // Allow setting TOS (type of service) + // Allow setting promiscuous mode + // Allow clearing driver statistics + // Allow multicasting + // Allow read/write of device-specific registers + // Allow activation of ATM control sockets + CAP_NET_ADMIN = Cap(12) + + // Allow use of RAW sockets + // Allow use of PACKET sockets + // Allow binding to any address for transparent proxying (also via NET_ADMIN) + CAP_NET_RAW = Cap(13) + + // Allow locking of shared memory segments + // Allow mlock and mlockall (which doesn't really have anything to do + // with IPC) + CAP_IPC_LOCK = Cap(14) + + // Override IPC ownership checks + CAP_IPC_OWNER = Cap(15) + + // Insert and remove kernel modules - modify kernel without limit + CAP_SYS_MODULE = Cap(16) + + // Allow ioperm/iopl access + // Allow sending USB messages to any device via /proc/bus/usb + CAP_SYS_RAWIO = Cap(17) + + // Allow use of chroot() + CAP_SYS_CHROOT = Cap(18) + + // Allow ptrace() of any process + CAP_SYS_PTRACE = Cap(19) + + // Allow configuration of process accounting + CAP_SYS_PACCT = Cap(20) + + // Allow configuration of the secure attention key + // Allow administration of the random device + // Allow examination and configuration of disk quotas + // Allow setting the domainname + // Allow setting the hostname + // Allow calling bdflush() + // Allow mount() and umount(), setting up new smb connection + // Allow some autofs root ioctls + // Allow nfsservctl + // Allow VM86_REQUEST_IRQ + // Allow to read/write pci config on alpha + // Allow irix_prctl on mips (setstacksize) + // Allow flushing all cache on m68k (sys_cacheflush) + // Allow removing semaphores + // Used instead of CAP_CHOWN to "chown" IPC message queues, semaphores + // and shared memory + // Allow locking/unlocking of shared memory segment + // Allow turning swap on/off + // Allow forged pids on socket credentials passing + // Allow setting readahead and flushing buffers on block devices + // Allow setting geometry in floppy driver + // Allow turning DMA on/off in xd driver + // Allow administration of md devices (mostly the above, but some + // extra ioctls) + // Allow tuning the ide driver + // Allow access to the nvram device + // Allow administration of apm_bios, serial and bttv (TV) device + // Allow manufacturer commands in isdn CAPI support driver + // Allow reading non-standardized portions of pci configuration space + // Allow DDI debug ioctl on sbpcd driver + // Allow setting up serial ports + // Allow sending raw qic-117 commands + // Allow enabling/disabling tagged queuing on SCSI controllers and sending + // arbitrary SCSI commands + // Allow setting encryption key on loopback filesystem + // Allow setting zone reclaim policy + // Allow everything under CAP_BPF and CAP_PERFMON for backward compatibility + CAP_SYS_ADMIN = Cap(21) + + // Allow use of reboot() + CAP_SYS_BOOT = Cap(22) + + // Allow raising priority and setting priority on other (different + // UID) processes + // Allow use of FIFO and round-robin (realtime) scheduling on own + // processes and setting the scheduling algorithm used by another + // process. + // Allow setting cpu affinity on other processes + CAP_SYS_NICE = Cap(23) + + // Override resource limits. Set resource limits. + // Override quota limits. + // Override reserved space on ext2 filesystem + // Modify data journaling mode on ext3 filesystem (uses journaling + // resources) + // NOTE: ext2 honors fsuid when checking for resource overrides, so + // you can override using fsuid too + // Override size restrictions on IPC message queues + // Allow more than 64hz interrupts from the real-time clock + // Override max number of consoles on console allocation + // Override max number of keymaps + // Control memory reclaim behavior + CAP_SYS_RESOURCE = Cap(24) + + // Allow manipulation of system clock + // Allow irix_stime on mips + // Allow setting the real-time clock + CAP_SYS_TIME = Cap(25) + + // Allow configuration of tty devices + // Allow vhangup() of tty + CAP_SYS_TTY_CONFIG = Cap(26) + + // Allow the privileged aspects of mknod() + CAP_MKNOD = Cap(27) + + // Allow taking of leases on files + CAP_LEASE = Cap(28) + + CAP_AUDIT_WRITE = Cap(29) + CAP_AUDIT_CONTROL = Cap(30) + CAP_SETFCAP = Cap(31) + + // Override MAC access. + // The base kernel enforces no MAC policy. + // An LSM may enforce a MAC policy, and if it does and it chooses + // to implement capability based overrides of that policy, this is + // the capability it should use to do so. + CAP_MAC_OVERRIDE = Cap(32) + + // Allow MAC configuration or state changes. + // The base kernel requires no MAC configuration. + // An LSM may enforce a MAC policy, and if it does and it chooses + // to implement capability based checks on modifications to that + // policy or the data required to maintain it, this is the + // capability it should use to do so. + CAP_MAC_ADMIN = Cap(33) + + // Allow configuring the kernel's syslog (printk behaviour) + CAP_SYSLOG = Cap(34) + + // Allow triggering something that will wake the system + CAP_WAKE_ALARM = Cap(35) + + // Allow preventing system suspends + CAP_BLOCK_SUSPEND = Cap(36) + + // Allow reading the audit log via multicast netlink socket + CAP_AUDIT_READ = Cap(37) + + // Allow system performance and observability privileged operations + // using perf_events, i915_perf and other kernel subsystems + CAP_PERFMON = Cap(38) + + // CAP_BPF allows the following BPF operations: + // - Creating all types of BPF maps + // - Advanced verifier features + // - Indirect variable access + // - Bounded loops + // - BPF to BPF function calls + // - Scalar precision tracking + // - Larger complexity limits + // - Dead code elimination + // - And potentially other features + // - Loading BPF Type Format (BTF) data + // - Retrieve xlated and JITed code of BPF programs + // - Use bpf_spin_lock() helper + // + // CAP_PERFMON relaxes the verifier checks further: + // - BPF progs can use of pointer-to-integer conversions + // - speculation attack hardening measures are bypassed + // - bpf_probe_read to read arbitrary kernel memory is allowed + // - bpf_trace_printk to print kernel memory is allowed + // + // CAP_SYS_ADMIN is required to use bpf_probe_write_user. + // + // CAP_SYS_ADMIN is required to iterate system wide loaded + // programs, maps, links, BTFs and convert their IDs to file descriptors. + // + // CAP_PERFMON and CAP_BPF are required to load tracing programs. + // CAP_NET_ADMIN and CAP_BPF are required to load networking programs. + CAP_BPF = Cap(39) + + // Allow checkpoint/restore related operations. + // Introduced in kernel 5.9 + CAP_CHECKPOINT_RESTORE = Cap(40) +) + +// List returns the list of all capabilities known to the package. +// +// Deprecated: use [ListKnown] or [ListSupported] instead. +func List() []Cap { + return ListKnown() +} + +// ListKnown returns the list of all capabilities known to the package. +func ListKnown() []Cap { + return list() +} + +// ListSupported retuns the list of all capabilities known to the package, +// except those that are not supported by the currently running Linux kernel. +func ListSupported() ([]Cap, error) { + last, err := LastCap() + if err != nil { + return nil, err + } + return slices.DeleteFunc(list(), func(c Cap) bool { + // Remove caps not supported by the kernel. + return c > last + }), nil +} diff --git a/vendor/github.com/moby/sys/capability/enum_gen.go b/vendor/github.com/moby/sys/capability/enum_gen.go new file mode 100644 index 00000000000..f72cd43a6e0 --- /dev/null +++ b/vendor/github.com/moby/sys/capability/enum_gen.go @@ -0,0 +1,137 @@ +// Code generated by go generate; DO NOT EDIT. + +package capability + +func (c Cap) String() string { + switch c { + case CAP_CHOWN: + return "chown" + case CAP_DAC_OVERRIDE: + return "dac_override" + case CAP_DAC_READ_SEARCH: + return "dac_read_search" + case CAP_FOWNER: + return "fowner" + case CAP_FSETID: + return "fsetid" + case CAP_KILL: + return "kill" + case CAP_SETGID: + return "setgid" + case CAP_SETUID: + return "setuid" + case CAP_SETPCAP: + return "setpcap" + case CAP_LINUX_IMMUTABLE: + return "linux_immutable" + case CAP_NET_BIND_SERVICE: + return "net_bind_service" + case CAP_NET_BROADCAST: + return "net_broadcast" + case CAP_NET_ADMIN: + return "net_admin" + case CAP_NET_RAW: + return "net_raw" + case CAP_IPC_LOCK: + return "ipc_lock" + case CAP_IPC_OWNER: + return "ipc_owner" + case CAP_SYS_MODULE: + return "sys_module" + case CAP_SYS_RAWIO: + return "sys_rawio" + case CAP_SYS_CHROOT: + return "sys_chroot" + case CAP_SYS_PTRACE: + return "sys_ptrace" + case CAP_SYS_PACCT: + return "sys_pacct" + case CAP_SYS_ADMIN: + return "sys_admin" + case CAP_SYS_BOOT: + return "sys_boot" + case CAP_SYS_NICE: + return "sys_nice" + case CAP_SYS_RESOURCE: + return "sys_resource" + case CAP_SYS_TIME: + return "sys_time" + case CAP_SYS_TTY_CONFIG: + return "sys_tty_config" + case CAP_MKNOD: + return "mknod" + case CAP_LEASE: + return "lease" + case CAP_AUDIT_WRITE: + return "audit_write" + case CAP_AUDIT_CONTROL: + return "audit_control" + case CAP_SETFCAP: + return "setfcap" + case CAP_MAC_OVERRIDE: + return "mac_override" + case CAP_MAC_ADMIN: + return "mac_admin" + case CAP_SYSLOG: + return "syslog" + case CAP_WAKE_ALARM: + return "wake_alarm" + case CAP_BLOCK_SUSPEND: + return "block_suspend" + case CAP_AUDIT_READ: + return "audit_read" + case CAP_PERFMON: + return "perfmon" + case CAP_BPF: + return "bpf" + case CAP_CHECKPOINT_RESTORE: + return "checkpoint_restore" + } + return "unknown" +} + +func list() []Cap { + return []Cap{ + CAP_CHOWN, + CAP_DAC_OVERRIDE, + CAP_DAC_READ_SEARCH, + CAP_FOWNER, + CAP_FSETID, + CAP_KILL, + CAP_SETGID, + CAP_SETUID, + CAP_SETPCAP, + CAP_LINUX_IMMUTABLE, + CAP_NET_BIND_SERVICE, + CAP_NET_BROADCAST, + CAP_NET_ADMIN, + CAP_NET_RAW, + CAP_IPC_LOCK, + CAP_IPC_OWNER, + CAP_SYS_MODULE, + CAP_SYS_RAWIO, + CAP_SYS_CHROOT, + CAP_SYS_PTRACE, + CAP_SYS_PACCT, + CAP_SYS_ADMIN, + CAP_SYS_BOOT, + CAP_SYS_NICE, + CAP_SYS_RESOURCE, + CAP_SYS_TIME, + CAP_SYS_TTY_CONFIG, + CAP_MKNOD, + CAP_LEASE, + CAP_AUDIT_WRITE, + CAP_AUDIT_CONTROL, + CAP_SETFCAP, + CAP_MAC_OVERRIDE, + CAP_MAC_ADMIN, + CAP_SYSLOG, + CAP_WAKE_ALARM, + CAP_BLOCK_SUSPEND, + CAP_AUDIT_READ, + CAP_PERFMON, + CAP_BPF, + CAP_CHECKPOINT_RESTORE, + } +} diff --git a/vendor/github.com/moby/sys/capability/syscall_linux.go b/vendor/github.com/moby/sys/capability/syscall_linux.go new file mode 100644 index 00000000000..d6b6932a94b --- /dev/null +++ b/vendor/github.com/moby/sys/capability/syscall_linux.go @@ -0,0 +1,153 @@ +// Copyright 2024 The Capability Authors. +// Copyright 2013 Suryandaru Triandana +// All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package capability + +import ( + "syscall" + "unsafe" +) + +type capHeader struct { + version uint32 + pid int32 +} + +type capData struct { + effective uint32 + permitted uint32 + inheritable uint32 +} + +func capget(hdr *capHeader, data *capData) (err error) { + _, _, e1 := syscall.Syscall(syscall.SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0) + if e1 != 0 { + err = e1 + } + return +} + +func capset(hdr *capHeader, data *capData) (err error) { + _, _, e1 := syscall.Syscall(syscall.SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0) + if e1 != 0 { + err = e1 + } + return +} + +// not yet in syscall +const ( + pr_CAP_AMBIENT = 47 + pr_CAP_AMBIENT_IS_SET = uintptr(1) + pr_CAP_AMBIENT_RAISE = uintptr(2) + pr_CAP_AMBIENT_LOWER = uintptr(3) + pr_CAP_AMBIENT_CLEAR_ALL = uintptr(4) +) + +func prctl(option int, arg2, arg3, arg4, arg5 uintptr) (err error) { + _, _, e1 := syscall.Syscall6(syscall.SYS_PRCTL, uintptr(option), arg2, arg3, arg4, arg5, 0) + if e1 != 0 { + err = e1 + } + return +} + +const ( + vfsXattrName = "security.capability" + + vfsCapVerMask = 0xff000000 + vfsCapVer1 = 0x01000000 + vfsCapVer2 = 0x02000000 + + vfsCapFlagMask = ^vfsCapVerMask + vfsCapFlageffective = 0x000001 + + vfscapDataSizeV1 = 4 * (1 + 2*1) + vfscapDataSizeV2 = 4 * (1 + 2*2) +) + +type vfscapData struct { + magic uint32 + data [2]struct { + permitted uint32 + inheritable uint32 + } + effective [2]uint32 + version int8 +} + +var _vfsXattrName *byte + +func init() { + _vfsXattrName, _ = syscall.BytePtrFromString(vfsXattrName) +} + +func getVfsCap(path string, dest *vfscapData) (err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := syscall.Syscall6(syscall.SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_vfsXattrName)), uintptr(unsafe.Pointer(dest)), vfscapDataSizeV2, 0, 0) + if e1 != 0 { + if e1 == syscall.ENODATA { + dest.version = 2 + return + } + err = e1 + } + switch dest.magic & vfsCapVerMask { + case vfsCapVer1: + dest.version = 1 + if r0 != vfscapDataSizeV1 { + return syscall.EINVAL + } + dest.data[1].permitted = 0 + dest.data[1].inheritable = 0 + case vfsCapVer2: + dest.version = 2 + if r0 != vfscapDataSizeV2 { + return syscall.EINVAL + } + default: + return syscall.EINVAL + } + if dest.magic&vfsCapFlageffective != 0 { + dest.effective[0] = dest.data[0].permitted | dest.data[0].inheritable + dest.effective[1] = dest.data[1].permitted | dest.data[1].inheritable + } else { + dest.effective[0] = 0 + dest.effective[1] = 0 + } + return +} + +func setVfsCap(path string, data *vfscapData) (err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(path) + if err != nil { + return + } + var size uintptr + if data.version == 1 { + data.magic = vfsCapVer1 + size = vfscapDataSizeV1 + } else if data.version == 2 { + data.magic = vfsCapVer2 + if data.effective[0] != 0 || data.effective[1] != 0 { + data.magic |= vfsCapFlageffective + } + size = vfscapDataSizeV2 + } else { + return syscall.EINVAL + } + _, _, e1 := syscall.Syscall6(syscall.SYS_SETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_vfsXattrName)), uintptr(unsafe.Pointer(data)), size, 0, 0) + if e1 != 0 { + err = e1 + } + return +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 9c5e1e2628f..0b98fc83a7d 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -94,7 +94,7 @@ github.com/containernetworking/cni/pkg/version # github.com/containernetworking/plugins v1.5.1 ## explicit; go 1.20 github.com/containernetworking/plugins/pkg/ns -# github.com/containers/common v0.60.1-0.20240906123248-5298b838dcbd +# github.com/containers/common v0.60.1-0.20241001171026-c3edf18f3339 ## explicit; go 1.22.0 github.com/containers/common/internal github.com/containers/common/internal/attributedstring @@ -309,7 +309,7 @@ github.com/distribution/reference github.com/docker/distribution/registry/api/errcode github.com/docker/distribution/registry/api/v2 github.com/docker/distribution/registry/client/auth/challenge -# github.com/docker/docker v27.2.1+incompatible +# github.com/docker/docker v27.3.1+incompatible ## explicit github.com/docker/docker/api github.com/docker/docker/api/types @@ -515,6 +515,9 @@ github.com/moby/docker-image-spec/specs-go/v1 # github.com/moby/patternmatcher v0.6.0 ## explicit; go 1.19 github.com/moby/patternmatcher +# github.com/moby/sys/capability v0.3.0 +## explicit; go 1.21 +github.com/moby/sys/capability # github.com/moby/sys/mountinfo v0.7.2 ## explicit; go 1.17 github.com/moby/sys/mountinfo @@ -748,15 +751,15 @@ golang.org/x/crypto/ssh/agent golang.org/x/crypto/ssh/internal/bcrypt_pbkdf golang.org/x/crypto/twofish golang.org/x/crypto/xts -# golang.org/x/exp v0.0.0-20240823005443-9b4947da3948 -## explicit; go 1.20 +# golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 +## explicit; go 1.22.0 golang.org/x/exp/constraints golang.org/x/exp/maps golang.org/x/exp/slices -# golang.org/x/mod v0.20.0 -## explicit; go 1.18 +# golang.org/x/mod v0.21.0 +## explicit; go 1.22.0 golang.org/x/mod/semver -# golang.org/x/net v0.28.0 +# golang.org/x/net v0.29.0 ## explicit; go 1.18 golang.org/x/net/http/httpguts golang.org/x/net/http2