nftables: use a secure RNG

Linux implements the random operation with a cryptographically secure RNG. We
must do the same.

PiperOrigin-RevId: 678301194
This commit is contained in:
Kevin Krakauer
2024-09-24 10:22:10 -07:00
committed by gVisor bot
parent fdd7580bd1
commit 9488cfcf0b
3 changed files with 28 additions and 13 deletions
+2
View File
@@ -13,6 +13,7 @@ go_library(
],
deps = [
"//pkg/abi/linux",
"//pkg/rand",
"//pkg/tcpip",
"//pkg/tcpip/checksum",
"//pkg/tcpip/header",
@@ -30,6 +31,7 @@ go_test(
deps = [
"//pkg/abi/linux",
"//pkg/buffer",
"//pkg/rand",
"//pkg/sync",
"//pkg/tcpip",
"//pkg/tcpip/faketime",
+4 -5
View File
@@ -44,12 +44,12 @@ import (
"bytes"
"encoding/binary"
"fmt"
"math/rand"
"slices"
"sync/atomic"
"time"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/rand"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/checksum"
"gvisor.dev/gvisor/pkg/tcpip/header"
@@ -229,7 +229,7 @@ type NFTables struct {
filters [NumAFs]*addressFamilyFilter // Filters for each address family.
clock tcpip.Clock // Clock for timing evaluations.
startTime time.Time // Time NFTables object was created.
rng *rand.Rand // Random number generator.
rng rand.RNG // Random number generator.
}
// addressFamilyFilter represents the nftables state for a specific address
@@ -2199,12 +2199,11 @@ func (r *Rule) evaluate(regs *registerSet, pkt *stack.PacketBuffer) error {
// NewNFTables creates a new NFTables state object using the given clock for
// timing operations.
// Note: Expects random number generator to be initialized with a seed.
// TODO(b/345684870): Use a secure RNG.
func NewNFTables(clock tcpip.Clock, rng *rand.Rand) *NFTables {
func NewNFTables(clock tcpip.Clock, rng rand.RNG) *NFTables {
if clock == nil {
panic("nftables state must be initialized with a non-nil clock")
}
if rng == nil {
if rng.Reader == nil {
panic("nftables state must be initialized with a non-nil random number generator")
}
return &NFTables{clock: clock, startTime: clock.Now(), rng: rng}
+22 -8
View File
@@ -17,7 +17,6 @@ package nftables
import (
"encoding/binary"
"fmt"
"math/rand"
"reflect"
"slices"
"testing"
@@ -25,6 +24,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/buffer"
"gvisor.dev/gvisor/pkg/rand"
"gvisor.dev/gvisor/pkg/sync"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/faketime"
@@ -2370,8 +2370,8 @@ func TestEvaluateLast(t *testing.T) {
// Sets up an NFTables object with a base chain and fake manual clock.
fakeClock := faketime.NewManualClock()
fixedRng := rand.New(rand.NewSource(0))
nf := NewNFTables(fakeClock, fixedRng)
fixedRNG := rand.RNGFrom(&fixedReader{})
nf := NewNFTables(fakeClock, fixedRNG)
tab, err := nf.AddTable(arbitraryFamily, "test", "test table", false)
if err != nil {
t.Fatalf("unexpected error for AddTable: %v", err)
@@ -2822,8 +2822,8 @@ func TestEvaluateMetaLoad(t *testing.T) {
timeNS := now.UnixNano()
timeDay := now.Weekday()
timeHour := now.Hour()*3600 + now.Minute()*60 + now.Second()
fixedRng := rand.New(rand.NewSource(0))
seededRandUint32 := fixedRng.Uint32() // fixes rng
fixedRNG := rand.RNGFrom(&fixedReader{})
seededRandUint32 := fixedRNG.Uint32() // fixes rng
for _, test := range []struct {
tname string
@@ -2920,7 +2920,7 @@ func TestEvaluateMetaLoad(t *testing.T) {
t.Run(test.tname, func(t *testing.T) {
// Sets up an NFTables object with a base chain and fake manual clock.
// Using Manual Clock sets time.Now to Unix Epoch which fixes rng seed!
nf := NewNFTables(fakeClock, rand.New(rand.NewSource(0)))
nf := NewNFTables(fakeClock, rand.RNGFrom(&fixedReader{}))
tab, err := nf.AddTable(arbitraryFamily, "test", "test table", false)
if err != nil {
@@ -3713,8 +3713,8 @@ func packetResultString(initial, final *stack.PacketBuffer) string {
// newNFTablesStd creates a new NFTables object w/ a standard clock for testing.
func newNFTablesStd() *NFTables {
stdClock := tcpip.NewStdClock()
fixedRng := rand.New(rand.NewSource(0))
return NewNFTables(stdClock, fixedRng)
fixedRNG := rand.RNGFrom(&fixedReader{})
return NewNFTables(stdClock, fixedRNG)
}
// mustCreateImmediate wraps the newImmediate function for brevity.
@@ -3815,3 +3815,17 @@ func mustCreateMetaSet(t *testing.T, key metaKey, sreg uint8) *metaSet {
}
return mtset
}
// A fixedReader sets all bytes to the same value (1) when Read is called.
//
// It is used to make the RNG deterministic for testing, i.e. it's really
// really bad at being an RNG.
type fixedReader struct{}
// Read implements io.Reader.Read.
func (*fixedReader) Read(buf []byte) (int, error) {
for i := range len(buf) {
buf[i] = 1
}
return len(buf), nil
}