Skip to content

Commit

Permalink
pkg/rand: replace SafeRand by global source in math/rand
Browse files Browse the repository at this point in the history
Since Go 1.20 the top-level math/rand functions are auto-seeded by
default, see https://go.dev/doc/go1.20#library and
golang/go#54880. They also use the runtime's
lock-free fastrand64 function when 1. Seed has not been called and 2.
GODEBUG=randautoseed=0 is not used, see
golang/go#49892.

This allows to drop SafeRand and use the global source again. SafeRand
was introduced in commit fac5dde ("rand: add and use
concurrency-safe PRNG source") to fix #10988 by providing a
concurrency-safe PRNG source other than the global math/rand source
which couldn't be used at the time because it can't be interfered with
from unrelated packages by means of calling rand.Seed, see #10575.
rand.Seed is deprecated since GO 1.20 and per the paragraph above the
global source is seeded by default. This makes it unlikely that packages
would interfere with the global PRNG state anymore and the top-level
math/rand functions are safe to use again.

Signed-off-by: Tobias Klauser <tobias@cilium.io>
  • Loading branch information
tklauser committed Dec 8, 2023
1 parent 332bc00 commit 94e5f12
Show file tree
Hide file tree
Showing 10 changed files with 22 additions and 193 deletions.
6 changes: 2 additions & 4 deletions daemon/cmd/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package cmd
import (
"context"
"fmt"
"math/rand"
"net/http"
"strings"

Expand Down Expand Up @@ -37,7 +38,6 @@ import (
nodeTypes "github.com/cilium/cilium/pkg/node/types"
"github.com/cilium/cilium/pkg/option"
"github.com/cilium/cilium/pkg/promise"
"github.com/cilium/cilium/pkg/rand"
"github.com/cilium/cilium/pkg/status"
"github.com/cilium/cilium/pkg/time"
"github.com/cilium/cilium/pkg/version"
Expand All @@ -54,8 +54,6 @@ const (
k8sMinimumEventHearbeat = time.Minute
)

var randGen = rand.NewSafeRand(time.Now().UnixNano())

type k8sVersion struct {
version string
lastVersionCheck time.Time
Expand Down Expand Up @@ -596,7 +594,7 @@ func (h *getNodes) Handle(d *Daemon, params GetClusterNodesParams) middleware.Re
if exists {
clientID = *params.ClientID
} else {
clientID = randGen.Int63()
clientID = rand.Int63()
// make sure we haven't allocated an existing client ID nor the
// randomizer has allocated ID 0, if we have then we will return
// clientID 0.
Expand Down
10 changes: 3 additions & 7 deletions pkg/backoff/backoff.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,17 @@ import (
"context"
"fmt"
"math"
"math/rand"

"github.com/google/uuid"
"github.com/sirupsen/logrus"

"github.com/cilium/cilium/pkg/logging"
"github.com/cilium/cilium/pkg/logging/logfields"
"github.com/cilium/cilium/pkg/rand"
"github.com/cilium/cilium/pkg/time"
)

var (
log = logging.DefaultLogger.WithField(logfields.LogSubsys, "backoff")

randGen = rand.NewSafeRand(time.Now().UnixNano())
)
var log = logging.DefaultLogger.WithField(logfields.LogSubsys, "backoff")

// NodeManager is the interface required to implement cluster size dependent
// intervals
Expand Down Expand Up @@ -98,7 +94,7 @@ func CalculateDuration(min, max time.Duration, factor float64, jitter bool, fail
}

if jitter {
t = randGen.Float64()*(t-minFloat) + minFloat
t = rand.Float64()*(t-minFloat) + minFloat
}

return time.Duration(t)
Expand Down
13 changes: 4 additions & 9 deletions pkg/ipam/service/allocator/bitmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@ package allocator
import (
"errors"
"math/big"
"math/rand"

"github.com/cilium/cilium/pkg/lock"
"github.com/cilium/cilium/pkg/rand"
"github.com/cilium/cilium/pkg/time"
)

// AllocationBitmap is a contiguous block of resources that can be allocated atomically.
Expand Down Expand Up @@ -50,9 +49,7 @@ type bitAllocator interface {
// NewAllocationMap creates an allocation bitmap using the random scan strategy.
func NewAllocationMap(max int, rangeSpec string) *AllocationBitmap {
a := AllocationBitmap{
strategy: randomScanStrategy{
rand: rand.NewSafeRand(time.Now().UnixNano()),
},
strategy: randomScanStrategy{},
allocated: big.NewInt(0),
count: 0,
max: max,
Expand Down Expand Up @@ -186,15 +183,13 @@ func (r *AllocationBitmap) Restore(rangeSpec string, data []byte) error {
// randomScanStrategy chooses a random address from the provided big.Int, and then
// scans forward looking for the next available address (it will wrap the range if
// necessary).
type randomScanStrategy struct {
rand *rand.SafeRand
}
type randomScanStrategy struct{}

func (rss randomScanStrategy) AllocateBit(allocated *big.Int, max, count int) (int, bool) {
if count >= max {
return 0, false
}
offset := rss.rand.Intn(max)
offset := rand.Intn(max)
for i := 0; i < max; i++ {
at := (offset + i) % max
if allocated.Bit(at) == 0 {
Expand Down
16 changes: 6 additions & 10 deletions pkg/kvstore/etcd.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"crypto/tls"
"errors"
"fmt"
"math/rand"
"net/url"
"os"
"strconv"
Expand All @@ -32,7 +33,6 @@ import (
"github.com/cilium/cilium/pkg/inctimer"
"github.com/cilium/cilium/pkg/lock"
"github.com/cilium/cilium/pkg/option"
"github.com/cilium/cilium/pkg/rand"
ciliumrate "github.com/cilium/cilium/pkg/rate"
ciliumratemetrics "github.com/cilium/cilium/pkg/rate/metrics"
"github.com/cilium/cilium/pkg/spanstat"
Expand Down Expand Up @@ -63,13 +63,9 @@ const (
etcdMaxKeysPerLease = 1000
)

var (
// ErrLockLeaseExpired is an error whenever the lease of the lock does not
// exist or it was expired.
ErrLockLeaseExpired = errors.New("transaction did not succeed: lock lease expired")

randGen = rand.NewSafeRand(time.Now().UnixNano())
)
// ErrLockLeaseExpired is an error whenever the lease of the lock does not
// exist or it was expired.
var ErrLockLeaseExpired = errors.New("transaction did not succeed: lock lease expired")

type etcdModule struct {
opts backendOptions
Expand Down Expand Up @@ -181,7 +177,7 @@ func (e *etcdModule) getConfig() map[string]string {
}

func shuffleEndpoints(endpoints []string) {
randGen.Shuffle(len(endpoints), func(i, j int) {
rand.Shuffle(len(endpoints), func(i, j int) {
endpoints[i], endpoints[j] = endpoints[j], endpoints[i]
})
}
Expand Down Expand Up @@ -425,7 +421,7 @@ func (e *etcdClient) waitForInitLock(ctx context.Context) <-chan error {

// Generate a random number so that we can acquire a lock even
// if other agents are killed while locking this path.
randNumber := strconv.FormatUint(randGen.Uint64(), 16)
randNumber := strconv.FormatUint(rand.Uint64(), 16)
locker, err := e.LockPath(ctx, InitLockPath+"/"+randNumber)
if err == nil {
locker.Unlock(context.Background())
Expand Down
4 changes: 0 additions & 4 deletions pkg/lock/stoppable_waitgroup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,6 @@ func (s *SemaphoredMutexSuite) TestWaitChannel(c *C) {
func (s *SemaphoredMutexSuite) TestParallelism(c *C) {
l := NewStoppableWaitGroup()

// Use math/rand instead of pkg/rand to avoid a test import cycle which
// go vet would complain about. Use the global default entropy source
// rather than creating a new source to avoid concurrency issues.
rand.Seed(time.Now().UnixNano())
in := make(chan int)
stop := make(chan struct{})
go func() {
Expand Down
5 changes: 2 additions & 3 deletions pkg/node/manager/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"context"
"errors"
"fmt"
"math/rand"
"net"
"net/netip"

Expand Down Expand Up @@ -35,13 +36,11 @@ import (
"github.com/cilium/cilium/pkg/node/addressing"
nodeTypes "github.com/cilium/cilium/pkg/node/types"
"github.com/cilium/cilium/pkg/option"
"github.com/cilium/cilium/pkg/rand"
"github.com/cilium/cilium/pkg/source"
"github.com/cilium/cilium/pkg/time"
)

var (
randGen = rand.NewSafeRand(time.Now().UnixNano())
baseBackgroundSyncInterval = time.Minute

neighborTableRefreshControllerGroup = controller.NewGroup("neighbor-table-refresh")
Expand Down Expand Up @@ -836,7 +835,7 @@ func (m *manager) StartNeighborRefresh(nh datapath.NodeNeighbors) {
// To avoid flooding network with arping requests
// at the same time, spread them over the
// [0; ARPPingRefreshPeriod/2) period.
n := randGen.Int63n(int64(option.Config.ARPPingRefreshPeriod / 2))
n := rand.Int63n(int64(option.Config.ARPPingRefreshPeriod / 2))
time.Sleep(time.Duration(n))
nh.NodeNeighborRefresh(c, e)
}(ctx, entryNode)
Expand Down
10 changes: 3 additions & 7 deletions pkg/proxy/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package proxy
import (
"context"
"fmt"
"math/rand"
"net"

"github.com/sirupsen/logrus"
Expand All @@ -25,16 +26,11 @@ import (
"github.com/cilium/cilium/pkg/policy"
"github.com/cilium/cilium/pkg/proxy/endpoint"
"github.com/cilium/cilium/pkg/proxy/types"
"github.com/cilium/cilium/pkg/rand"
"github.com/cilium/cilium/pkg/revert"
"github.com/cilium/cilium/pkg/time"
)

var (
log = logging.DefaultLogger.WithField(logfields.LogSubsys, "proxy")

portRandomizer = rand.NewSafeRand(time.Now().UnixNano())
)
var log = logging.DefaultLogger.WithField(logfields.LogSubsys, "proxy")

// field names used while logging
const (
Expand Down Expand Up @@ -201,7 +197,7 @@ func (p *Proxy) allocatePort(port, min, max uint16) (uint16, error) {
}

// TODO: Maybe not create a large permutation each time?
portRange := portRandomizer.Perm(int(max - min + 1))
portRange := rand.Perm(int(max - min + 1))

// Allow reuse of previously used ports only if no ports are otherwise availeble.
// This allows the same port to be used again by a listener being reconfigured
Expand Down
87 changes: 0 additions & 87 deletions pkg/rand/safe_rand.go

This file was deleted.

57 changes: 0 additions & 57 deletions pkg/rand/safe_rand_test.go

This file was deleted.

0 comments on commit 94e5f12

Please sign in to comment.