From 7ca550fd6421bdeb1e81b33198965f24398cfac1 Mon Sep 17 00:00:00 2001 From: Ondrej Fabry Date: Mon, 18 May 2020 11:36:44 +0200 Subject: Fix stats data errors and panic for VPP 20.05 - fixes panic occurring when updating error counters - fixes stat data length errors when updating stats Change-Id: If2d4bcb7df084bf1999ba469f128b7a01aa6be5e Signed-off-by: Ondrej Fabry --- adapter/statsclient/stat_segment.go | 57 ++++++++++++++++++++++++------------- core/stats.go | 4 +-- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/adapter/statsclient/stat_segment.go b/adapter/statsclient/stat_segment.go index 0d988ba..2a97fd4 100644 --- a/adapter/statsclient/stat_segment.go +++ b/adapter/statsclient/stat_segment.go @@ -200,6 +200,14 @@ func (c *statSegment) copyEntryData(dirEntry *statSegDirectoryEntry) adapter.Sta return adapter.ScalarStat(dirEntry.unionData) case statDirErrorIndex: + if dirEntry.unionData == 0 { + debugf("offset invalid for %s", dirEntry.name) + break + } else if dirEntry.unionData >= uint64(len(c.sharedHeader)) { + debugf("offset out of range for %s", dirEntry.name) + break + } + _, errOffset, _ := c.getOffsets() offsetVector := unsafe.Pointer(&c.sharedHeader[errOffset]) @@ -324,6 +332,14 @@ func (c *statSegment) updateEntryData(dirEntry *statSegDirectoryEntry, stat *ada *stat = adapter.ScalarStat(dirEntry.unionData) case adapter.ErrorStat: + if dirEntry.unionData == 0 { + debugf("offset invalid for %s", dirEntry.name) + break + } else if dirEntry.unionData >= uint64(len(c.sharedHeader)) { + debugf("offset out of range for %s", dirEntry.name) + break + } + _, errOffset, _ := c.getOffsets() offsetVector := unsafe.Pointer(&c.sharedHeader[errOffset]) @@ -334,8 +350,9 @@ func (c *statSegment) updateEntryData(dirEntry *statSegDirectoryEntry, stat *ada val := *(*adapter.Counter)(statSegPointer(offsetVector, offset)) errData = val } else { - vecLen := vectorLen(offsetVector) - for i := uint64(0); i < vecLen; i++ { + vecLen := uint32(vectorLen(unsafe.Pointer(&c.sharedHeader[errOffset]))) + + for i := uint32(0); i < vecLen; i++ { cb := *(*uint64)(statSegPointer(offsetVector, uintptr(i)*unsafe.Sizeof(uint64(0)))) offset := uintptr(cb) + uintptr(dirEntry.unionData)*unsafe.Sizeof(adapter.Counter(0)) val := *(*adapter.Counter)(statSegPointer(unsafe.Pointer(&c.sharedHeader[0]), offset)) @@ -353,22 +370,22 @@ func (c *statSegment) updateEntryData(dirEntry *statSegDirectoryEntry, stat *ada break } - vecLen := vectorLen(unsafe.Pointer(&c.sharedHeader[dirEntry.unionData])) + vecLen := uint32(vectorLen(unsafe.Pointer(&c.sharedHeader[dirEntry.unionData]))) offsetVector := statSegPointer(unsafe.Pointer(&c.sharedHeader[0]), uintptr(dirEntry.offsetVector)) data := (*stat).(adapter.SimpleCounterStat) - if uint64(len(data)) != vecLen { + if uint32(len(data)) != vecLen { return ErrStatDataLenIncorrect } - for i := uint64(0); i < vecLen; i++ { + for i := uint32(0); i < vecLen; i++ { cb := *(*uint64)(statSegPointer(offsetVector, uintptr(i)*unsafe.Sizeof(uint64(0)))) counterVec := unsafe.Pointer(&c.sharedHeader[uintptr(cb)]) - vecLen2 := vectorLen(counterVec) + vecLen2 := uint32(vectorLen(counterVec)) simpData := data[i] - if uint64(len(simpData)) != vecLen2 { + if uint32(len(simpData)) != vecLen2 { return ErrStatDataLenIncorrect } - for j := uint64(0); j < vecLen2; j++ { + for j := uint32(0); j < vecLen2; j++ { offset := uintptr(j) * unsafe.Sizeof(adapter.Counter(0)) val := *(*adapter.Counter)(statSegPointer(counterVec, offset)) simpData[j] = val @@ -384,22 +401,22 @@ func (c *statSegment) updateEntryData(dirEntry *statSegDirectoryEntry, stat *ada break } - vecLen := vectorLen(unsafe.Pointer(&c.sharedHeader[dirEntry.unionData])) + vecLen := uint32(vectorLen(unsafe.Pointer(&c.sharedHeader[dirEntry.unionData]))) offsetVector := statSegPointer(unsafe.Pointer(&c.sharedHeader[0]), uintptr(dirEntry.offsetVector)) data := (*stat).(adapter.CombinedCounterStat) - if uint64(len(data)) != vecLen { + if uint32(len(data)) != vecLen { return ErrStatDataLenIncorrect } - for i := uint64(0); i < vecLen; i++ { + for i := uint32(0); i < vecLen; i++ { cb := *(*uint64)(statSegPointer(offsetVector, uintptr(i)*unsafe.Sizeof(uint64(0)))) counterVec := unsafe.Pointer(&c.sharedHeader[uintptr(cb)]) - vecLen2 := vectorLen(counterVec) + vecLen2 := uint32(vectorLen(counterVec)) combData := data[i] - if uint64(len(combData)) != vecLen2 { + if uint32(len(combData)) != vecLen2 { return ErrStatDataLenIncorrect } - for j := uint64(0); j < vecLen2; j++ { + for j := uint32(0); j < vecLen2; j++ { offset := uintptr(j) * unsafe.Sizeof(adapter.CombinedCounter{}) val := *(*adapter.CombinedCounter)(statSegPointer(counterVec, offset)) combData[j] = val @@ -415,26 +432,26 @@ func (c *statSegment) updateEntryData(dirEntry *statSegDirectoryEntry, stat *ada break } - vecLen := vectorLen(unsafe.Pointer(&c.sharedHeader[dirEntry.unionData])) + vecLen := uint32(vectorLen(unsafe.Pointer(&c.sharedHeader[dirEntry.unionData]))) offsetVector := statSegPointer(unsafe.Pointer(&c.sharedHeader[0]), uintptr(dirEntry.offsetVector)) data := (*stat).(adapter.NameStat) - if uint64(len(data)) != vecLen { + if uint32(len(data)) != vecLen { return ErrStatDataLenIncorrect } - for i := uint64(0); i < vecLen; i++ { + for i := uint32(0); i < vecLen; i++ { cb := *(*uint64)(statSegPointer(offsetVector, uintptr(i)*unsafe.Sizeof(uint64(0)))) if cb == 0 { continue } nameVec := unsafe.Pointer(&c.sharedHeader[cb]) - vecLen2 := vectorLen(nameVec) + vecLen2 := uint32(vectorLen(nameVec)) nameData := data[i] - if uint64(len(nameData))+1 != vecLen2 { + if uint32(len(nameData))+1 != vecLen2 { return ErrStatDataLenIncorrect } - for j := uint64(0); j < vecLen2; j++ { + for j := uint32(0); j < vecLen2; j++ { offset := uintptr(j) * unsafe.Sizeof(byte(0)) val := *(*byte)(statSegPointer(nameVec, offset)) if val == 0 { diff --git a/core/stats.go b/core/stats.go index 2a9e964..0717be6 100644 --- a/core/stats.go +++ b/core/stats.go @@ -88,7 +88,7 @@ func newStatsConnection(stats adapter.StatsAPI) *StatsConnection { } } -// Connect connects to Stats API using specified adapter and returns a connection handle. +// ConnectStats connects to Stats API using specified adapter and returns a connection handle. // This call blocks until it is either connected, or an error occurs. // Only one connection attempt will be performed. func ConnectStats(stats adapter.StatsAPI) (*StatsConnection, error) { @@ -177,7 +177,7 @@ func (c *StatsConnection) updateStats(statDir **adapter.StatDir, patterns ...str return err } -// UpdateSystemStats retrieves VPP system stats. +// GetSystemStats retrieves VPP system stats. func (c *StatsConnection) GetSystemStats(sysStats *api.SystemStats) (err error) { if err := c.updateStats(&c.sysStatsData, SystemStatsPrefix); err != nil { return err -- cgit 1.2.3-korg