Compare commits

..

No commits in common. "factory" and "factory" have entirely different histories.

19 changed files with 1620 additions and 1199 deletions

View File

@ -1,7 +1,7 @@
From 70a1e03d5572deb789c5c4d817257c0760b79869 Mon Sep 17 00:00:00 2001
From ec53ee338835c4c1dc583695ac166f36bf3bac5c Mon Sep 17 00:00:00 2001
From: Aleksa Sarai <asarai@suse.de>
Date: Wed, 8 Mar 2017 12:41:54 +1100
Subject: [PATCH 1/5] SECRETS: daemon: allow directory creation in /run/secrets
Subject: [PATCH 1/7] SECRETS: daemon: allow directory creation in /run/secrets
Since FileMode can have the directory bit set, allow a SecretStore
implementation to return secrets that are actually directories. This is
@ -14,7 +14,7 @@ Signed-off-by: Aleksa Sarai <asarai@suse.de>
1 file changed, 20 insertions(+), 3 deletions(-)
diff --git a/daemon/container_operations_unix.go b/daemon/container_operations_unix.go
index f572e0d8a865..88573559d537 100644
index 4dedc1b21c87..b7c310493e79 100644
--- a/daemon/container_operations_unix.go
+++ b/daemon/container_operations_unix.go
@@ -3,6 +3,7 @@
@ -25,15 +25,15 @@ index f572e0d8a865..88573559d537 100644
"context"
"fmt"
"os"
@@ -17,6 +18,7 @@ import (
"github.com/docker/docker/daemon/network"
@@ -16,6 +17,7 @@ import (
"github.com/docker/docker/daemon/links"
"github.com/docker/docker/errdefs"
"github.com/docker/docker/libnetwork"
+ "github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/idtools"
"github.com/docker/docker/pkg/process"
"github.com/docker/docker/pkg/stringid"
@@ -240,9 +242,6 @@ func (daemon *Daemon) setupSecretDir(ctr *container.Container) (setupErr error)
@@ -240,9 +242,6 @@ func (daemon *Daemon) setupSecretDir(c *container.Container) (setupErr error) {
if err != nil {
return errors.Wrap(err, "unable to get secret from secret store")
}
@ -43,7 +43,7 @@ index f572e0d8a865..88573559d537 100644
uid, err := strconv.Atoi(s.File.UID)
if err != nil {
@@ -253,6 +252,24 @@ func (daemon *Daemon) setupSecretDir(ctr *container.Container) (setupErr error)
@@ -253,6 +252,24 @@ func (daemon *Daemon) setupSecretDir(c *container.Container) (setupErr error) {
return err
}
@ -69,5 +69,5 @@ index f572e0d8a865..88573559d537 100644
return errors.Wrap(err, "error setting ownership for secret")
}
--
2.47.1
2.45.2

View File

@ -1,32 +1,28 @@
From f1bfb09b1d53d6ddf68beedfce4e4110c2b10118 Mon Sep 17 00:00:00 2001
From 759482e941bde2b67d39b52c803e3390555ff9e9 Mon Sep 17 00:00:00 2001
From: Aleksa Sarai <asarai@suse.de>
Date: Wed, 8 Mar 2017 11:43:29 +1100
Subject: [PATCH 2/5] SECRETS: SUSE: implement SUSE container secrets
Subject: [PATCH 2/7] SECRETS: SUSE: implement SUSE container secrets
This allows for us to pass in host credentials to a container, allowing
for SUSEConnect to work with containers.
Users can disable this by setting DOCKER_SUSE_SECRETS_ENABLE=0 in
/etc/sysconfig/docker or by adding that setting to docker.service's
Environment using a drop-in file.
THIS PATCH IS NOT TO BE UPSTREAMED, DUE TO THE FACT THAT IT IS
SUSE-SPECIFIC, AND UPSTREAM DOES NOT APPROVE OF THIS CONCEPT BECAUSE IT
MAKES BUILDS NOT ENTIRELY REPRODUCIBLE.
SUSE-Bugs: bsc#1065609 bsc#1057743 bsc#1055676 bsc#1030702 bsc#1231348
SUSE-Bugs: bsc#1065609 bsc#1057743 bsc#1055676 bsc#1030702
Signed-off-by: Aleksa Sarai <asarai@suse.de>
---
daemon/start.go | 5 +
daemon/suse_secrets.go | 461 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 466 insertions(+)
daemon/suse_secrets.go | 415 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 420 insertions(+)
create mode 100644 daemon/suse_secrets.go
diff --git a/daemon/start.go b/daemon/start.go
index 027f08a6dc07..d8545f8cb46a 100644
index b967947af2ce..09e79e410310 100644
--- a/daemon/start.go
+++ b/daemon/start.go
@@ -128,6 +128,11 @@ func (daemon *Daemon) containerStart(ctx context.Context, daemonCfg *configStore
@@ -123,6 +123,11 @@ func (daemon *Daemon) containerStart(ctx context.Context, daemonCfg *configStore
return err
}
@ -35,15 +31,15 @@ index 027f08a6dc07..d8545f8cb46a 100644
+ return err
+ }
+
mnts, err := daemon.setupContainerDirs(container)
m, cleanup, err := daemon.setupMounts(ctx, container)
if err != nil {
return err
diff --git a/daemon/suse_secrets.go b/daemon/suse_secrets.go
new file mode 100644
index 000000000000..85b37bf46544
index 000000000000..32b0ece91b59
--- /dev/null
+++ b/daemon/suse_secrets.go
@@ -0,0 +1,461 @@
@@ -0,0 +1,415 @@
+/*
+ * suse-secrets: patch for Docker to implement SUSE secrets
+ * Copyright (C) 2017-2021 SUSE LLC.
@ -86,47 +82,9 @@ index 000000000000..85b37bf46544
+ "github.com/sirupsen/logrus"
+)
+
+const suseSecretsTogglePath = "/etc/docker/suse-secrets-enable"
+
+// parseEnableFile parses a file that can only contain "0" or "1" (with some
+// whitespace).
+func parseEnableFile(path string) (bool, error) {
+ data, err := os.ReadFile(path)
+ if err != nil {
+ return false, err
+ }
+ data = bytes.TrimSpace(data)
+
+ switch value := string(data); value {
+ case "1":
+ return true, nil
+ case "0", "":
+ return false, nil
+ default:
+ return false, fmt.Errorf("invalid value %q (must be 0 to disable or 1 to enable)", value)
+ }
+}
+
+func isSuseSecretsEnabled() bool {
+ value, err := parseEnableFile(suseSecretsTogglePath)
+ if err != nil {
+ logrus.Warnf("SUSE:secrets :: error parsing %s: %v -- disabling SUSE secrets", suseSecretsTogglePath, err)
+ value = false
+ }
+ return value
+}
+
+var suseSecretsEnabled = true
+
+func init() {
+ // Make this entire feature toggle-able so that users can disable it if
+ // they run into issues like bsc#1231348.
+ suseSecretsEnabled = isSuseSecretsEnabled()
+ if suseSecretsEnabled {
+ logrus.Infof("SUSE:secrets :: SUSEConnect support enabled (set %s to 0 to disable)", suseSecretsTogglePath)
+ } else {
+ logrus.Infof("SUSE:secrets :: SUSEConnect support disabled by %s", suseSecretsTogglePath)
+ }
+ // Output to tell us in logs that SUSE:secrets is enabled.
+ logrus.Infof("SUSE:secrets :: enabled")
+}
+
+// Creating a fake file.
@ -442,7 +400,7 @@ index 000000000000..85b37bf46544
+ var without []*swarmtypes.SecretReference
+ for _, secret := range c.SecretReferences {
+ if strings.HasPrefix(secret.SecretID, "suse") {
+ logrus.Debugf("SUSE:secrets :: removing 'old' suse secret %q from container %q", secret.SecretID, c.ID)
+ logrus.Warnf("SUSE:secrets :: removing 'old' suse secret %q from container %q", secret.SecretID, c.ID)
+ continue
+ }
+ without = append(without, secret)
@ -451,20 +409,6 @@ index 000000000000..85b37bf46544
+}
+
+func (daemon *Daemon) injectSuseSecretStore(c *container.Container) error {
+ // We drop any "old" SUSE secrets, as it appears that old containers (when
+ // restarted) could still have references to old secrets. The .id() of all
+ // secrets have a prefix of "suse" so this is much easier. See bsc#1057743
+ // for details on why this could cause issues.
+ removeSuseSecrets(c)
+
+ // Don't inject anything if the administrator has disabled suse secrets.
+ // However, for previous existing containers we need to remove old secrets
+ // (see above), otherwise they will still have old secret data.
+ if !suseSecretsEnabled {
+ logrus.Debugf("SUSE:secrets :: skipping injection of secrets into container %q because of %s", c.ID, suseSecretsTogglePath)
+ return nil
+ }
+
+ newDependencyStore := &suseDependencyStore{
+ dfl: c.DependencyStore,
+ secrets: make(map[string]*swarmapi.Secret),
@ -474,6 +418,12 @@ index 000000000000..85b37bf46544
+ newDependencyStore.dfl = emptyStore
+ }
+
+ // We drop any "old" SUSE secrets, as it appears that old containers (when
+ // restarted) could still have references to old secrets. The .id() of all
+ // secrets have a prefix of "suse" so this is much easier. See bsc#1057743
+ // for details on why this could cause issues.
+ removeSuseSecrets(c)
+
+ secrets, err := getHostSuseSecretData()
+ if err != nil {
+ return err
@ -506,5 +456,5 @@ index 000000000000..85b37bf46544
+ return nil
+}
--
2.47.1
2.45.2

View File

@ -1,7 +1,7 @@
From 3613734aeb6eacd45e53dfd834f46dc006ba0047 Mon Sep 17 00:00:00 2001
From 983a57fd37dc8e42e9c4e4dfc72eb346a4385948 Mon Sep 17 00:00:00 2001
From: Aleksa Sarai <asarai@suse.de>
Date: Mon, 22 May 2023 15:44:54 +1000
Subject: [PATCH 3/5] BUILD: SLE12: revert "graphdriver/btrfs: use kernel UAPI
Subject: [PATCH 3/7] BUILD: SLE12: revert "graphdriver/btrfs: use kernel UAPI
headers"
This reverts commit 3208dcabdc8997340b255f5b880fef4e3f54580d.
@ -16,7 +16,7 @@ Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
1 file changed, 4 insertions(+), 9 deletions(-)
diff --git a/daemon/graphdriver/btrfs/btrfs.go b/daemon/graphdriver/btrfs/btrfs.go
index 61f22ed2dd49..330571e3c047 100644
index 6aaa33cf7622..7264d4036427 100644
--- a/daemon/graphdriver/btrfs/btrfs.go
+++ b/daemon/graphdriver/btrfs/btrfs.go
@@ -4,17 +4,12 @@ package btrfs // import "github.com/docker/docker/daemon/graphdriver/btrfs"
@ -42,5 +42,5 @@ index 61f22ed2dd49..330571e3c047 100644
static void set_name_btrfs_ioctl_vol_args_v2(struct btrfs_ioctl_vol_args_v2* btrfs_struct, const char* value) {
snprintf(btrfs_struct->name, BTRFS_SUBVOL_NAME_MAX, "%s", value);
--
2.47.1
2.45.2

View File

@ -1,7 +1,7 @@
From e06f78e09fa03680ce51c8a080447fbc62156d3d Mon Sep 17 00:00:00 2001
From 8829bb8ec53399fd41dd6f46e2bad64e773e8eaa Mon Sep 17 00:00:00 2001
From: Aleksa Sarai <asarai@suse.de>
Date: Fri, 29 Jun 2018 17:59:30 +1000
Subject: [PATCH 4/5] bsc1073877: apparmor: clobber docker-default profile on
Subject: [PATCH 4/7] bsc1073877: apparmor: clobber docker-default profile on
start
In the process of making docker-default reloading far less expensive,
@ -69,10 +69,10 @@ index be4938f5b61a..2b326fea5829 100644
return nil
}
diff --git a/daemon/daemon.go b/daemon/daemon.go
index f152685e6026..dee4c33471d5 100644
index e7ca77d8cbfc..13b39538fb00 100644
--- a/daemon/daemon.go
+++ b/daemon/daemon.go
@@ -941,8 +941,9 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S
@@ -916,8 +916,9 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S
log.G(ctx).Warnf("Failed to configure golang's threads limit: %v", err)
}
@ -81,9 +81,9 @@ index f152685e6026..dee4c33471d5 100644
+ // Make sure we clobber any pre-existing docker-default profile to ensure
+ // that upgrades to the profile actually work smoothly.
+ if err := clobberDefaultAppArmorProfile(); err != nil {
log.G(ctx).WithError(err).Error("Failed to ensure default apparmor profile is loaded")
log.G(ctx).Errorf(err.Error())
}
--
2.47.1
2.45.2

View File

@ -1,7 +1,7 @@
From 65799b8d19180cb039d257262bfa88e6629ccdf9 Mon Sep 17 00:00:00 2001
From 24173cd6a2643e5e680e84920864f42ed43b6f28 Mon Sep 17 00:00:00 2001
From: Aleksa Sarai <asarai@suse.de>
Date: Wed, 11 Oct 2023 21:19:12 +1100
Subject: [PATCH 5/5] SLE12: revert "apparmor: remove version-conditionals from
Subject: [PATCH 5/7] SLE12: revert "apparmor: remove version-conditionals from
template"
This reverts the following commits:
@ -322,5 +322,5 @@ index 8dbc1b610288..2062aab1ac99 100644
}
`
--
2.47.1
2.45.2

View File

@ -0,0 +1,890 @@
From dd16d113b9215bf5b0b56c409e7272ce07525836 Mon Sep 17 00:00:00 2001
From: Aleksa Sarai <cyphar@cyphar.com>
Date: Tue, 7 May 2024 01:51:25 +1000
Subject: [PATCH 6/7] bsc1221916: update to patched buildkit version to fix
symlink resolution
SUSE-Bugs: https://bugzilla.suse.com/show_bug.cgi?id=1221916
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
---
vendor.mod | 2 +
vendor.sum | 4 +-
.../buildkit/cache/contenthash/checksum.go | 393 ++++++++++--------
.../moby/buildkit/cache/contenthash/path.go | 161 +++----
vendor/modules.txt | 3 +-
5 files changed, 314 insertions(+), 249 deletions(-)
diff --git a/vendor.mod b/vendor.mod
index d69d2aa9f87f..5c42a653b91b 100644
--- a/vendor.mod
+++ b/vendor.mod
@@ -114,6 +114,8 @@ require (
tags.cncf.io/container-device-interface v0.7.2
)
+replace github.com/moby/buildkit => github.com/cyphar/buildkit v0.0.0-20240624075140-0db2d2345b94
+
require (
cloud.google.com/go v0.110.8 // indirect
cloud.google.com/go/compute v1.23.1 // indirect
diff --git a/vendor.sum b/vendor.sum
index 7a5bd6b4077b..f2aba7f8d3eb 100644
--- a/vendor.sum
+++ b/vendor.sum
@@ -199,6 +199,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
+github.com/cyphar/buildkit v0.0.0-20240624075140-0db2d2345b94 h1:xBwPT+ap0LDYsQJh1VKm9NNEKF5A7e/P3TRjnbTqZUE=
+github.com/cyphar/buildkit v0.0.0-20240624075140-0db2d2345b94/go.mod h1:2cyVOv9NoHM7arphK9ZfHIWKn9YVZRFd1wXB8kKmEzY=
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -480,8 +482,6 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b/go.mod h1:pzzDgJWZ34fGzaAZGFW22KVZDfyrYW+QABMrWnJBnSs=
-github.com/moby/buildkit v0.13.2 h1:nXNszM4qD9E7QtG7bFWPnDI1teUQFQglBzon/IU3SzI=
-github.com/moby/buildkit v0.13.2/go.mod h1:2cyVOv9NoHM7arphK9ZfHIWKn9YVZRFd1wXB8kKmEzY=
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/moby/ipvs v1.1.0 h1:ONN4pGaZQgAx+1Scz5RvWV4Q7Gb+mvfRh3NsPS+1XQQ=
diff --git a/vendor/github.com/moby/buildkit/cache/contenthash/checksum.go b/vendor/github.com/moby/buildkit/cache/contenthash/checksum.go
index e0f58d57b3db..ec649f69b5e0 100644
--- a/vendor/github.com/moby/buildkit/cache/contenthash/checksum.go
+++ b/vendor/github.com/moby/buildkit/cache/contenthash/checksum.go
@@ -10,6 +10,7 @@ import (
"path/filepath"
"strings"
"sync"
+ "sync/atomic"
iradix "github.com/hashicorp/go-immutable-radix"
"github.com/hashicorp/golang-lru/simplelru"
@@ -290,7 +291,7 @@ func keyPath(p string) string {
// HandleChange notifies the source about a modification operation
func (cc *cacheContext) HandleChange(kind fsutil.ChangeKind, p string, fi os.FileInfo, err error) (retErr error) {
p = keyPath(p)
- k := convertPathToKey([]byte(p))
+ k := convertPathToKey(p)
deleteDir := func(cr *CacheRecord) {
if cr.Type == CacheRecordTypeDir {
@@ -369,7 +370,7 @@ func (cc *cacheContext) HandleChange(kind fsutil.ChangeKind, p string, fi os.Fil
// note that the source may be called later because data writing is async
if fi.Mode()&os.ModeSymlink == 0 && stat.Linkname != "" {
ln := path.Join("/", filepath.ToSlash(stat.Linkname))
- v, ok := cc.txn.Get(convertPathToKey([]byte(ln)))
+ v, ok := cc.txn.Get(convertPathToKey(ln))
if ok {
cp := *v.(*CacheRecord)
cr = &cp
@@ -407,7 +408,7 @@ func (cc *cacheContext) Checksum(ctx context.Context, mountable cache.Mountable,
defer m.clean()
if !opts.Wildcard && len(opts.IncludePatterns) == 0 && len(opts.ExcludePatterns) == 0 {
- return cc.checksumFollow(ctx, m, p, opts.FollowLinks)
+ return cc.lazyChecksum(ctx, m, p, opts.FollowLinks)
}
includedPaths, err := cc.includedPaths(ctx, m, p, opts)
@@ -418,7 +419,7 @@ func (cc *cacheContext) Checksum(ctx context.Context, mountable cache.Mountable,
if opts.FollowLinks {
for i, w := range includedPaths {
if w.record.Type == CacheRecordTypeSymlink {
- dgst, err := cc.checksumFollow(ctx, m, w.path, opts.FollowLinks)
+ dgst, err := cc.lazyChecksum(ctx, m, w.path, opts.FollowLinks)
if err != nil {
return "", err
}
@@ -445,30 +446,6 @@ func (cc *cacheContext) Checksum(ctx context.Context, mountable cache.Mountable,
return digester.Digest(), nil
}
-func (cc *cacheContext) checksumFollow(ctx context.Context, m *mount, p string, follow bool) (digest.Digest, error) {
- const maxSymlinkLimit = 255
- i := 0
- for {
- if i > maxSymlinkLimit {
- return "", errors.Errorf("too many symlinks: %s", p)
- }
- cr, err := cc.checksumNoFollow(ctx, m, p)
- if err != nil {
- return "", err
- }
- if cr.Type == CacheRecordTypeSymlink && follow {
- link := cr.Linkname
- if !path.IsAbs(cr.Linkname) {
- link = path.Join(path.Dir(p), link)
- }
- i++
- p = link
- } else {
- return cr.Digest, nil
- }
- }
-}
-
func (cc *cacheContext) includedPaths(ctx context.Context, m *mount, p string, opts ChecksumOpts) ([]*includedPath, error) {
cc.mu.Lock()
defer cc.mu.Unlock()
@@ -478,12 +455,12 @@ func (cc *cacheContext) includedPaths(ctx context.Context, m *mount, p string, o
}
root := cc.tree.Root()
- scan, err := cc.needsScan(root, "")
+ scan, err := cc.needsScan(root, "", false)
if err != nil {
return nil, err
}
if scan {
- if err := cc.scanPath(ctx, m, ""); err != nil {
+ if err := cc.scanPath(ctx, m, "", false); err != nil {
return nil, err
}
}
@@ -536,13 +513,13 @@ func (cc *cacheContext) includedPaths(ctx context.Context, m *mount, p string, o
}
} else {
origPrefix = p
- k = convertPathToKey([]byte(origPrefix))
+ k = convertPathToKey(origPrefix)
// We need to resolve symlinks here, in case the base path
// involves a symlink. That will match fsutil behavior of
// calling functions such as stat and walk.
var cr *CacheRecord
- k, cr, err = getFollowLinks(root, k, true)
+ k, cr, err = getFollowLinks(root, k, false)
if err != nil {
return nil, err
}
@@ -554,7 +531,7 @@ func (cc *cacheContext) includedPaths(ctx context.Context, m *mount, p string, o
iter.SeekLowerBound(append(append([]byte{}, k...), 0))
}
- resolvedPrefix = string(convertKeyToPath(k))
+ resolvedPrefix = convertKeyToPath(k)
} else {
k, _, keyOk = iter.Next()
}
@@ -565,7 +542,7 @@ func (cc *cacheContext) includedPaths(ctx context.Context, m *mount, p string, o
)
for keyOk {
- fn := string(convertKeyToPath(k))
+ fn := convertKeyToPath(k)
// Convert the path prefix from what we found in the prefix
// tree to what the argument specified.
@@ -751,36 +728,12 @@ func wildcardPrefix(root *iradix.Node, p string) (string, []byte, bool, error) {
return "", nil, false, nil
}
- linksWalked := 0
- k, cr, err := getFollowLinksWalk(root, convertPathToKey([]byte(d1)), true, &linksWalked)
+ // Only resolve the final symlink component if there are components in the
+ // wildcard segment.
+ k, cr, err := getFollowLinks(root, convertPathToKey(d1), d2 != "")
if err != nil {
return "", k, false, err
}
-
- if d2 != "" && cr != nil && cr.Type == CacheRecordTypeSymlink {
- // getFollowLinks only handles symlinks in path
- // components before the last component, so
- // handle last component in d1 specially.
- resolved := string(convertKeyToPath(k))
- for {
- v, ok := root.Get(k)
-
- if !ok {
- return d1, k, false, nil
- }
- if v.(*CacheRecord).Type != CacheRecordTypeSymlink {
- break
- }
-
- linksWalked++
- if linksWalked > 255 {
- return "", k, false, errors.Errorf("too many links")
- }
-
- resolved := cleanLink(resolved, v.(*CacheRecord).Linkname)
- k = convertPathToKey([]byte(resolved))
- }
- }
return d1, k, cr != nil, nil
}
@@ -816,19 +769,22 @@ func containsWildcards(name string) bool {
return false
}
-func (cc *cacheContext) checksumNoFollow(ctx context.Context, m *mount, p string) (*CacheRecord, error) {
+func (cc *cacheContext) lazyChecksum(ctx context.Context, m *mount, p string, followTrailing bool) (digest.Digest, error) {
p = keyPath(p)
+ k := convertPathToKey(p)
+ // Try to look up the path directly without doing a scan.
cc.mu.RLock()
if cc.txn == nil {
root := cc.tree.Root()
cc.mu.RUnlock()
- v, ok := root.Get(convertPathToKey([]byte(p)))
- if ok {
- cr := v.(*CacheRecord)
- if cr.Digest != "" {
- return cr, nil
- }
+
+ _, cr, err := getFollowLinks(root, k, followTrailing)
+ if err != nil {
+ return "", err
+ }
+ if cr != nil && cr.Digest != "" {
+ return cr.Digest, nil
}
} else {
cc.mu.RUnlock()
@@ -848,7 +804,11 @@ func (cc *cacheContext) checksumNoFollow(ctx context.Context, m *mount, p string
}
}()
- return cc.lazyChecksum(ctx, m, p)
+ cr, err := cc.scanChecksum(ctx, m, p, followTrailing)
+ if err != nil {
+ return "", err
+ }
+ return cr.Digest, nil
}
func (cc *cacheContext) commitActiveTransaction() {
@@ -856,7 +816,7 @@ func (cc *cacheContext) commitActiveTransaction() {
addParentToMap(d, cc.dirtyMap)
}
for d := range cc.dirtyMap {
- k := convertPathToKey([]byte(d))
+ k := convertPathToKey(d)
if _, ok := cc.txn.Get(k); ok {
cc.txn.Insert(k, &CacheRecord{Type: CacheRecordTypeDir})
}
@@ -867,21 +827,21 @@ func (cc *cacheContext) commitActiveTransaction() {
cc.txn = nil
}
-func (cc *cacheContext) lazyChecksum(ctx context.Context, m *mount, p string) (*CacheRecord, error) {
+func (cc *cacheContext) scanChecksum(ctx context.Context, m *mount, p string, followTrailing bool) (*CacheRecord, error) {
root := cc.tree.Root()
- scan, err := cc.needsScan(root, p)
+ scan, err := cc.needsScan(root, p, followTrailing)
if err != nil {
return nil, err
}
if scan {
- if err := cc.scanPath(ctx, m, p); err != nil {
+ if err := cc.scanPath(ctx, m, p, followTrailing); err != nil {
return nil, err
}
}
- k := convertPathToKey([]byte(p))
+ k := convertPathToKey(p)
txn := cc.tree.Txn()
root = txn.Root()
- cr, updated, err := cc.checksum(ctx, root, txn, m, k, true)
+ cr, updated, err := cc.checksum(ctx, root, txn, m, k, followTrailing)
if err != nil {
return nil, err
}
@@ -890,9 +850,9 @@ func (cc *cacheContext) lazyChecksum(ctx context.Context, m *mount, p string) (*
return cr, err
}
-func (cc *cacheContext) checksum(ctx context.Context, root *iradix.Node, txn *iradix.Txn, m *mount, k []byte, follow bool) (*CacheRecord, bool, error) {
+func (cc *cacheContext) checksum(ctx context.Context, root *iradix.Node, txn *iradix.Txn, m *mount, k []byte, followTrailing bool) (*CacheRecord, bool, error) {
origk := k
- k, cr, err := getFollowLinks(root, k, follow)
+ k, cr, err := getFollowLinks(root, k, followTrailing)
if err != nil {
return nil, false, err
}
@@ -918,7 +878,9 @@ func (cc *cacheContext) checksum(ctx context.Context, root *iradix.Node, txn *ir
}
h.Write(bytes.TrimPrefix(subk, k))
- subcr, _, err := cc.checksum(ctx, root, txn, m, subk, true)
+ // We do not follow trailing links when checksumming a directory's
+ // contents.
+ subcr, _, err := cc.checksum(ctx, root, txn, m, subk, false)
if err != nil {
return nil, false, err
}
@@ -935,7 +897,7 @@ func (cc *cacheContext) checksum(ctx context.Context, root *iradix.Node, txn *ir
dgst = digest.NewDigest(digest.SHA256, h)
default:
- p := string(convertKeyToPath(bytes.TrimSuffix(k, []byte{0})))
+ p := convertKeyToPath(bytes.TrimSuffix(k, []byte{0}))
target, err := m.mount(ctx)
if err != nil {
@@ -967,42 +929,82 @@ func (cc *cacheContext) checksum(ctx context.Context, root *iradix.Node, txn *ir
return cr2, true, nil
}
-// needsScan returns false if path is in the tree or a parent path is in tree
-// and subpath is missing
-func (cc *cacheContext) needsScan(root *iradix.Node, p string) (bool, error) {
- var linksWalked int
- return cc.needsScanFollow(root, p, &linksWalked)
+// pathSet is a set of path prefixes that can be used to see if a given path is
+// lexically a child of any path in the set. All paths provided to this set
+// MUST be absolute and use / as the separator.
+type pathSet struct {
+ // prefixes contains paths of the form "/a/b/", so that we correctly detect
+ // /a/b as being a parent of /a/b/c but not /a/bc.
+ prefixes []string
}
-func (cc *cacheContext) needsScanFollow(root *iradix.Node, p string, linksWalked *int) (bool, error) {
- if p == "/" {
- p = ""
- }
- v, ok := root.Get(convertPathToKey([]byte(p)))
- if !ok {
- if p == "" {
- return true, nil
+// add a path to the set. This is a no-op if includes(path) == true.
+func (s *pathSet) add(p string) {
+ // Ensure the path is absolute and clean.
+ p = path.Join("/", p)
+ if !s.includes(p) {
+ if p != "/" {
+ p += "/"
}
- return cc.needsScanFollow(root, path.Clean(path.Dir(p)), linksWalked)
+ s.prefixes = append(s.prefixes, p)
+ }
+}
+
+// includes returns true iff there is a path in the pathSet which is a lexical
+// parent of the given path. The provided path MUST be an absolute path and
+// MUST NOT contain any ".." components, as they will be path.Clean'd.
+func (s pathSet) includes(p string) bool {
+ // Ensure the path is absolute and clean.
+ p = path.Join("/", p)
+ if p != "/" {
+ p += "/"
}
- cr := v.(*CacheRecord)
- if cr.Type == CacheRecordTypeSymlink {
- if *linksWalked > 255 {
- return false, errTooManyLinks
+ for _, prefix := range s.prefixes {
+ if strings.HasPrefix(p, prefix) {
+ return true
}
- *linksWalked++
- link := path.Clean(cr.Linkname)
- if !path.IsAbs(cr.Linkname) {
- link = path.Join("/", path.Dir(p), link)
+ }
+ return false
+}
+
+// needsScan returns false if path is in the tree or a parent path is in tree
+// and subpath is missing.
+func (cc *cacheContext) needsScan(root *iradix.Node, path string, followTrailing bool) (bool, error) {
+ var (
+ goodPaths pathSet
+ hasParentInTree bool
+ )
+ k := convertPathToKey(path)
+ _, cr, err := getFollowLinksCallback(root, k, followTrailing, func(subpath string, cr *CacheRecord) error {
+ // If we found a path that exists in the cache, add it to the set of
+ // known-scanned paths. Otherwise, verify whether the not-found subpath
+ // is inside a known-scanned path (we might have hit a "..", taking us
+ // out of the scanned paths, or we might hit a non-existent path inside
+ // a scanned path). getFollowLinksCallback iterates left-to-right, so
+ // we will always hit ancestors first.
+ if cr != nil {
+ hasParentInTree = cr.Type != CacheRecordTypeSymlink
+ goodPaths.add(subpath)
+ } else {
+ hasParentInTree = goodPaths.includes(subpath)
}
- return cc.needsScanFollow(root, link, linksWalked)
+ return nil
+ })
+ if err != nil {
+ return false, err
}
- return false, nil
+ return cr == nil && !hasParentInTree, nil
}
-func (cc *cacheContext) scanPath(ctx context.Context, m *mount, p string) (retErr error) {
+// Only used by TestNeedScanChecksumRegression to make sure scanPath is not
+// called for paths we have already scanned.
+var (
+ scanCounterEnable bool
+ scanCounter atomic.Uint64
+)
+
+func (cc *cacheContext) scanPath(ctx context.Context, m *mount, p string, followTrailing bool) (retErr error) {
p = path.Join("/", p)
- d, _ := path.Split(p)
mp, err := m.mount(ctx)
if err != nil {
@@ -1012,33 +1014,42 @@ func (cc *cacheContext) scanPath(ctx context.Context, m *mount, p string) (retEr
n := cc.tree.Root()
txn := cc.tree.Txn()
- parentPath, err := rootPath(mp, filepath.FromSlash(d), func(p, link string) error {
+ resolvedPath, err := rootPath(mp, filepath.FromSlash(p), followTrailing, func(p, link string) error {
cr := &CacheRecord{
Type: CacheRecordTypeSymlink,
Linkname: filepath.ToSlash(link),
}
- k := []byte(path.Join("/", filepath.ToSlash(p)))
- k = convertPathToKey(k)
- txn.Insert(k, cr)
+ p = path.Join("/", filepath.ToSlash(p))
+ txn.Insert(convertPathToKey(p), cr)
return nil
})
if err != nil {
return err
}
- err = filepath.Walk(parentPath, func(itemPath string, fi os.FileInfo, err error) error {
+ // Scan the parent directory of the path we resolved, unless we're at the
+ // root (in which case we scan the root).
+ scanPath := filepath.Dir(resolvedPath)
+ if !strings.HasPrefix(filepath.ToSlash(scanPath)+"/", filepath.ToSlash(mp)+"/") {
+ scanPath = resolvedPath
+ }
+
+ err = filepath.Walk(scanPath, func(itemPath string, fi os.FileInfo, err error) error {
+ if scanCounterEnable {
+ scanCounter.Add(1)
+ }
if err != nil {
+ // If the root doesn't exist, ignore the error.
+ if itemPath == scanPath && errors.Is(err, os.ErrNotExist) {
+ return nil
+ }
return errors.Wrapf(err, "failed to walk %s", itemPath)
}
rel, err := filepath.Rel(mp, itemPath)
if err != nil {
return err
}
- k := []byte(path.Join("/", filepath.ToSlash(rel)))
- if string(k) == "/" {
- k = []byte{}
- }
- k = convertPathToKey(k)
+ k := convertPathToKey(keyPath(rel))
if _, ok := n.Get(k); !ok {
cr := &CacheRecord{
Type: CacheRecordTypeFile,
@@ -1071,55 +1082,118 @@ func (cc *cacheContext) scanPath(ctx context.Context, m *mount, p string) (retEr
return nil
}
-func getFollowLinks(root *iradix.Node, k []byte, follow bool) ([]byte, *CacheRecord, error) {
- var linksWalked int
- return getFollowLinksWalk(root, k, follow, &linksWalked)
+// followLinksCallback is called after we try to resolve each element. If the
+// path was not found, cr is nil.
+type followLinksCallback func(path string, cr *CacheRecord) error
+
+// getFollowLinks is shorthand for getFollowLinksCallback(..., nil).
+func getFollowLinks(root *iradix.Node, k []byte, followTrailing bool) ([]byte, *CacheRecord, error) {
+ return getFollowLinksCallback(root, k, followTrailing, nil)
}
-func getFollowLinksWalk(root *iradix.Node, k []byte, follow bool, linksWalked *int) ([]byte, *CacheRecord, error) {
+// getFollowLinksCallback looks up the requested key, fully resolving any
+// symlink components encountered. The implementation is heavily based on
+// <https://github.com/cyphar/filepath-securejoin>.
+//
+// followTrailing indicates whether the *final component* of the path should be
+// resolved (effectively O_PATH|O_NOFOLLOW). Note that (in contrast to some
+// Linux APIs), followTrailing is obeyed even if the key has a trailing slash
+// (though paths like "foo/link/." will cause the link to be resolved).
+//
+// cb is a callback that is called for each path component encountered during
+// path resolution (after the path component is looked up in the cache). This
+// means for a path like /a/b/c, the callback will be called for at least
+//
+// {/, /a, /a/b, /a/b/c}
+//
+// Note that if any of the components are symlinks, the paths will depend on
+// the symlink contents and there will be more callbacks. If the requested key
+// has a trailing slash, the callback will also be called for the final
+// trailing-slash lookup (/a/b/c/ in the above example). Note that
+// getFollowLinksCallback will try to look up the original key directly first
+// and the callback is not called for this first lookup.
+func getFollowLinksCallback(root *iradix.Node, k []byte, followTrailing bool, cb followLinksCallback) ([]byte, *CacheRecord, error) {
v, ok := root.Get(k)
- if ok {
+ if ok && (!followTrailing || v.(*CacheRecord).Type != CacheRecordTypeSymlink) {
return k, v.(*CacheRecord), nil
}
- if !follow || len(k) == 0 {
+ if len(k) == 0 {
return k, nil, nil
}
- dir, file := splitKey(k)
+ var (
+ currentPath = "/"
+ remainingPath = convertKeyToPath(k)
+ linksWalked int
+ cr *CacheRecord
+ )
+ // Trailing slashes are significant for the cache, but path.Clean strips
+ // them. We only care about the slash for the final lookup.
+ remainingPath, hadTrailingSlash := strings.CutSuffix(remainingPath, "/")
+ for remainingPath != "" {
+ // Get next component.
+ var part string
+ if i := strings.IndexRune(remainingPath, '/'); i == -1 {
+ part, remainingPath = remainingPath, ""
+ } else {
+ part, remainingPath = remainingPath[:i], remainingPath[i+1:]
+ }
- k, parent, err := getFollowLinksWalk(root, dir, follow, linksWalked)
- if err != nil {
- return nil, nil, err
- }
- if parent != nil {
- if parent.Type == CacheRecordTypeSymlink {
- *linksWalked++
- if *linksWalked > 255 {
- return nil, nil, errors.Errorf("too many links")
+ // Apply the component to the path. Since it is a single component, and
+ // our current path contains no symlinks, we can just apply it
+ // leixically.
+ nextPath := keyPath(path.Join("/", currentPath, part))
+ // In contrast to rootPath, we don't skip lookups for no-op components
+ // or / because we need to call the callback for every path component
+ // we hit (including /) and we need to make sure that the CacheRecord
+ // we return is correct after every iteration.
+
+ cr = nil
+ v, ok := root.Get(convertPathToKey(nextPath))
+ if ok {
+ cr = v.(*CacheRecord)
+ }
+ if cb != nil {
+ if err := cb(nextPath, cr); err != nil {
+ return nil, nil, err
}
+ }
+ if !ok || cr.Type != CacheRecordTypeSymlink {
+ currentPath = nextPath
+ continue
+ }
+ if !followTrailing && remainingPath == "" {
+ currentPath = nextPath
+ break
+ }
- link := cleanLink(string(convertKeyToPath(dir)), parent.Linkname)
- return getFollowLinksWalk(root, append(convertPathToKey([]byte(link)), file...), follow, linksWalked)
+ linksWalked++
+ if linksWalked > maxSymlinkLimit {
+ return nil, nil, errTooManyLinks
}
- }
- k = append(k, file...)
- v, ok = root.Get(k)
- if ok {
- return k, v.(*CacheRecord), nil
- }
- return k, nil, nil
-}
-func cleanLink(dir, linkname string) string {
- dirPath := path.Clean(dir)
- if dirPath == "." || dirPath == "/" {
- dirPath = ""
+ remainingPath = cr.Linkname + "/" + remainingPath
+ if path.IsAbs(cr.Linkname) {
+ currentPath = "/"
+ }
}
- link := path.Clean(linkname)
- if !path.IsAbs(link) {
- return path.Join("/", path.Join(path.Dir(dirPath), link))
+ // We've already looked up the final component. However, if there was a
+ // trailing slash in the original path, we need to do the lookup again with
+ // the slash applied.
+ if hadTrailingSlash {
+ cr = nil
+ currentPath += "/"
+ v, ok := root.Get(convertPathToKey(currentPath))
+ if ok {
+ cr = v.(*CacheRecord)
+ }
+ if cb != nil {
+ if err := cb(currentPath, cr); err != nil {
+ return nil, nil, err
+ }
+ }
}
- return link
+ return convertPathToKey(currentPath), cr, nil
}
func prepareDigest(fp, p string, fi os.FileInfo) (digest.Digest, error) {
@@ -1176,25 +1250,10 @@ func poolsCopy(dst io.Writer, src io.Reader) (written int64, err error) {
return
}
-func convertPathToKey(p []byte) []byte {
+func convertPathToKey(p string) []byte {
return bytes.Replace([]byte(p), []byte("/"), []byte{0}, -1)
}
-func convertKeyToPath(p []byte) []byte {
- return bytes.Replace([]byte(p), []byte{0}, []byte("/"), -1)
-}
-
-func splitKey(k []byte) ([]byte, []byte) {
- foundBytes := false
- i := len(k) - 1
- for {
- if i <= 0 || foundBytes && k[i] == 0 {
- break
- }
- if k[i] != 0 {
- foundBytes = true
- }
- i--
- }
- return append([]byte{}, k[:i]...), k[i:]
+func convertKeyToPath(p []byte) string {
+ return string(bytes.Replace(p, []byte{0}, []byte("/"), -1))
}
diff --git a/vendor/github.com/moby/buildkit/cache/contenthash/path.go b/vendor/github.com/moby/buildkit/cache/contenthash/path.go
index 42b7fd8349c7..ae950f713241 100644
--- a/vendor/github.com/moby/buildkit/cache/contenthash/path.go
+++ b/vendor/github.com/moby/buildkit/cache/contenthash/path.go
@@ -1,108 +1,111 @@
+// This code mostly comes from <https://github.com/cyphar/filepath-securejoin>.
+
+// Copyright (C) 2014-2015 Docker Inc & Go Authors. All rights reserved.
+// Copyright (C) 2017-2024 SUSE LLC. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
package contenthash
import (
"os"
"path/filepath"
+ "strings"
"github.com/pkg/errors"
)
-var (
- errTooManyLinks = errors.New("too many links")
-)
+var errTooManyLinks = errors.New("too many links")
+
+const maxSymlinkLimit = 255
type onSymlinkFunc func(string, string) error
-// rootPath joins a path with a root, evaluating and bounding any
-// symlink to the root directory.
-// This is containerd/continuity/fs RootPath implementation with a callback on
-// resolving the symlink.
-func rootPath(root, path string, cb onSymlinkFunc) (string, error) {
- if path == "" {
+// rootPath joins a path with a root, evaluating and bounding any symlink to
+// the root directory. This is a slightly modified version of SecureJoin from
+// github.com/cyphar/filepath-securejoin, with a callback which we call after
+// each symlink resolution.
+func rootPath(root, unsafePath string, followTrailing bool, cb onSymlinkFunc) (string, error) {
+ if unsafePath == "" {
return root, nil
}
- var linksWalked int // to protect against cycles
- for {
- i := linksWalked
- newpath, err := walkLinks(root, path, &linksWalked, cb)
- if err != nil {
- return "", err
- }
- path = newpath
- if i == linksWalked {
- newpath = filepath.Join("/", newpath)
- if path == newpath {
- return filepath.Join(root, newpath), nil
- }
- path = newpath
- }
- }
-}
-func walkLink(root, path string, linksWalked *int, cb onSymlinkFunc) (newpath string, islink bool, err error) {
- if *linksWalked > 255 {
- return "", false, errTooManyLinks
- }
+ unsafePath = filepath.FromSlash(unsafePath)
+ var (
+ currentPath string
+ linksWalked int
+ )
+ for unsafePath != "" {
+ // Windows-specific: remove any drive letters from the path.
+ if v := filepath.VolumeName(unsafePath); v != "" {
+ unsafePath = unsafePath[len(v):]
+ }
- path = filepath.Join("/", path)
- if path == "/" {
- return path, false, nil
- }
- realPath := filepath.Join(root, path)
+ // Remove any unnecessary trailing slashes.
+ unsafePath = strings.TrimSuffix(unsafePath, string(filepath.Separator))
- fi, err := os.Lstat(realPath)
- if err != nil {
- // If path does not yet exist, treat as non-symlink
- if errors.Is(err, os.ErrNotExist) {
- return path, false, nil
+ // Get the next path component.
+ var part string
+ if i := strings.IndexRune(unsafePath, filepath.Separator); i == -1 {
+ part, unsafePath = unsafePath, ""
+ } else {
+ part, unsafePath = unsafePath[:i], unsafePath[i+1:]
}
- return "", false, err
- }
- if fi.Mode()&os.ModeSymlink == 0 {
- return path, false, nil
- }
- newpath, err = os.Readlink(realPath)
- if err != nil {
- return "", false, err
- }
- if cb != nil {
- if err := cb(path, newpath); err != nil {
- return "", false, err
- }
- }
- *linksWalked++
- return newpath, true, nil
-}
-func walkLinks(root, path string, linksWalked *int, cb onSymlinkFunc) (string, error) {
- switch dir, file := filepath.Split(path); {
- case dir == "":
- newpath, _, err := walkLink(root, file, linksWalked, cb)
- return newpath, err
- case file == "":
- if os.IsPathSeparator(dir[len(dir)-1]) {
- if dir == "/" {
- return dir, nil
- }
- return walkLinks(root, dir[:len(dir)-1], linksWalked, cb)
+ // Apply the component lexically to the path we are building. path does
+ // not contain any symlinks, and we are lexically dealing with a single
+ // component, so it's okay to do filepath.Clean here.
+ nextPath := filepath.Join(string(filepath.Separator), currentPath, part)
+ if nextPath == string(filepath.Separator) {
+ // If we end up back at the root, we don't need to re-evaluate /.
+ currentPath = ""
+ continue
}
- newpath, _, err := walkLink(root, dir, linksWalked, cb)
- return newpath, err
- default:
- newdir, err := walkLinks(root, dir, linksWalked, cb)
- if err != nil {
+ fullPath := root + string(filepath.Separator) + nextPath
+
+ // Figure out whether the path is a symlink.
+ fi, err := os.Lstat(fullPath)
+ if err != nil && !errors.Is(err, os.ErrNotExist) {
return "", err
}
- newpath, islink, err := walkLink(root, filepath.Join(newdir, file), linksWalked, cb)
+ // Treat non-existent path components the same as non-symlinks (we
+ // can't do any better here).
+ if errors.Is(err, os.ErrNotExist) || fi.Mode()&os.ModeSymlink == 0 {
+ currentPath = nextPath
+ continue
+ }
+ // Don't resolve the final component with !followTrailing.
+ if !followTrailing && unsafePath == "" {
+ currentPath = nextPath
+ break
+ }
+
+ // It's a symlink, so get its contents and expand it by prepending it
+ // to the yet-unparsed path.
+ linksWalked++
+ if linksWalked > maxSymlinkLimit {
+ return "", errTooManyLinks
+ }
+
+ dest, err := os.Readlink(fullPath)
if err != nil {
return "", err
}
- if !islink {
- return newpath, nil
+ if cb != nil {
+ if err := cb(nextPath, dest); err != nil {
+ return "", err
+ }
}
- if filepath.IsAbs(newpath) {
- return newpath, nil
+
+ unsafePath = dest + string(filepath.Separator) + unsafePath
+ // Absolute symlinks reset any work we've already done.
+ if filepath.IsAbs(dest) {
+ currentPath = ""
}
- return filepath.Join(newdir, newpath), nil
}
+
+ // There should be no lexical components left in path here, but just for
+ // safety do a filepath.Clean before the join.
+ finalPath := filepath.Join(string(filepath.Separator), currentPath)
+ return filepath.Join(root, finalPath), nil
}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 7f3e6497785d..247f49f3518e 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -711,7 +711,7 @@ github.com/mitchellh/hashstructure/v2
# github.com/mitchellh/reflectwalk v1.0.2
## explicit
github.com/mitchellh/reflectwalk
-# github.com/moby/buildkit v0.13.2
+# github.com/moby/buildkit v0.13.2 => github.com/cyphar/buildkit v0.0.0-20240624075140-0db2d2345b94
## explicit; go 1.21
github.com/moby/buildkit/api/services/control
github.com/moby/buildkit/api/types
@@ -1610,3 +1610,4 @@ tags.cncf.io/container-device-interface/pkg/parser
# tags.cncf.io/container-device-interface/specs-go v0.7.0
## explicit; go 1.19
tags.cncf.io/container-device-interface/specs-go
+# github.com/moby/buildkit => github.com/cyphar/buildkit v0.0.0-20240624075140-0db2d2345b94
--
2.45.2

View File

@ -0,0 +1,53 @@
From 62035ba22a45bde6bed2da321e7ad954f5b461b4 Mon Sep 17 00:00:00 2001
From: Aleksa Sarai <cyphar@cyphar.com>
Date: Wed, 19 Jun 2024 16:30:49 +1000
Subject: [PATCH 7/7] bsc1214855: volume: use AtomicWriteFile to save volume
options
If the system (or Docker) crashes while saivng the volume options, on
restart the daemon will error out when trying to read the options file
because it doesn't contain valid JSON.
In such a crash scenario, the new volume will be treated as though it
has the default options configuration. This is not ideal, but volumes
created on very old Docker versions (pre-1.11[1], circa 2016) do not
have opts.json and so doing some kind of cleanup when loading the volume
store (even if we take care to only delete empty volumes) could delete
existing volumes carried over from very old Docker versions that users
would not expect to disappear.
Ultimately, if a user creates a volume and the system crashes, a volume
that has the wrong config is better than Docker not being able to start.
[1]: commit b05b2370757d ("Support mount opts for `local` volume driver")
SUSE-Bugs: https://bugzilla.suse.com/show_bug.cgi?id=1214855
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
---
volume/local/local.go | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/volume/local/local.go b/volume/local/local.go
index 6e96aeea4189..4412f34a3da9 100644
--- a/volume/local/local.go
+++ b/volume/local/local.go
@@ -17,6 +17,7 @@ import (
"github.com/docker/docker/daemon/names"
"github.com/docker/docker/errdefs"
"github.com/docker/docker/pkg/idtools"
+ "github.com/docker/docker/pkg/ioutils"
"github.com/docker/docker/quota"
"github.com/docker/docker/volume"
"github.com/pkg/errors"
@@ -388,7 +389,7 @@ func (v *localVolume) saveOpts() error {
if err != nil {
return err
}
- err = os.WriteFile(filepath.Join(v.rootPath, "opts.json"), b, 0o600)
+ err = ioutils.AtomicWriteFile(filepath.Join(v.rootPath, "opts.json"), b, 0o600)
if err != nil {
return errdefs.System(errors.Wrap(err, "error while persisting volume options"))
}
--
2.45.2

View File

@ -3,26 +3,18 @@
<param name="url">https://github.com/moby/moby.git</param>
<param name="scm">git</param>
<param name="exclude">.git</param>
<param name="versionformat">27.4.1_ce_%h</param>
<param name="revision">v27.4.1</param>
<param name="versionformat">26.1.5_ce_%h</param>
<param name="revision">v26.1.5</param>
<param name="filename">docker</param>
</service>
<service name="tar_scm" mode="manual">
<param name="url">https://github.com/docker/cli.git</param>
<param name="scm">git</param>
<param name="exclude">.git</param>
<param name="versionformat">27.4.1_ce</param>
<param name="revision">v27.4.1</param>
<param name="versionformat">26.1.5_ce</param>
<param name="revision">v26.1.5</param>
<param name="filename">docker-cli</param>
</service>
<service name="tar_scm" mode="manual">
<param name="url">https://github.com/docker/buildx.git</param>
<param name="scm">git</param>
<param name="exclude">.git</param>
<param name="versionformat">0.19.3</param>
<param name="revision">v0.19.3</param>
<param name="filename">docker-buildx</param>
</service>
<service name="recompress" mode="manual">
<param name="file">docker-*.tar</param>
<param name="compression">xz</param>

File diff suppressed because it is too large Load Diff

BIN
docker-26.1.5_ce_411e817ddf71.tar.xz (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:73a38f03a8fe7f3c96f976fe776dfed2a46331735f7c0d5e7871a4afedd59325
size 10076932

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e6efae9f26c3d94c2f73aa22197aa1b7e97c1c81bc73ac5e38f165753373bf0a
size 6480184

BIN
docker-cli-26.1.5_ce.tar.xz (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:fe4d69790c4d21affd64d9b81ec5323f9f23153f7b0856e274ebd675058f6488
size 4079044

View File

@ -1,291 +0,0 @@
#!/bin/bash
# docker-integration: run Docker's integration tests
# Copyright (C) 2024 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -Eeuo pipefail
TESTDIR=/usr/src/docker-test
TEST_SRCDIR="$TESTDIR/src"
TEST_BINDIR="$TESTDIR/bin"
TMPROOT="$(mktemp --tmpdir -d docker-integration-tmpdir.XXXXXX)"
TMPDIR="$TMPROOT/tmp"
DEST="$TMPROOT/dest"
mkdir -p "$TMPDIR" "$TEST_BINDIR" "$DEST"
chmod 1777 "$TMPDIR"
chmod 777 "$TMPROOT"
function usage() {
cat >&2 <<-EOF
docker-integration.sh [-Av] [-r TestName] [-t timeout] [<test-suites>...]
Arguments:
-A
Run all tests (do not fail on first suite failure).
-v
Run tests in verbose mode (go test -v).
-r
Only run tests that match the given regular expression (go test -run).
-t <timeout=$timeout>
Set the per-suite timeout to <timeout> (go test -timeout).
<test-suites>...
Only run the given test suites in /usr/src/docker-test. The
default is to run all test suites
Examples:
Run the build and network integration tests with a 60 minute timeout:
./docker-integration.sh -t 60m integration/build integration/network
Run all of the tests in verbose mode with a 6 hour timeout:
./docker-integration.sh -Av -t 360m
This script is maintained by openSUSE in the Virtualization:containers
project, and is only intended to be used by openSUSE developers.
EOF
exit "${1:-1}"
}
fail_fast=1
verbose=
filter=
timeout=20m
while getopts "Ahr:t:v" opt; do
case "$opt" in
A)
fail_fast=
;;
v)
verbose=1
;;
r)
filter="$OPTARG"
;;
t)
timeout="$OPTARG"
;;
h)
usage 0
;;
:)
echo "Missing argument: -$OPTARG" >&2
usage 1
;;
\?)
echo "Invalid option: -$OPTARG" >&2
usage 1
;;
esac
done
pushd "$TEST_SRCDIR"
if [ "$OPTIND" -le "$#" ]; then
SUITES=("${@:$OPTIND:$(($#+1))}")
else
readarray -t SUITES <<<"$(find . -type f -name test.main -printf "%h\n")"
fi
echo "Planning to run suites {${SUITES[@]}}."
# Download the frozen images.
if ! [ -d /docker-frozen-images ]; then
# TODO: Get the hashes from /usr/src/docker-test/Dockerfile...
contrib/download-frozen-image-v2.sh "$TMPDIR/docker-frozen-images" \
busybox:latest@sha256:95cf004f559831017cdf4628aaf1bb30133677be8702a8c5f2994629f637a209 \
busybox:glibc@sha256:1f81263701cddf6402afe9f33fca0266d9fff379e59b1748f33d3072da71ee85 \
debian:bookworm-slim@sha256:2bc5c236e9b262645a323e9088dfa3bb1ecb16cc75811daf40a23a824d665be9 \
hello-world:latest@sha256:d58e752213a51785838f9eed2b7a498ffa1cb3aa7f946dda11af39286c3db9a9 \
arm32v7/hello-world:latest@sha256:50b8560ad574c779908da71f7ce370c0a2471c098d44d1c8f6b513c5a55eeeb1
sudo cp -r "$TMPDIR/docker-frozen-images" /
fi
# Create binaries in $TEST_BINDIR.
if ! [ -e "$TEST_BINDIR/docker-basic-plugin" ]; then
(
pushd "$TEST_SRCDIR/testutil/fixtures/plugin/basic"
go mod init docker-basic-plugin
go build -o "$TEST_BINDIR/docker-basic-plugin" .
)
fi
if ! [ -e "$TEST_BINDIR/registry-v2" ]; then
# The v2.x tags of Docker registry don't use go.mod, and pre-date the move
# to github.com/distribution, so we need to create a fake GOPATH with the
# old github.com/docker/distribution import path.
(
export GOPATH="$(mktemp -d -p "$TMPROOT" distribution-build-gopath.XXXXXX)"
pushd "$GOPATH"
git clone \
--depth=1 --branch=v2.8.3 \
https://github.com/distribution/distribution.git \
src/github.com/docker/distribution
pushd src/github.com/docker/distribution
GO111MODULE=off go build -o "$TEST_BINDIR/registry-v2" ./cmd/registry
)
fi
if ! [ -e "$TEST_BINDIR/ctr" ]; then
containerd-ctr --help >/dev/null
ln -sf "$(which containerd-ctr)" "$TEST_BINDIR/ctr"
fi
if ! [ -e "$TEST_BINDIR/docker" ]; then
# The integration-cli tests require a Docker 17.06.2 client (from 2017).
# This is mainly because the tests are all based on the specific output the
# client gives, and some tests fail on modern client versions.
(
export GOPATH="$(mktemp -d -p "$TMPROOT" distribution-build-gopath.XXXXXX)"
pushd "$GOPATH"
# This tag also comes from the time when this was called
# github.com/docker/docker-ce-packaging, so we need to work around this
# by moving the cli component into the right path...
git clone \
--depth=1 --branch=v17.06.2-ce \
https://github.com/docker/cli.git \
src/github.com/docker/docker-ce-packaging
mv \
src/github.com/docker/docker-ce-packaging/components/cli \
src/github.com/docker/cli
pushd src/github.com/docker/cli
GO111MODULE=off go build -o "$TEST_BINDIR/docker" ./cmd/docker
)
fi
# Create an unprivilegeduser account for tests.
if ! ( grep unprivilegeduser /etc/passwd &>/dev/null ); then
useradd --create-home --gid docker unprivilegeduser
fi
# Disable SUSE secrets for tests, as some tests (TestDiff from
# integration/container) will fail if we have secrets injected.
[ -e /etc/docker/suse-secrets-enable ] && \
mv -nv /etc/docker/suse-secrets-enable{,-DISABLED}
sudo systemctl restart docker
# Make sure docker-buildx is disabled.
[ -e /usr/lib/docker/cli-plugins/docker-buildx ] && \
mv -nv /usr/lib/docker/cli-plugins/docker-buildx{,-DISABLED}
# Disable any daemon configurations.
[ -e /etc/docker/daemon.json ] && \
mv -nv /etc/docker/daemon.json{,.DISABLED}
set -x
# In order for< gotest.tools/v3/assert> to parse the source and give us useful
# error messages, we have to create a fake source directory that points at
# $TEST_SRCDIR. This path is replaced with %{docker_builddir} during the
# docker.spec build.
__DOCKER_BUILDIR="@@docker_builddir@@"
DOCKER_BUILDDIR="${DOCKER_BUILDDIR:-$__DOCKER_BUILDIR}"
sudo rm -rvf "$DOCKER_BUILDDIR"
sudo mkdir -p "$(dirname "$DOCKER_BUILDDIR")"
sudo ln -svf "$TEST_SRCDIR" "$DOCKER_BUILDDIR"
# Clean up any old containers/images/networks/volumes before running the tests.
# We need to do this *BEFORE* we set PATH, as the outdated $TEST_BINDIR/docker
# doesn't support some of these commands.
docker container prune -f
docker image prune -af
#docker buildx prune -af
docker network prune -f
docker volume prune -af
[ -z "$(docker plugin ls -q)" ] || docker plugin ls -q | xargs docker plugin rm -f
docker system prune -af
export DOCKERFILE="$TEST_SRCDIR/Dockerfile"
export TMPDIR="$TMPDIR"
export TEMP="$TMPDIR"
export HOME="$TMPDIR/fake-home"
export DEST="$TEST_SRCDIR/bundles"
export ABS_DEST="$DEST"
export PATH="$TEST_BINDIR:$PATH"
export TZ=UTC
export DOCKER_INTEGRATION_DAEMON_DEST="$ABS_DEST"
export DOCKER_HOST=unix:///run/docker.sock
export DOCKER_GRAPHDRIVER=overlay2
export DOCKER_USERLANDPROXY=true
export DOCKER_REMAP_ROOT="${DOCKER_REMAP_ROOT:-}"
export DOCKER_TMPDIR="$TMPDIR"
export DOCKER_SUSE_SECRETS_ENABLE=0
set +x
# Make sure that we have a dummy "destination" directory for tests.
rm -rf "$DOCKER_INTEGRATION_DAEMON_DEST"
mkdir -p "$DOCKER_INTEGRATION_DAEMON_DEST"
# Install the emptyfs images.
sh ./hack/make/.build-empty-images
ls -la "$TMPROOT"
success=0
failed_suites=()
for suite_name in "${SUITES[@]}"; do
suite_name="${suite_name#*./}"
pushd "$TEST_SRCDIR/$suite_name"
test_flags=()
[ -n "$verbose" ] && test_flags+=("-test.v")
[ -n "$filter" ] && test_flags+=("-test.run" "$filter")
if [[ "$suite_name" == "integration-cli" ]]; then
# We need to disable docker-buildx for the integration-cli tests
# because otherwise the "docker build" command will use the wrong
# builder and the output won't match what the tests expect.
timeout=360m
fi
test_flags+=("-test.timeout" "$timeout")
echo "Running suite $suite_name (${test_flags[@]}) [success=$success fail=${#failed_suites[@]}]"
set -x +e
sudo -E HOME="$HOME" TMPDIR="$TMPDIR" PATH="$PATH" \
./test.main "${test_flags[@]}"
err="$?"
if (( $err != 0 )); then
[ -z "$fail_fast" ] || exit "$err"
failed_suites+=("$suite_name")
else
(( success++ ))
fi
set +x -e
popd
done
[ -e /usr/lib/docker/cli-plugins/docker-buildx-DISABLED ] && \
mv -nv /usr/lib/docker/cli-plugins/docker-buildx{-DISABLED,}
[ -e /etc/docker/suse-secrets-enable-DISABLED ] && \
mv -nv /etc/docker/suse-secrets-enable{-DISABLED,}
[ -e /etc/docker/daemon.json.DISABLED ] && \
mv -nv /etc/docker/daemon.json{.DISABLED,}
echo "Suite results: $success success(es) ${#failed_suites[@]} failure(s)."
if (( ${#failed_suites[@]} > 0 )); then
echo "Failed suites:"
printf " - %s\n" "${failed_suites[@]}"
exit 1
fi

View File

@ -1,7 +1,2 @@
addFilter("^docker-(stable-)?bash-completion.noarch: (E|W): non-executable-script /usr/share/bash-completion/completions/docker")
addFilter("^docker-(stable-)?zsh-completion.noarch: W: non-conffile-in-etc /etc/zsh_completion.d/_docker")
# The docker-integration-tests-devel package contains all of the source code of
# Docker, which causes a bunch of warnings. Note that
# docker-integration-tests-devel is used internally and isn't actually shipped.
addFilter("^docker-(stable-)?integration-tests-devel\..*: (E|W): .*")
addFilter("^docker-bash-completion.noarch: (E|W): non-executable-script /usr/share/bash-completion/completions/docker")
addFilter("^docker-zsh-completion.noarch: W: non-conffile-in-etc /etc/zsh_completion.d/_docker")

View File

@ -1,126 +1,3 @@
-------------------------------------------------------------------
Wed Dec 18 12:29:07 UTC 2024 - Aleksa Sarai <asarai@suse.com>
- Update to Docker 27.4.1-ce. See upstream changelog online at
<https://docs.docker.com/engine/release-notes/27/#2741>
- Rebase patches:
* 0001-SECRETS-daemon-allow-directory-creation-in-run-secre.patch
* 0002-SECRETS-SUSE-implement-SUSE-container-secrets.patch
* 0003-BUILD-SLE12-revert-graphdriver-btrfs-use-kernel-UAPI.patch
* 0004-bsc1073877-apparmor-clobber-docker-default-profile-o.patch
* 0005-SLE12-revert-apparmor-remove-version-conditionals-fr.patch
* cli-0001-docs-include-required-tools-in-source-tree.patch
-------------------------------------------------------------------
Tue Dec 17 13:20:39 UTC 2024 - Aleksa Sarai <asarai@suse.com>
- Update to docker-buildx 0.19.3. See upstream changelog online at
<https://github.com/docker/buildx/releases/tag/v0.19.3>
-------------------------------------------------------------------
Fri Dec 13 06:12:25 UTC 2024 - Aleksa Sarai <asarai@suse.com>
- Update to Docker 27.4.0-ce. See upstream changelog online at
<https://docs.docker.com/engine/release-notes/27/#274>
- Rebase patches:
* 0001-SECRETS-daemon-allow-directory-creation-in-run-secre.patch
* 0002-SECRETS-SUSE-implement-SUSE-container-secrets.patch
* 0003-BUILD-SLE12-revert-graphdriver-btrfs-use-kernel-UAPI.patch
* 0004-bsc1073877-apparmor-clobber-docker-default-profile-o.patch
* 0005-SLE12-revert-apparmor-remove-version-conditionals-fr.patch
* cli-0001-docs-include-required-tools-in-source-tree.patch
- Remove upstreamed patches:
- 0006-bsc1221916-update-to-patched-buildkit-version-to-fix.patch
- 0007-bsc1214855-volume-use-AtomicWriteFile-to-save-volume.patch
-------------------------------------------------------------------
Wed Dec 11 10:14:56 UTC 2024 - Aleksa Sarai <asarai@suse.com>
- Update docker-buildx to v0.19.2. See upstream changelog online at
<https://github.com/docker/buildx/releases/tag/v0.19.2>.
Some notable changelogs from the last update:
* <https://github.com/docker/buildx/releases/tag/v0.19.0>
* <https://github.com/docker/buildx/releases/tag/v0.18.0>
- Update to Go 1.22.
-------------------------------------------------------------------
Wed Dec 11 05:39:42 UTC 2024 - Aleksa Sarai <asarai@suse.com>
- Add a new toggle file /etc/docker/suse-secrets-enable which allows users to
disable the SUSEConnect integration with Docker (which creates special mounts
in /run/secrets to allow container-suseconnect to authenticate containers
with registries on registered hosts). bsc#1231348 bsc#1232999
In order to disable these mounts, just do
echo 0 > /etc/docker/suse-secrets-enable
and restart Docker. In order to re-enable them, just do
echo 1 > /etc/docker/suse-secrets-enable
and restart Docker. Docker will output information on startup to tell you
whether the SUSE secrets feature is enabled or not.
* 0002-SECRETS-SUSE-implement-SUSE-container-secrets.patch
-------------------------------------------------------------------
Wed Nov 27 12:10:42 UTC 2024 - Aleksa Sarai <asarai@suse.com>
- Disable docker-buildx builds for SLES. It turns out that build containers
with docker-buildx don't currently get the SUSE secrets mounts applied,
meaning that container-suseconnect doesn't work when building images.
bsc#1233819
-------------------------------------------------------------------
Wed Nov 20 05:34:38 UTC 2024 - Aleksa Sarai <asarai@suse.com>
- Add docker-integration-tests-devel subpackage for building and running the
upstream Docker integration tests on machines to test that Docker works
properly. Users should not install this package.
- docker-rpmlintrc updated to include allow-list for all of the integration
tests package, since it contains a bunch of stuff that wouldn't normally be
allowed.
-------------------------------------------------------------------
Tue Nov 12 06:34:28 UTC 2024 - Aleksa Sarai <asarai@suse.com>
- Remove DOCKER_NETWORK_OPTS from docker.service. This was removed from
sysconfig a long time ago, and apparently this causes issues with systemd in
some cases.
-------------------------------------------------------------------
Wed Oct 16 22:24:52 UTC 2024 - Aleksa Sarai <asarai@suse.com>
- Further merge docker and docker-stable specfiles to minimise the differences.
The main thing is that we now include both halves of the
Conflicts/Provides/Obsoletes dance in both specfiles.
-------------------------------------------------------------------
Wed Oct 16 05:37:14 UTC 2024 - Aleksa Sarai <asarai@suse.com>
- Update to docker-buildx v0.17.1 to match standalone docker-buildx package we
are replacing. See upstream changelog online at
<https://github.com/docker/buildx/releases/tag/v0.17.1>
-------------------------------------------------------------------
Wed Sep 18 13:47:45 UTC 2024 - Ana Guerrero <ana.guerrero@suse.com>
- Add %{_sysconfdir}/audit/rules.d to filelist.
-------------------------------------------------------------------
Sat Sep 7 06:07:50 UTC 2024 - Aleksa Sarai <asarai@suse.com>
- Mark docker-buildx as required since classic "docker build" has been
deprecated since Docker 23.0. bsc#1230331
- Import docker-buildx v0.16.2 as a subpackage. Previously this was a separate
package, but with docker-stable it will be necessary to maintain the packages
together and it makes more sense to have them live in the same OBS package.
bsc#1230333
- Make some minor name macro updates to help with the docker-stable package
fork.
-------------------------------------------------------------------
Wed Jul 31 05:28:09 UTC 2024 - Aleksa Sarai <asarai@suse.com>
@ -150,8 +27,8 @@ Wed Jul 31 04:58:15 UTC 2024 - Aleksa Sarai <asarai@suse.com>
<https://docs.docker.com/engine/release-notes/25.0/#2506>
- This update includes fixes for:
* CVE-2024-41110. bsc#1228324
* CVE-2023-47108. bsc#1217070 bsc#1229806
* CVE-2023-45142. bsc#1228553 bsc#1229806
* CVE-2023-47108. bsc#1217070
* CVE-2023-45142. bsc#1228553
- Rebase patches:
* 0001-SECRETS-daemon-allow-directory-creation-in-run-secre.patch
* 0002-SECRETS-SUSE-implement-SUSE-container-secrets.patch
@ -221,7 +98,6 @@ Mon Mar 25 12:34:56 UTC 2024 - Aleksa Sarai <asarai@suse.com>
- Update to Docker 25.0.5-ce. See upstream changelog online at
<https://docs.docker.com/engine/release-notes/25.0/#2505> bsc#1223409
bsc#1234089 CVE-2024-29018
- Rebase patches:
* 0001-SECRETS-daemon-allow-directory-creation-in-run-secre.patch
* 0002-SECRETS-SUSE-implement-SUSE-container-secrets.patch

View File

@ -16,7 +16,7 @@ EnvironmentFile=/etc/sysconfig/docker
# enabled by default because enabling socket activation means that on boot your
# containers won't start until someone tries to administer the Docker daemon.
Type=notify
ExecStart=/usr/bin/dockerd --add-runtime oci=/usr/sbin/runc $DOCKER_OPTS
ExecStart=/usr/bin/dockerd --add-runtime oci=/usr/sbin/runc $DOCKER_NETWORK_OPTIONS $DOCKER_OPTS
ExecReload=/bin/kill -s HUP $MAINPID
# Having non-zero Limit*s causes performance problems due to accounting overhead

View File

@ -1,7 +1,7 @@
#
# spec file for package docker
#
# Copyright (c) 2024 SUSE LLC
# Copyright (c) 2023 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@ -16,69 +16,38 @@
#
# nodebuginfo
%bcond_without apparmor
# This subpackage is only used for testing by developers, and shouldn't be
# built for actual users.
%bcond_with integration_tests
%if 0%{?is_opensuse} == 0
# SUSEConnect support ("SUSE secrets") only makes sense for SLES hosts.
%bcond_without suseconnect
# There is currently a known bug between buildx and SUSE secrets, so we don't
# package docker-buildx for SLES. bsc#1233819
%bcond_with buildx
%else
%bcond_with suseconnect
%bcond_without buildx
%endif
# The flavour is defined with a macro to try to keep docker and docker-stable
# as similar as possible, to make maintenance a little easier.
%define flavour %{nil}
# Where important update information will be stored, such that an administrator
# is guaranteed to see the relevant warning.
%define update_messages %{_localstatedir}/adm/update-messages/%{name}-%{version}-%{release}
# Test binaries.
%define testdir /usr/src/docker-test
#Compat macro for new _fillupdir macro introduced in Nov 2017
%if ! %{defined _fillupdir}
%define _fillupdir /var/adm/fillup-templates
%endif
# MANUAL: This needs to be updated with every docker update.
%define docker_real_version 27.4.1
%define docker_git_version c710b88579fc
%define docker_version %{docker_real_version}_ce
# This "nice version" is so that docker --version gives a result that can be
# parsed by other people. boo#1182476
%define docker_nice_version %{docker_real_version}-ce
%if %{with buildx}
# MANUAL: This needs to be updated with every docker-buildx update.
%define buildx_version 0.19.3
%endif
# Used when generating the "build" information for Docker version. The value of
# git_commit_epoch is unused here (we use SOURCE_DATE_EPOCH, which rpm
# helpfully injects into our build environment from the changelog). If you want
# to generate a new git_commit_epoch, use this:
# $ date --date="$(git show --format=fuller --date=iso $COMMIT_ID | grep -oP '(?<=^CommitDate: ).*')" '+%s'
%define git_commit_epoch 1734439831
%define real_version 26.1.5
%define git_version 411e817ddf71
%define git_commit_epoch 1721763388
Name: docker%{flavour}
Version: %{docker_version}
Name: docker
Version: %{real_version}_ce
# This "nice version" is so that docker --version gives a result that can be
# parsed by other people. boo#1182476
%define nice_version %{real_version}-ce
Release: 0
Summary: The Moby-project Linux container runtime
License: Apache-2.0
Group: System/Management
URL: http://www.docker.io
Source: docker-%{docker_version}_%{docker_git_version}.tar.xz
Source1: docker-cli-%{docker_version}.tar.xz
Source: %{name}-%{version}_%{git_version}.tar.xz
Source1: %{name}-cli-%{version}.tar.xz
Source3: docker-rpmlintrc
# TODO: Move these source files to somewhere nicer.
Source100: docker.service
@ -89,8 +58,6 @@ Source130: README_SUSE.md
Source140: docker-audit.rules
Source150: docker-daemon.json
Source160: docker.sysusers
# docker-integration-tests-devel
Source900: docker-integration.sh
# NOTE: All of these patches are maintained in <https://github.com/suse/docker>
# in the suse-v<version> branch. Make sure you update the patches in that
# branch and then git-format-patch the patch here.
@ -104,6 +71,11 @@ Patch200: 0003-BUILD-SLE12-revert-graphdriver-btrfs-use-kernel-UAPI.patch
Patch201: 0004-bsc1073877-apparmor-clobber-docker-default-profile-o.patch
# UPSTREAM: Revert of upstream patches to make apparmor work on SLE 12.
Patch202: 0005-SLE12-revert-apparmor-remove-version-conditionals-fr.patch
# UPSTREAM: Backport of <https://github.com/moby/buildkit/pull/4896> and
# <https://github.com/moby/buildkit/pull/5060>.
Patch203: 0006-bsc1221916-update-to-patched-buildkit-version-to-fix.patch
# UPSTREAM: Backport of <https://github.com/moby/moby/pull/48034>.
Patch204: 0007-bsc1214855-volume-use-AtomicWriteFile-to-save-volume.patch
# UPSTREAM: Backport of <https://github.com/docker/cli/pull/4228>.
Patch900: cli-0001-docs-include-required-tools-in-source-tree.patch
BuildRequires: audit
@ -114,18 +86,18 @@ BuildRequires: fdupes
%if %{with apparmor}
BuildRequires: libapparmor-devel
%endif
BuildRequires: fish
BuildRequires: go-go-md2man
BuildRequires: libbtrfs-devel >= 3.8
BuildRequires: libseccomp-devel >= 2.2
BuildRequires: libtool
BuildRequires: linux-glibc-devel
BuildRequires: procps
BuildRequires: sqlite3-devel
BuildRequires: sysuser-tools
BuildRequires: zsh
BuildRequires: golang(API) = 1.22
BuildRequires: fish
BuildRequires: go-go-md2man
BuildRequires: pkgconfig(libsystemd)
BuildRequires: sysuser-tools
BuildRequires: golang(API) = 1.21
%if %{with apparmor}
%if 0%{?sle_version} >= 150000
# This conditional only works on rpm>=4.13, which SLE 12 doesn't have. But we
@ -147,15 +119,7 @@ Requires: ca-certificates-mozilla
# The docker-proxy binary used to be in a separate package. We obsolete it,
# since now docker-proxy is maintained as part of this package.
Obsoletes: docker-libnetwork < 0.7.0.2
Provides: docker-libnetwork = 0.7.0.2.%{docker_version}
# docker-stable cannot be used alongside docker.
%if "%{name}" == "docker-stable"
Provides: docker = %{docker_version}
Obsoletes: docker < %{docker_version}
Conflicts: docker
%else
Conflicts: docker-stable
%endif
Provides: docker-libnetwork = 0.7.0.2.%{version}
# Required to actually run containers. We require the minimum version that is
# pinned by Docker, but in order to avoid headaches we allow for updates.
Requires: runc >= 1.1.9
@ -170,11 +134,6 @@ Requires: iptables >= 1.4
Requires: procps
Requires: tar >= 1.26
Requires: xz >= 4.9
%if %{with buildx}
# Standard docker-build is deprecated, so require docker-buildx to avoid users
# hitting bugs that have long since been fixed by docker-buildx. bsc#1230331
Requires: %{name}-buildx
%endif
%?sysusers_requires
Requires(post): %fillup_prereq
Requires(post): udev
@ -183,8 +142,10 @@ Requires(post): shadow
# configured to use lvm and the user doesn't explicitly provide a
# different storage-driver than devicemapper
Recommends: lvm2 >= 2.2.89
Recommends: %{name}-rootless-extras
Recommends: git-core >= 1.7
# Required for "docker buildx" support.
Recommends: %{name}-buildx
Recommends: %{name}-rootless-extras
ExcludeArch: s390 ppc
%description
@ -196,95 +157,27 @@ Docker is a great building block for automating distributed systems: large-scale
web deployments, database clusters, continuous deployment systems, private PaaS,
service-oriented architectures, etc.
%if %{with buildx}
%package buildx
Version: %{buildx_version}
Summary: Docker CLI plugin for extended build capabilities with BuildKit
License: Apache-2.0
URL: https://github.com/docker/buildx
Source500: docker-buildx-%{buildx_version}.tar.xz
Group: System/Management
Requires: %{name} >= 19.03.0_ce
# docker-stable cannot be used alongside docker.
%if "%{name}" == "docker-stable"
Provides: docker-buildx = %{buildx_version}
Obsoletes: docker-buildx < %{buildx_version}
Conflicts: docker-buildx
%else
Conflicts: docker-stable-buildx
%endif
%description buildx
buildx is a Docker CLI plugin for extended build capabilities with BuildKit.
Key features:
- Familiar UI from docker build
- Full BuildKit capabilities with container driver
- Multiple builder instance support
- Multi-node builds for cross-platform images
- Compose build support
- High-level build constructs (bake)
- In-container driver support (both Docker and Kubernetes)
%endif
%package rootless-extras
Summary: Rootless support for Docker
Group: System/Management
Requires: %{name} = %{docker_version}
Requires: %{name} = %{version}
Requires: slirp4netns >= 0.4
Requires: fuse-overlayfs >= 0.7
Requires: rootlesskit
Requires: slirp4netns >= 0.4
BuildArch: noarch
# docker-stable cannot be used alongside docker.
%if "%{name}" == "docker-stable"
Provides: docker-rootless-extras = %{docker_version}
Obsoletes: docker-rootless-extras < %{docker_version}
Conflicts: docker-rootless-extras
%else
Conflicts: docker-stable-rootless-extras
%endif
%description rootless-extras
Rootless support for Docker.
Use dockerd-rootless.sh to run the daemon.
Use dockerd-rootless-setuptool.sh to setup systemd for dockerd-rootless.sh.
%if %{with integration_tests}
%package integration-tests-devel
Summary: Rootless support for Docker
Group: TestSuite
Requires: %{name} = %{docker_version}
Requires: containerd-ctr
Requires: curl
Requires: gcc
Requires: git
Requires: glibc-devel-static
Requires: go
Requires: jq
Requires: libcap-progs
%description integration-tests-devel
Integration testing binaries for Docker.
THIS PACKAGE SHOULD NOT BE INSTALLED BY END-USERS, IT IS ONLY INTENDED FOR
INTERNAL DEVELOPMENT OF THE DOCKER PACKAGE FOR (OPEN)SUSE.
%endif
%package bash-completion
Summary: Bash Completion for %{name}
Group: System/Shells
Requires: %{name} = %{docker_version}
Requires: %{name} = %{version}
Requires: bash-completion
Supplements: packageand(%{name}:bash-completion)
BuildArch: noarch
# docker-stable cannot be used alongside docker.
%if "%{name}" == "docker-stable"
Provides: docker-bash-completion = %{docker_version}
Obsoletes: docker-bash-completion < %{docker_version}
Conflicts: docker-bash-completion
%else
Conflicts: docker-stable-bash-completion
%endif
%description bash-completion
Bash command line completion support for %{name}.
@ -292,18 +185,10 @@ Bash command line completion support for %{name}.
%package zsh-completion
Summary: Zsh Completion for %{name}
Group: System/Shells
Requires: %{name} = %{docker_version}
Requires: %{name} = %{version}
Requires: zsh
Supplements: packageand(%{name}:zsh)
BuildArch: noarch
# docker-stable cannot be used alongside docker.
%if "%{name}" == "docker-stable"
Provides: docker-zsh-completion = %{docker_version}
Obsoletes: docker-zsh-completion < %{docker_version}
Conflicts: docker-zsh-completion
%else
Conflicts: docker-stable-zsh-completion
%endif
%description zsh-completion
Zsh command line completion support for %{name}.
@ -311,45 +196,30 @@ Zsh command line completion support for %{name}.
%package fish-completion
Summary: Fish completion for %{name}
Group: System/Shells
Requires: %{name} = %{docker_version}
Requires: %{name} = %{version}
Requires: fish
Supplements: packageand(%{name}:fish)
BuildArch: noarch
# docker-stable cannot be used alongside docker.
%if "%{name}" == "docker-stable"
Provides: docker-fish-completion = %{docker_version}
Obsoletes: docker-fish-completion < %{docker_version}
Conflicts: docker-fish-completion
%else
Conflicts: docker-stable-fish-completion
%endif
%description fish-completion
Fish command line completion support for %{name}.
%prep
# docker-cli
%define cli_builddir %{_builddir}/docker-cli-%{docker_version}
%setup -q -T -b 1 -n docker-cli-%{docker_version}
%define cli_builddir %{_builddir}/%{name}-cli-%{version}
%setup -q -T -b 1 -n %{name}-cli-%{version}
[ "%{cli_builddir}" = "$PWD" ]
# offline manpages
%patch -P900 -p1
%if %{with buildx}
# docker-buildx
%define buildx_builddir %{_builddir}/docker-buildx-%{buildx_version}
%setup -q -T -b 500 -n docker-buildx-%{buildx_version}
[ "%{buildx_builddir}" = "$PWD" ]
%endif
# docker
%define docker_builddir %{_builddir}/docker-%{docker_version}_%{docker_git_version}
%setup -q -n docker-%{docker_version}_%{docker_git_version}
%define docker_builddir %{_builddir}/%{name}-%{version}_%{git_version}
%setup -q -n %{name}-%{version}_%{git_version}
[ "%{docker_builddir}" = "$PWD" ]
# README_SUSE.md for documentation.
cp %{SOURCE130} .
%if %{with suseconnect}
%if 0%{?is_opensuse} == 0
# PATCH-SUSE: Secrets patches.
%patch -P100 -p1
%patch -P101 -p1
@ -362,9 +232,13 @@ cp %{SOURCE130} .
%patch -P201 -p1
# Solves apparmor issues on SLE-12, but okay for newer SLE versions too.
%patch -P202 -p1
# bsc#1221916
%patch -P203 -p1
# bsc#1214855
%patch -P204 -p1
%build
%sysusers_generate_pre %{SOURCE160} %{name} docker.conf
%sysusers_generate_pre %{SOURCE160} %{name} %{name}.conf
BUILDTAGS="exclude_graphdriver_aufs apparmor selinux seccomp pkcs11"
%if 0%{?sle_version} == 120000
@ -381,9 +255,9 @@ export BUILDFLAGS="-buildmode=pie"
# Specify all of the versioning information. We use SOURCE_DATE_EPOCH if it's
# been injected by rpmbuild, otherwise we use the hardcoded git_commit_epoch
# generated above. boo#1064781
export VERSION="%{docker_nice_version}"
export DOCKER_GITCOMMIT="%{docker_git_version}"
export GITCOMMIT="%{docker_git_version}"
export VERSION="%{nice_version}"
export DOCKER_GITCOMMIT="%{git_version}"
export GITCOMMIT="%{git_version}"
export SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:-%{git_commit_epoch}}"
export BUILDTIME="$(date -u -d "@$SOURCE_DATE_EPOCH" --rfc-3339 ns 2>/dev/null | sed -e 's/ /T/')"
@ -393,24 +267,9 @@ export BUILDTIME="$(date -u -d "@$SOURCE_DATE_EPOCH" --rfc-3339 ns 2>/dev/null |
pushd "%{docker_builddir}"
# use go module for build
cp {vendor,go}.mod
cp {vendor,go}.sum
ln -s {vendor,go}.mod
ln -s {vendor,go}.sum
./hack/make.sh dynbinary
%if %{with integration_tests}
# build test binaries for integration tests
readarray -t integration_dirs \
<<<"$(go list -test -f '{{- if ne .ForTest "" -}}{{- .Dir -}}{{- end -}}' ./integration/... ./integration-cli/...)"
for dir in "${integration_dirs[@]}"
do
pushd "$dir"
go test -c -buildmode=pie -tags "$BUILDTAGS" -o test.main .
popd
done
# Update __DOCKER_BUILDIR in the integration testing script.
sed -i 's|^__DOCKER_BUILDIR=.*|__DOCKER_BUILDIR=%{docker_builddir}|g' "%{SOURCE900}"
%endif
popd
###################
@ -419,26 +278,11 @@ popd
pushd "%{cli_builddir}"
# use go module for build
cp {vendor,go}.mod
cp {vendor,go}.sum
ln -s {vendor,go}.mod
ln -s {vendor,go}.sum
make DISABLE_WARN_OUTSIDE_CONTAINER=1 dynbinary manpages
popd
%if %{with buildx}
###################
## DOCKER BUILDX ##
###################
pushd "%{buildx_builddir}"
make \
CGO_ENABLED=1 \
VERSION="%{buildx_version}" \
REVISION="v%{buildx_version}" \
GO_EXTRA_FLAGS="-buildmode=pie" \
build
popd
%endif
%install
install -Dd -m0755 \
%{buildroot}%{_sysconfdir}/init.d \
@ -452,37 +296,29 @@ install -D -m0755 %{docker_builddir}/bundles/dynbinary-daemon/docker-proxy %{bui
# cli-plugins/
install -d %{buildroot}/usr/lib/docker/cli-plugins
%if %{with buildx}
# buildx plugin
install -D -m0755 %{buildx_builddir}/bin/build/docker-buildx %{buildroot}/usr/lib/docker/cli-plugins/docker-buildx
%endif
# /var/lib/docker
install -d %{buildroot}/%{_localstatedir}/lib/docker
# daemon.json config file
install -D -m0644 %{SOURCE150} %{buildroot}%{_sysconfdir}/docker/daemon.json
%if %{with suseconnect}
# SUSE-specific config file
echo 1 > %{buildroot}%{_sysconfdir}/docker/suse-secrets-enable
%endif
# docker cli
install -D -m0755 %{cli_builddir}/build/docker %{buildroot}/%{_bindir}/docker
install -D -m0644 %{cli_builddir}/contrib/completion/bash/docker "%{buildroot}%{_datarootdir}/bash-completion/completions/docker"
install -D -m0644 %{cli_builddir}/contrib/completion/zsh/_docker "%{buildroot}%{_sysconfdir}/zsh_completion.d/_docker"
install -D -m0644 %{cli_builddir}/contrib/completion/fish/docker.fish "%{buildroot}/%{_datadir}/fish/vendor_completions.d/docker.fish"
install -D -m0644 %{cli_builddir}/contrib/completion/bash/docker "%{buildroot}%{_datarootdir}/bash-completion/completions/%{name}"
install -D -m0644 %{cli_builddir}/contrib/completion/zsh/_docker "%{buildroot}%{_sysconfdir}/zsh_completion.d/_%{name}"
install -D -m0644 %{cli_builddir}/contrib/completion/fish/docker.fish "%{buildroot}/%{_datadir}/fish/vendor_completions.d/%{name}.fish"
# systemd service
install -D -m0644 %{SOURCE100} %{buildroot}%{_unitdir}/docker.service
install -D -m0644 %{SOURCE101} %{buildroot}%{_unitdir}/docker.socket
install -D -m0644 %{SOURCE100} %{buildroot}%{_unitdir}/%{name}.service
install -D -m0644 %{SOURCE101} %{buildroot}%{_unitdir}/%{name}.socket
ln -sf service %{buildroot}%{_sbindir}/rcdocker
# udev rules that prevents dolphin to show all docker devices and slows down
# upstream report https://bugs.kde.org/show_bug.cgi?id=329930
install -D -m0644 %{SOURCE110} %{buildroot}%{_udevrulesdir}/80-docker.rules
install -D -m0644 %{SOURCE110} %{buildroot}%{_udevrulesdir}/80-%{name}.rules
# audit rules
install -D -m0640 %{SOURCE140} %{buildroot}%{_sysconfdir}/audit/rules.d/docker.rules
install -D -m0640 %{SOURCE140} %{buildroot}%{_sysconfdir}/audit/rules.d/%{name}.rules
# sysconfig file
install -D -m0644 %{SOURCE120} %{buildroot}%{_fillupdir}/sysconfig.docker
@ -496,22 +332,12 @@ install -d %{buildroot}%{_mandir}/man8
install -p -m0644 %{cli_builddir}/man/man8/*.8 %{buildroot}%{_mandir}/man8
# sysusers.d
install -D -m0644 %{SOURCE160} %{buildroot}%{_sysusersdir}/docker.conf
install -D -m0644 %{SOURCE160} %{buildroot}%{_sysusersdir}/%{name}.conf
# rootless extras
install -D -p -m 0755 contrib/dockerd-rootless.sh %{buildroot}/%{_bindir}/dockerd-rootless.sh
install -D -p -m 0755 contrib/dockerd-rootless-setuptool.sh %{buildroot}/%{_bindir}/dockerd-rootless-setuptool.sh
%if %{with integration_tests}
# integration tests
install -d %{buildroot}%{testdir}
cp -ar %{docker_builddir} %{buildroot}%{testdir}/src
install -d %{buildroot}%{testdir}/bin
install -D -p -m 0755 %{SOURCE900} %{buildroot}%{testdir}/docker-integration.sh
# remove all of the non-test binaries in bundles/
rm -rfv %{buildroot}%{testdir}/src/bundles/
%endif
%fdupes %{buildroot}
%pre -f %{name}.pre
@ -530,17 +356,17 @@ grep -q '^dockremap:' /etc/subgid || \
usermod -w 100000000-200000000 dockremap &>/dev/null || \
echo "dockremap:100000000:100000001" >>/etc/subgid ||:
%service_add_pre docker.service docker.socket
%service_add_pre %{name}.service %{name}.socket
%post
%service_add_post docker.service docker.socket
%service_add_post %{name}.service %{name}.socket
%{fillup_only -n docker}
%preun
%service_del_preun docker.service docker.socket
%service_del_preun %{name}.service %{name}.socket
%postun
%service_del_postun docker.service docker.socket
%service_del_postun %{name}.service %{name}.socket
%files
%defattr(-,root,root)
@ -555,53 +381,37 @@ grep -q '^dockremap:' /etc/subgid || \
%dir /usr/lib/docker
%dir /usr/lib/docker/cli-plugins
%{_unitdir}/docker.service
%{_unitdir}/docker.socket
%{_sysusersdir}/docker.conf
%{_unitdir}/%{name}.service
%{_unitdir}/%{name}.socket
%{_sysusersdir}/%{name}.conf
%dir %{_sysconfdir}/docker
%config(noreplace) %{_sysconfdir}/docker/daemon.json
%if %{with suseconnect}
%config(noreplace) %{_sysconfdir}/docker/suse-secrets-enable
%endif
%{_fillupdir}/sysconfig.docker
%dir %attr(750,root,root) %{_sysconfdir}/audit/rules.d
%config %{_sysconfdir}/audit/rules.d/docker.rules
%{_udevrulesdir}/80-docker.rules
%config %{_sysconfdir}/audit/rules.d/%{name}.rules
%{_udevrulesdir}/80-%{name}.rules
%{_mandir}/man1/docker-*.1%{ext_man}
%{_mandir}/man1/docker.1%{ext_man}
%{_mandir}/man5/Dockerfile.5%{ext_man}
%{_mandir}/man8/dockerd.8%{ext_man}
%if %{with buildx}
%files buildx
%defattr(-,root,root)
/usr/lib/docker/cli-plugins/docker-buildx
%endif
%files rootless-extras
%defattr(-,root,root)
%{_bindir}/dockerd-rootless.sh
%{_bindir}/dockerd-rootless-setuptool.sh
%if %{with integration_tests}
%files integration-tests-devel
%defattr(-,root,root)
%{testdir}
%endif
%files bash-completion
%defattr(-,root,root)
%{_datarootdir}/bash-completion/completions/docker
%{_datarootdir}/bash-completion/completions/%{name}
%files zsh-completion
%defattr(-,root,root)
%{_sysconfdir}/zsh_completion.d/_docker
%{_sysconfdir}/zsh_completion.d/_%{name}
%files fish-completion
%defattr(-,root,root)
%{_datadir}/fish/vendor_completions.d/docker.fish
%{_datadir}/fish/vendor_completions.d/%{name}.fish
%changelog