Fix stats data errors and panic for VPP 20.05 21/27121/1
authorOndrej Fabry <ofabry@cisco.com>
Mon, 18 May 2020 09:36:44 +0000 (11:36 +0200)
committerOndrej Fabry <ofabry@cisco.com>
Mon, 18 May 2020 09:36:44 +0000 (11:36 +0200)
- fixes panic occurring when updating error counters
- fixes stat data length errors when updating stats

Change-Id: If2d4bcb7df084bf1999ba469f128b7a01aa6be5e
Signed-off-by: Ondrej Fabry <ofabry@cisco.com>
adapter/statsclient/stat_segment.go
core/stats.go

index 0d988ba..2a97fd4 100644 (file)
@@ -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 {
index 2a9e964..0717be6 100644 (file)
@@ -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