diff options
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/sentry/socket/netfilter/netfilter.go | 4 | ||||
-rw-r--r-- | pkg/tcpip/stack/conntrack.go | 25 | ||||
-rw-r--r-- | pkg/tcpip/stack/iptables.go | 5 | ||||
-rw-r--r-- | pkg/tcpip/stack/iptables_state.go | 44 | ||||
-rw-r--r-- | pkg/tcpip/stack/stack.go | 4 | ||||
-rw-r--r-- | pkg/tcpip/stack/stack_state_autogen.go | 44 |
6 files changed, 29 insertions, 97 deletions
diff --git a/pkg/sentry/socket/netfilter/netfilter.go b/pkg/sentry/socket/netfilter/netfilter.go index e3eade180..8d9e73243 100644 --- a/pkg/sentry/socket/netfilter/netfilter.go +++ b/pkg/sentry/socket/netfilter/netfilter.go @@ -58,8 +58,8 @@ var nameToID = map[string]stack.TableID{ // DefaultLinuxTables returns the rules of stack.DefaultTables() wrapped for // compatibility with netfilter extensions. -func DefaultLinuxTables(seed uint32) *stack.IPTables { - tables := stack.DefaultTables(seed) +func DefaultLinuxTables(seed uint32, clock tcpip.Clock) *stack.IPTables { + tables := stack.DefaultTables(seed, clock) tables.VisitTargets(func(oldTarget stack.Target) stack.Target { switch val := oldTarget.(type) { case *stack.AcceptTarget: diff --git a/pkg/tcpip/stack/conntrack.go b/pkg/tcpip/stack/conntrack.go index eee0fc20c..3583d93c6 100644 --- a/pkg/tcpip/stack/conntrack.go +++ b/pkg/tcpip/stack/conntrack.go @@ -122,14 +122,12 @@ type conn struct { // lastUsed is the last time the connection saw a relevant packet, and // is updated by each packet on the connection. // - // TODO(gvisor.dev/issue/5939): do not use the ambient clock. - // // +checklocks:mu - lastUsed time.Time `state:".(unixTime)"` + lastUsed tcpip.MonotonicTime } // timedOut returns whether the connection timed out based on its state. -func (cn *conn) timedOut(now time.Time) bool { +func (cn *conn) timedOut(now tcpip.MonotonicTime) bool { const establishedTimeout = 5 * 24 * time.Hour const defaultTimeout = 120 * time.Second cn.mu.RLock() @@ -190,6 +188,9 @@ type ConnTrack struct { // It is immutable. seed uint32 + // clock provides timing used to determine conntrack reapings. + clock tcpip.Clock + mu sync.RWMutex `state:"nosave"` // mu protects the buckets slice, but not buckets' contents. Only take // the write lock if you are modifying the slice or saving for S/R. @@ -248,7 +249,7 @@ func (ct *ConnTrack) getConnOrMaybeInsertNoop(pkt *PacketBuffer) *tuple { bkt := &ct.buckets[bktID] ct.mu.RUnlock() - now := time.Now() + now := ct.clock.NowMonotonic() if t := bkt.connForTID(tid, now); t != nil { return t } @@ -294,17 +295,17 @@ func (ct *ConnTrack) connForTID(tid tupleID) *tuple { bkt := &ct.buckets[bktID] ct.mu.RUnlock() - return bkt.connForTID(tid, time.Now()) + return bkt.connForTID(tid, ct.clock.NowMonotonic()) } -func (bkt *bucket) connForTID(tid tupleID, now time.Time) *tuple { +func (bkt *bucket) connForTID(tid tupleID, now tcpip.MonotonicTime) *tuple { bkt.mu.RLock() defer bkt.mu.RUnlock() return bkt.connForTIDRLocked(tid, now) } // +checklocksread:bkt.mu -func (bkt *bucket) connForTIDRLocked(tid tupleID, now time.Time) *tuple { +func (bkt *bucket) connForTIDRLocked(tid tupleID, now tcpip.MonotonicTime) *tuple { for other := bkt.tuples.Front(); other != nil; other = other.Next() { if tid == other.id() && !other.conn.timedOut(now) { return other @@ -324,7 +325,7 @@ func (ct *ConnTrack) finalize(cn *conn) { bkt.mu.Lock() defer bkt.mu.Unlock() - if t := bkt.connForTIDRLocked(tid, time.Now()); t != nil { + if t := bkt.connForTIDRLocked(tid, ct.clock.NowMonotonic()); t != nil { // Another connection for the reply already exists. We can't do much about // this so we leave the connection cn represents in a state where it can // send packets but its responses will be mapped to some other connection. @@ -476,7 +477,7 @@ func (cn *conn) handlePacket(pkt *PacketBuffer, hook Hook, r *Route) bool { } // Mark the connection as having been used recently so it isn't reaped. - cn.lastUsed = time.Now() + cn.lastUsed = cn.ct.clock.NowMonotonic() // Update connection state. cn.updateLocked(pkt, reply) @@ -548,7 +549,7 @@ func (ct *ConnTrack) reapUnused(start int, prevInterval time.Duration) (int, tim const minInterval = 10 * time.Millisecond const maxInterval = maxFullTraversal / fractionPerReaping - now := time.Now() + now := ct.clock.NowMonotonic() checked := 0 expired := 0 var idx int @@ -592,7 +593,7 @@ func (ct *ConnTrack) reapUnused(start int, prevInterval time.Duration) (int, tim // Precondition: ct.mu is read locked and bkt.mu is write locked. // +checklocksread:ct.mu // +checklocks:bkt.mu -func (ct *ConnTrack) reapTupleLocked(tuple *tuple, bktID int, bkt *bucket, now time.Time) bool { +func (ct *ConnTrack) reapTupleLocked(tuple *tuple, bktID int, bkt *bucket, now tcpip.MonotonicTime) bool { if !tuple.conn.timedOut(now) { return false } diff --git a/pkg/tcpip/stack/iptables.go b/pkg/tcpip/stack/iptables.go index 0baa378ea..fd61387bf 100644 --- a/pkg/tcpip/stack/iptables.go +++ b/pkg/tcpip/stack/iptables.go @@ -42,7 +42,7 @@ const reaperDelay = 5 * time.Second // DefaultTables returns a default set of tables. Each chain is set to accept // all packets. -func DefaultTables(seed uint32) *IPTables { +func DefaultTables(seed uint32, clock tcpip.Clock) *IPTables { return &IPTables{ v4Tables: [NumTables]Table{ NATID: { @@ -182,7 +182,8 @@ func DefaultTables(seed uint32) *IPTables { Postrouting: {MangleID, NATID}, }, connections: ConnTrack{ - seed: seed, + seed: seed, + clock: clock, }, reaperDone: make(chan struct{}, 1), } diff --git a/pkg/tcpip/stack/iptables_state.go b/pkg/tcpip/stack/iptables_state.go deleted file mode 100644 index 3d3c39c20..000000000 --- a/pkg/tcpip/stack/iptables_state.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2020 The gVisor Authors. -// -// 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. - -package stack - -import ( - "time" -) - -// +stateify savable -type unixTime struct { - second int64 - nano int64 -} - -// saveLastUsed is invoked by stateify. -func (cn *conn) saveLastUsed() unixTime { - cn.mu.Lock() - defer cn.mu.Unlock() - return unixTime{cn.lastUsed.Unix(), cn.lastUsed.UnixNano()} -} - -// loadLastUsed is invoked by stateify. -func (cn *conn) loadLastUsed(unix unixTime) { - cn.mu.Lock() - defer cn.mu.Unlock() - cn.lastUsed = time.Unix(unix.second, unix.nano) -} - -// beforeSave is invoked by stateify. -func (ct *ConnTrack) beforeSave() { - ct.mu.Lock() -} diff --git a/pkg/tcpip/stack/stack.go b/pkg/tcpip/stack/stack.go index 428350f31..ee6767654 100644 --- a/pkg/tcpip/stack/stack.go +++ b/pkg/tcpip/stack/stack.go @@ -238,7 +238,7 @@ type Options struct { // DefaultIPTables is an optional iptables rules constructor that is called // if IPTables is nil. If both fields are nil, iptables will allow all // traffic. - DefaultIPTables func(uint32) *IPTables + DefaultIPTables func(seed uint32, clock tcpip.Clock) *IPTables // SecureRNG is a cryptographically secure random number generator. SecureRNG io.Reader @@ -358,7 +358,7 @@ func New(opts Options) *Stack { if opts.DefaultIPTables == nil { opts.DefaultIPTables = DefaultTables } - opts.IPTables = opts.DefaultIPTables(seed) + opts.IPTables = opts.DefaultIPTables(seed, clock) } opts.NUDConfigs.resetInvalidFields() diff --git a/pkg/tcpip/stack/stack_state_autogen.go b/pkg/tcpip/stack/stack_state_autogen.go index f1befa422..e4752bab1 100644 --- a/pkg/tcpip/stack/stack_state_autogen.go +++ b/pkg/tcpip/stack/stack_state_autogen.go @@ -102,9 +102,6 @@ func (cn *conn) beforeSave() {} // +checklocksignore func (cn *conn) StateSave(stateSinkObject state.Sink) { cn.beforeSave() - var lastUsedValue unixTime - lastUsedValue = cn.saveLastUsed() - stateSinkObject.SaveValue(7, lastUsedValue) stateSinkObject.Save(0, &cn.ct) stateSinkObject.Save(1, &cn.original) stateSinkObject.Save(2, &cn.reply) @@ -112,6 +109,7 @@ func (cn *conn) StateSave(stateSinkObject state.Sink) { stateSinkObject.Save(4, &cn.sourceManip) stateSinkObject.Save(5, &cn.destinationManip) stateSinkObject.Save(6, &cn.tcb) + stateSinkObject.Save(7, &cn.lastUsed) } func (cn *conn) afterLoad() {} @@ -125,7 +123,7 @@ func (cn *conn) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(4, &cn.sourceManip) stateSourceObject.Load(5, &cn.destinationManip) stateSourceObject.Load(6, &cn.tcb) - stateSourceObject.LoadValue(7, new(unixTime), func(y interface{}) { cn.loadLastUsed(y.(unixTime)) }) + stateSourceObject.Load(7, &cn.lastUsed) } func (ct *ConnTrack) StateTypeName() string { @@ -135,15 +133,19 @@ func (ct *ConnTrack) StateTypeName() string { func (ct *ConnTrack) StateFields() []string { return []string{ "seed", + "clock", "buckets", } } +func (ct *ConnTrack) beforeSave() {} + // +checklocksignore func (ct *ConnTrack) StateSave(stateSinkObject state.Sink) { ct.beforeSave() stateSinkObject.Save(0, &ct.seed) - stateSinkObject.Save(1, &ct.buckets) + stateSinkObject.Save(1, &ct.clock) + stateSinkObject.Save(2, &ct.buckets) } func (ct *ConnTrack) afterLoad() {} @@ -151,7 +153,8 @@ func (ct *ConnTrack) afterLoad() {} // +checklocksignore func (ct *ConnTrack) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(0, &ct.seed) - stateSourceObject.Load(1, &ct.buckets) + stateSourceObject.Load(1, &ct.clock) + stateSourceObject.Load(2, &ct.buckets) } func (bkt *bucket) StateTypeName() string { @@ -179,34 +182,6 @@ func (bkt *bucket) StateLoad(stateSourceObject state.Source) { stateSourceObject.Load(0, &bkt.tuples) } -func (u *unixTime) StateTypeName() string { - return "pkg/tcpip/stack.unixTime" -} - -func (u *unixTime) StateFields() []string { - return []string{ - "second", - "nano", - } -} - -func (u *unixTime) beforeSave() {} - -// +checklocksignore -func (u *unixTime) StateSave(stateSinkObject state.Sink) { - u.beforeSave() - stateSinkObject.Save(0, &u.second) - stateSinkObject.Save(1, &u.nano) -} - -func (u *unixTime) afterLoad() {} - -// +checklocksignore -func (u *unixTime) StateLoad(stateSourceObject state.Source) { - stateSourceObject.Load(0, &u.second) - stateSourceObject.Load(1, &u.nano) -} - func (it *IPTables) StateTypeName() string { return "pkg/tcpip/stack.IPTables" } @@ -1268,7 +1243,6 @@ func init() { state.Register((*conn)(nil)) state.Register((*ConnTrack)(nil)) state.Register((*bucket)(nil)) - state.Register((*unixTime)(nil)) state.Register((*IPTables)(nil)) state.Register((*Table)(nil)) state.Register((*Rule)(nil)) |