diff --git a/Dockerfile b/Dockerfile index 56168a180f..63106487c0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -223,8 +223,7 @@ FROM binary-dummy AS containerd-windows FROM containerd-${TARGETOS} AS containerd FROM base AS golangci_lint -# FIXME: when updating golangci-lint, remove the temporary "nolint" in https://github.com/moby/moby/blob/7860686a8df15eea9def9e6189c6f9eca031bb6f/libnetwork/networkdb/cluster.go#L246 -ARG GOLANGCI_LINT_VERSION=v1.49.0 +ARG GOLANGCI_LINT_VERSION=v1.51.2 RUN --mount=type=cache,target=/root/.cache/go-build \ --mount=type=cache,target=/go/pkg/mod \ GOBIN=/build/ GO111MODULE=on go install "github.com/golangci/golangci-lint/cmd/golangci-lint@${GOLANGCI_LINT_VERSION}" \ diff --git a/daemon/errors.go b/daemon/errors.go index 6ab45f30e3..c77e54598d 100644 --- a/daemon/errors.go +++ b/daemon/errors.go @@ -154,6 +154,17 @@ func translateContainerdStartErr(cmd string, setExitCode func(int), err error) e retErr = startInvalidConfigError(errDesc) } + // Go 1.20 changed the error for attempting to execute a directory from + // syscall.EACCESS to syscall.EISDIR. Unfortunately docker/cli checks + // whether the error message contains syscall.EACCESS.Error() to + // determine whether to exit with code 126 or 125, so we have little + // choice but to fudge the error string. + if contains(errDesc, syscall.EISDIR.Error()) { + errDesc += ": " + syscall.EACCES.Error() + setExitCode(126) + return startInvalidConfigError(errDesc) + } + // attempted to mount a file onto a directory, or a directory onto a file, maybe from user specified bind mounts if contains(errDesc, syscall.ENOTDIR.Error()) { errDesc += ": Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type" diff --git a/daemon/logger/awslogs/cloudwatchlogs_test.go b/daemon/logger/awslogs/cloudwatchlogs_test.go index f28b029452..4473a8ce3b 100644 --- a/daemon/logger/awslogs/cloudwatchlogs_test.go +++ b/daemon/logger/awslogs/cloudwatchlogs_test.go @@ -1428,7 +1428,7 @@ func TestCollectBatchWithDuplicateTimestamps(t *testing.T) { for i := 0; i < times; i++ { line := fmt.Sprintf("%d", i) if i%2 == 0 { - timestamp.Add(1 * time.Nanosecond) + timestamp = timestamp.Add(1 * time.Nanosecond) } stream.Log(&logger.Message{ Line: []byte(line), diff --git a/libnetwork/bitseq/sequence_test.go b/libnetwork/bitseq/sequence_test.go index 6ba671ce62..789043466b 100644 --- a/libnetwork/bitseq/sequence_test.go +++ b/libnetwork/bitseq/sequence_test.go @@ -891,10 +891,10 @@ func TestRandomAllocateDeallocate(t *testing.T) { } seed := time.Now().Unix() - rand.Seed(seed) + rng := rand.New(rand.NewSource(seed)) // Allocate all bits using a random pattern - pattern := rand.Perm(numBits) + pattern := rng.Perm(numBits) for _, bit := range pattern { err := hnd.Set(uint64(bit)) if err != nil { @@ -909,7 +909,7 @@ func TestRandomAllocateDeallocate(t *testing.T) { } // Deallocate all bits using a random pattern - pattern = rand.Perm(numBits) + pattern = rng.Perm(numBits) for _, bit := range pattern { err := hnd.Unset(uint64(bit)) if err != nil { @@ -959,10 +959,10 @@ func TestAllocateRandomDeallocate(t *testing.T) { } seed := time.Now().Unix() - rand.Seed(seed) + rng := rand.New(rand.NewSource(seed)) // Deallocate half of the allocated bits following a random pattern - pattern := rand.Perm(numBits / 2) + pattern := rng.Perm(numBits / 2) for i := 0; i < numBits/4; i++ { bit := pattern[i] err := hnd.Unset(uint64(bit)) @@ -1025,10 +1025,10 @@ func TestAllocateRandomDeallocateSerialize(t *testing.T) { } seed := time.Now().Unix() - rand.Seed(seed) + rng := rand.New(rand.NewSource(seed)) // Deallocate half of the allocated bits following a random pattern - pattern := rand.Perm(numBits / 2) + pattern := rng.Perm(numBits / 2) for i := 0; i < numBits/4; i++ { bit := pattern[i] err := hnd.Unset(uint64(bit)) @@ -1269,10 +1269,10 @@ func testSetRollover(t *testing.T, serial bool) { } seed := time.Now().Unix() - rand.Seed(seed) + rng := rand.New(rand.NewSource(seed)) // Deallocate half of the allocated bits following a random pattern - pattern := rand.Perm(numBits / 2) + pattern := rng.Perm(numBits / 2) for i := 0; i < numBits/4; i++ { bit := pattern[i] err := hnd.Unset(uint64(bit)) diff --git a/libnetwork/ipam/allocator_test.go b/libnetwork/ipam/allocator_test.go index a2bd0dc1af..489447b687 100644 --- a/libnetwork/ipam/allocator_test.go +++ b/libnetwork/ipam/allocator_test.go @@ -1317,10 +1317,10 @@ func testAllocateRandomDeallocate(t *testing.T, pool, subPool string, num int, s } seed := time.Now().Unix() - rand.Seed(seed) + rng := rand.New(rand.NewSource(seed)) // Deallocate half of the allocated addresses following a random pattern - pattern := rand.Perm(num) + pattern := rng.Perm(num) for i := 0; i < num/2; i++ { idx := pattern[i] ip := indices[idx] @@ -1553,6 +1553,10 @@ func TestRequestReleaseAddressDuplicate(t *testing.T) { t.Fatal(err) } + seed := time.Now().Unix() + t.Logf("Random seed: %v", seed) + rng := rand.New(rand.NewSource(seed)) + group := new(errgroup.Group) for err == nil { var c *net.IPNet @@ -1562,7 +1566,7 @@ func TestRequestReleaseAddressDuplicate(t *testing.T) { l.Unlock() allocatedIPs = append(allocatedIPs, c) if len(allocatedIPs) > 500 { - i := rand.Intn(len(allocatedIPs) - 1) + i := rng.Intn(len(allocatedIPs) - 1) ip := allocatedIPs[i] group.Go(func() error { if err = a.ReleaseAddress(poolID, ip.IP); err != nil { diff --git a/libnetwork/networkdb/cluster.go b/libnetwork/networkdb/cluster.go index 3cebbaba42..2ef5c22157 100644 --- a/libnetwork/networkdb/cluster.go +++ b/libnetwork/networkdb/cluster.go @@ -717,7 +717,7 @@ func randomOffset(n int) int { return 0 } - val, err := rand.Int(rand.Reader, big.NewInt(int64(n))) // #nosec G404 -- False positive; see https://github.com/securego/gosec/issues/862 + val, err := rand.Int(rand.Reader, big.NewInt(int64(n))) if err != nil { logrus.Errorf("Failed to get a random offset: %v", err) return 0 diff --git a/libnetwork/resolver.go b/libnetwork/resolver.go index 1c05afc608..6445975723 100644 --- a/libnetwork/resolver.go +++ b/libnetwork/resolver.go @@ -94,10 +94,6 @@ type resolver struct { startCh chan struct{} } -func init() { - rand.Seed(time.Now().Unix()) -} - // NewResolver creates a new instance of the Resolver func NewResolver(address string, proxyDNS bool, resolverKey string, backend DNSBackend) Resolver { return &resolver{ @@ -212,9 +208,17 @@ func setCommonFlags(msg *dns.Msg) { msg.RecursionAvailable = true } +//nolint:gosec // The RNG is not used in a security-sensitive context. +var ( + shuffleRNG = rand.New(rand.NewSource(time.Now().Unix())) + shuffleRNGMu sync.Mutex +) + func shuffleAddr(addr []net.IP) []net.IP { + shuffleRNGMu.Lock() + defer shuffleRNGMu.Unlock() for i := len(addr) - 1; i > 0; i-- { - r := rand.Intn(i + 1) //nolint:gosec // gosec complains about the use of rand here. It should be fine. + r := shuffleRNG.Intn(i + 1) //nolint:gosec // gosec complains about the use of rand here. It should be fine. addr[i], addr[r] = addr[r], addr[i] } return addr diff --git a/pkg/archive/archive.go b/pkg/archive/archive.go index e9ac1e322e..3af7c3a652 100644 --- a/pkg/archive/archive.go +++ b/pkg/archive/archive.go @@ -711,7 +711,7 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, L } } - case tar.TypeReg, tar.TypeRegA: + case tar.TypeReg: // Source is regular file. We use sequential file access to avoid depleting // the standby list on Windows. On Linux, this equates to a regular os.OpenFile. file, err := sequential.OpenFile(path, os.O_CREATE|os.O_WRONLY, hdrInfo.Mode())