From ad8f293e1af99f3c04d1020bb51b46c0dba60e45 Mon Sep 17 00:00:00 2001 From: Zhaozhong Ni Date: Tue, 4 Dec 2018 13:13:13 -0800 Subject: sentry: save copy of tcp segment's delivered views to avoid in-struct pointers. PiperOrigin-RevId: 224033238 Change-Id: Ie5b1854b29340843b02c123766d290a8738d7631 --- pkg/state/encode.go | 5 +++-- pkg/tcpip/transport/tcp/segment.go | 2 +- pkg/tcpip/transport/tcp/segment_state.go | 11 ++++++++++- 3 files changed, 14 insertions(+), 4 deletions(-) (limited to 'pkg') diff --git a/pkg/state/encode.go b/pkg/state/encode.go index 577aaf051..fe8512bbf 100644 --- a/pkg/state/encode.go +++ b/pkg/state/encode.go @@ -119,9 +119,10 @@ func (es *encodeState) register(obj reflect.Value) uint64 { if size := typ.Size(); size > 0 { r := addrRange{addr, addr + size} if !es.values.IsEmptyRange(r) { - panic(fmt.Errorf("overlapping objects: [new object] %#v [existing object] %#v", obj.Interface(), es.values.FindSegment(addr).Value().Elem().Interface())) + old := es.values.LowerBoundSegment(addr).Value().Interface().(recoverable) + panic(fmt.Errorf("overlapping objects: [new object] %#v [existing object path] %s", obj.Interface(), old.path())) } - es.values.Add(r, obj) + es.values.Add(r, reflect.ValueOf(es.recoverable.copy())) } } else { // Push back the map itself; when maps are encoded from the diff --git a/pkg/tcpip/transport/tcp/segment.go b/pkg/tcpip/transport/tcp/segment.go index fc87a05fd..87c6d7d20 100644 --- a/pkg/tcpip/transport/tcp/segment.go +++ b/pkg/tcpip/transport/tcp/segment.go @@ -46,7 +46,7 @@ type segment struct { data buffer.VectorisedView `state:".(buffer.VectorisedView)"` // views is used as buffer for data when its length is large // enough to store a VectorisedView. - views [8]buffer.View + views [8]buffer.View `state:"nosave"` // viewToDeliver keeps track of the next View that should be // delivered by the Read endpoint. viewToDeliver int diff --git a/pkg/tcpip/transport/tcp/segment_state.go b/pkg/tcpip/transport/tcp/segment_state.go index 46b6d85a6..d4bd6cf95 100644 --- a/pkg/tcpip/transport/tcp/segment_state.go +++ b/pkg/tcpip/transport/tcp/segment_state.go @@ -22,7 +22,16 @@ import ( func (s *segment) saveData() buffer.VectorisedView { // We cannot save s.data directly as s.data.views may alias to s.views, // which is not allowed by state framework (in-struct pointer). - return s.data.Clone(nil) + v := make([]buffer.View, len(s.data.Views())) + // For views already delivered, we cannot save them directly as they may + // have already been sliced and saved elsewhere (e.g., readViews). + for i := 0; i < s.viewToDeliver; i++ { + v[i] = append([]byte(nil), s.data.Views()[i]...) + } + for i := s.viewToDeliver; i < len(v); i++ { + v[i] = s.data.Views()[i] + } + return buffer.NewVectorisedView(s.data.Size(), v) } // loadData is invoked by stateify. -- cgit v1.2.3