0
0
Fork 0
mirror of https://github.com/netdata/netdata.git synced 2025-04-27 06:10:43 +00:00

more perflib error checking ()

* more perflib error checking

* more checks

* fix comparison
This commit is contained in:
Costa Tsaousis 2025-02-12 21:36:04 +02:00 committed by GitHub
parent 0453c3aed9
commit d57c5c503b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 65 additions and 40 deletions
src/libnetdata/os/windows-perflib

View file

@ -236,20 +236,22 @@ static BOOL getCounterData(
// -------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------
static inline BOOL isValidPointer(PERF_DATA_BLOCK *pDataBlock __maybe_unused, void *ptr __maybe_unused) { ALWAYS_INLINE
#ifdef NETDATA_INTERNAL_CHECKS static BOOL isValidPointer(PERF_DATA_BLOCK *pDataBlock, void *ptr) {
return (PBYTE)ptr >= (PBYTE)pDataBlock + pDataBlock->TotalByteLength ? FALSE : TRUE; return
#else !pDataBlock ||
return TRUE; (PBYTE)ptr < (PBYTE)pDataBlock ||
#endif (PBYTE)ptr >= (PBYTE)pDataBlock + pDataBlock->TotalByteLength ? FALSE : TRUE;
} }
static inline BOOL isValidStructure(PERF_DATA_BLOCK *pDataBlock __maybe_unused, void *ptr __maybe_unused, size_t length __maybe_unused) { ALWAYS_INLINE
#ifdef NETDATA_INTERNAL_CHECKS static BOOL isValidStructure(PERF_DATA_BLOCK *pDataBlock, void *ptr, size_t length) {
return (PBYTE)ptr + length > (PBYTE)pDataBlock + pDataBlock->TotalByteLength ? FALSE : TRUE; return
#else !pDataBlock ||
return TRUE; !length || length > pDataBlock->TotalByteLength ||
#endif (PBYTE)ptr < (PBYTE)pDataBlock ||
(PBYTE)ptr > (PBYTE)ptr + length || // Check for pointer arithmetic overflow
(PBYTE)ptr + length > (PBYTE)pDataBlock + pDataBlock->TotalByteLength ? FALSE : TRUE;
} }
static inline PERF_DATA_BLOCK *getDataBlock(BYTE *pBuffer) { static inline PERF_DATA_BLOCK *getDataBlock(BYTE *pBuffer) {
@ -273,7 +275,8 @@ static inline PERF_DATA_BLOCK *getDataBlock(BYTE *pBuffer) {
return pDataBlock; return pDataBlock;
} }
static inline PERF_OBJECT_TYPE *getObjectType(PERF_DATA_BLOCK* pDataBlock, PERF_OBJECT_TYPE *lastObjectType) { ALWAYS_INLINE
static PERF_OBJECT_TYPE *getObjectType(PERF_DATA_BLOCK* pDataBlock, PERF_OBJECT_TYPE *lastObjectType) {
PERF_OBJECT_TYPE* pObjectType = NULL; PERF_OBJECT_TYPE* pObjectType = NULL;
if(!lastObjectType) if(!lastObjectType)
@ -282,18 +285,20 @@ static inline PERF_OBJECT_TYPE *getObjectType(PERF_DATA_BLOCK* pDataBlock, PERF_
pObjectType = (PERF_OBJECT_TYPE *)((PBYTE)lastObjectType + lastObjectType->TotalByteLength); pObjectType = (PERF_OBJECT_TYPE *)((PBYTE)lastObjectType + lastObjectType->TotalByteLength);
if(pObjectType && (!isValidPointer(pDataBlock, pObjectType) || !isValidStructure(pDataBlock, pObjectType, pObjectType->TotalByteLength))) { if(pObjectType && (!isValidPointer(pDataBlock, pObjectType) || !isValidStructure(pDataBlock, pObjectType, pObjectType->TotalByteLength))) {
nd_log(NDLS_COLLECTORS, NDLP_ERR, nd_log(NDLS_COLLECTORS, NDLP_ERR, "WINDOWS: PERFLIB: %s(): Invalid ObjectType!", __FUNCTION__);
"WINDOWS: PERFLIB: Invalid ObjectType!");
pObjectType = NULL; pObjectType = NULL;
} }
return pObjectType; return pObjectType;
} }
inline PERF_OBJECT_TYPE *getObjectTypeByIndex(PERF_DATA_BLOCK *pDataBlock, DWORD ObjectNameTitleIndex) { ALWAYS_INLINE
PERF_OBJECT_TYPE *getObjectTypeByIndex(PERF_DATA_BLOCK *pDataBlock, DWORD ObjectNameTitleIndex) {
PERF_OBJECT_TYPE *po = NULL; PERF_OBJECT_TYPE *po = NULL;
for(DWORD o = 0; o < pDataBlock->NumObjectTypes ; o++) { for(DWORD o = 0; o < pDataBlock->NumObjectTypes ; o++) {
po = getObjectType(pDataBlock, po); po = getObjectType(pDataBlock, po);
if(!po) break;
if(po->ObjectNameTitleIndex == ObjectNameTitleIndex) if(po->ObjectNameTitleIndex == ObjectNameTitleIndex)
return po; return po;
} }
@ -301,60 +306,68 @@ inline PERF_OBJECT_TYPE *getObjectTypeByIndex(PERF_DATA_BLOCK *pDataBlock, DWORD
return NULL; return NULL;
} }
static inline PERF_INSTANCE_DEFINITION *getInstance( ALWAYS_INLINE
static PERF_INSTANCE_DEFINITION *getInstance(
PERF_DATA_BLOCK *pDataBlock, PERF_DATA_BLOCK *pDataBlock,
PERF_OBJECT_TYPE *pObjectType, PERF_OBJECT_TYPE *pObjectType,
PERF_COUNTER_BLOCK *lastCounterBlock PERF_COUNTER_BLOCK *lastCounterBlock
) { ) {
PERF_INSTANCE_DEFINITION *pInstance; if(unlikely(!pObjectType))
return NULL;
PERF_INSTANCE_DEFINITION *pInstance;
if(!lastCounterBlock) if(!lastCounterBlock)
pInstance = (PERF_INSTANCE_DEFINITION *)((PBYTE)pObjectType + pObjectType->DefinitionLength); pInstance = (PERF_INSTANCE_DEFINITION *)((PBYTE)pObjectType + pObjectType->DefinitionLength);
else else
pInstance = (PERF_INSTANCE_DEFINITION *)((PBYTE)lastCounterBlock + lastCounterBlock->ByteLength); pInstance = (PERF_INSTANCE_DEFINITION *)((PBYTE)lastCounterBlock + lastCounterBlock->ByteLength);
if(pInstance && (!isValidPointer(pDataBlock, pInstance) || !isValidStructure(pDataBlock, pInstance, pInstance->ByteLength))) { if(pInstance && (!isValidPointer(pDataBlock, pInstance) || !isValidStructure(pDataBlock, pInstance, pInstance->ByteLength))) {
nd_log(NDLS_COLLECTORS, NDLP_ERR, nd_log(NDLS_COLLECTORS, NDLP_ERR, "WINDOWS: PERFLIB: %s(): Invalid Instance Definition!", __FUNCTION__);
"WINDOWS: PERFLIB: Invalid Instance Definition!");
pInstance = NULL; pInstance = NULL;
} }
return pInstance; return pInstance;
} }
static inline PERF_COUNTER_BLOCK *getObjectTypeCounterBlock( ALWAYS_INLINE
static PERF_COUNTER_BLOCK *getObjectTypeCounterBlock(
PERF_DATA_BLOCK *pDataBlock, PERF_DATA_BLOCK *pDataBlock,
PERF_OBJECT_TYPE *pObjectType PERF_OBJECT_TYPE *pObjectType
) { ) {
if(unlikely(!pObjectType))
return NULL;
PERF_COUNTER_BLOCK *pCounterBlock = (PERF_COUNTER_BLOCK *)((PBYTE)pObjectType + pObjectType->DefinitionLength); PERF_COUNTER_BLOCK *pCounterBlock = (PERF_COUNTER_BLOCK *)((PBYTE)pObjectType + pObjectType->DefinitionLength);
if(pCounterBlock && (!isValidPointer(pDataBlock, pCounterBlock) || !isValidStructure(pDataBlock, pCounterBlock, pCounterBlock->ByteLength))) { if(pCounterBlock && (!isValidPointer(pDataBlock, pCounterBlock) || !isValidStructure(pDataBlock, pCounterBlock, pCounterBlock->ByteLength))) {
nd_log(NDLS_COLLECTORS, NDLP_ERR, nd_log(NDLS_COLLECTORS, NDLP_ERR, "WINDOWS: PERFLIB: %s(): Invalid ObjectType CounterBlock!", __FUNCTION__);
"WINDOWS: PERFLIB: Invalid ObjectType CounterBlock!");
pCounterBlock = NULL; pCounterBlock = NULL;
} }
return pCounterBlock; return pCounterBlock;
} }
static inline PERF_COUNTER_BLOCK *getInstanceCounterBlock( ALWAYS_INLINE
static PERF_COUNTER_BLOCK *getInstanceCounterBlock(
PERF_DATA_BLOCK *pDataBlock, PERF_DATA_BLOCK *pDataBlock,
PERF_OBJECT_TYPE *pObjectType, PERF_OBJECT_TYPE *pObjectType __maybe_unused,
PERF_INSTANCE_DEFINITION *pInstance PERF_INSTANCE_DEFINITION *pInstance
) { ) {
(void)pObjectType; if(unlikely(!pInstance))
return NULL;
PERF_COUNTER_BLOCK *pCounterBlock = (PERF_COUNTER_BLOCK *)((PBYTE)pInstance + pInstance->ByteLength); PERF_COUNTER_BLOCK *pCounterBlock = (PERF_COUNTER_BLOCK *)((PBYTE)pInstance + pInstance->ByteLength);
if(pCounterBlock && (!isValidPointer(pDataBlock, pCounterBlock) || !isValidStructure(pDataBlock, pCounterBlock, pCounterBlock->ByteLength))) { if(pCounterBlock && (!isValidPointer(pDataBlock, pCounterBlock) || !isValidStructure(pDataBlock, pCounterBlock, pCounterBlock->ByteLength))) {
nd_log(NDLS_COLLECTORS, NDLP_ERR, nd_log(NDLS_COLLECTORS, NDLP_ERR, "WINDOWS: PERFLIB: %s(): Invalid Instance CounterBlock!", __FUNCTION__);
"WINDOWS: PERFLIB: Invalid Instance CounterBlock!");
pCounterBlock = NULL; pCounterBlock = NULL;
} }
return pCounterBlock; return pCounterBlock;
} }
inline PERF_INSTANCE_DEFINITION *getInstanceByPosition(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType, DWORD instancePosition) { ALWAYS_INLINE
PERF_INSTANCE_DEFINITION *getInstanceByPosition(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType, DWORD instancePosition) {
PERF_INSTANCE_DEFINITION *pi = NULL; PERF_INSTANCE_DEFINITION *pi = NULL;
PERF_COUNTER_BLOCK *pc = NULL; PERF_COUNTER_BLOCK *pc = NULL;
for(DWORD i = 0; i <= instancePosition ;i++) { for(DWORD i = 0; i <= instancePosition ;i++) {
@ -364,17 +377,19 @@ inline PERF_INSTANCE_DEFINITION *getInstanceByPosition(PERF_DATA_BLOCK *pDataBlo
return pi; return pi;
} }
static inline PERF_COUNTER_DEFINITION *getCounterDefinition(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType, PERF_COUNTER_DEFINITION *lastCounterDefinition) { ALWAYS_INLINE
PERF_COUNTER_DEFINITION *pCounterDefinition = NULL; static PERF_COUNTER_DEFINITION *getCounterDefinition(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType, PERF_COUNTER_DEFINITION *lastCounterDefinition) {
if(unlikely(!pObjectType))
return NULL;
PERF_COUNTER_DEFINITION *pCounterDefinition = NULL;
if(!lastCounterDefinition) if(!lastCounterDefinition)
pCounterDefinition = (PERF_COUNTER_DEFINITION *)((PBYTE)pObjectType + pObjectType->HeaderLength); pCounterDefinition = (PERF_COUNTER_DEFINITION *)((PBYTE)pObjectType + pObjectType->HeaderLength);
else else
pCounterDefinition = (PERF_COUNTER_DEFINITION *)((PBYTE)lastCounterDefinition + lastCounterDefinition->ByteLength); pCounterDefinition = (PERF_COUNTER_DEFINITION *)((PBYTE)lastCounterDefinition + lastCounterDefinition->ByteLength);
if(pCounterDefinition && (!isValidPointer(pDataBlock, pCounterDefinition) || !isValidStructure(pDataBlock, pCounterDefinition, pCounterDefinition->ByteLength))) { if(pCounterDefinition && (!isValidPointer(pDataBlock, pCounterDefinition) || !isValidStructure(pDataBlock, pCounterDefinition, pCounterDefinition->ByteLength))) {
nd_log(NDLS_COLLECTORS, NDLP_ERR, nd_log(NDLS_COLLECTORS, NDLP_ERR, "WINDOWS: PERFLIB: %s(): Invalid Counter Definition!", __FUNCTION__);
"WINDOWS: PERFLIB: Invalid Counter Definition!");
pCounterDefinition = NULL; pCounterDefinition = NULL;
} }
@ -383,7 +398,8 @@ static inline PERF_COUNTER_DEFINITION *getCounterDefinition(PERF_DATA_BLOCK *pDa
// -------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------
static inline BOOL getEncodedStringToUTF8(char *dst, size_t dst_len, DWORD CodePage, char *start, DWORD length) { ALWAYS_INLINE
static BOOL getEncodedStringToUTF8(char *dst, size_t dst_len, DWORD CodePage, char *start, DWORD length) {
static __thread wchar_t unicode[PERFLIB_MAX_NAME_LENGTH]; static __thread wchar_t unicode[PERFLIB_MAX_NAME_LENGTH];
WCHAR *tempBuffer; // Temporary buffer for Unicode data WCHAR *tempBuffer; // Temporary buffer for Unicode data
@ -411,29 +427,34 @@ static inline BOOL getEncodedStringToUTF8(char *dst, size_t dst_len, DWORD CodeP
return TRUE; return TRUE;
} }
inline BOOL getInstanceName(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType, PERF_INSTANCE_DEFINITION *pInstance, ALWAYS_INLINE
BOOL getInstanceName(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType, PERF_INSTANCE_DEFINITION *pInstance,
char *buffer, size_t bufferLen) { char *buffer, size_t bufferLen) {
(void)pDataBlock; (void)pDataBlock;
if (!pInstance || !buffer || !bufferLen) return FALSE; if (!pObjectType || !pInstance || !buffer || !bufferLen)
return FALSE;
return getEncodedStringToUTF8(buffer, bufferLen, pObjectType->CodePage, return getEncodedStringToUTF8(buffer, bufferLen, pObjectType->CodePage,
((char *)pInstance + pInstance->NameOffset), pInstance->NameLength); ((char *)pInstance + pInstance->NameOffset), pInstance->NameLength);
} }
inline BOOL getSystemName(PERF_DATA_BLOCK *pDataBlock, char *buffer, size_t bufferLen) { ALWAYS_INLINE
BOOL getSystemName(PERF_DATA_BLOCK *pDataBlock, char *buffer, size_t bufferLen) {
return getEncodedStringToUTF8(buffer, bufferLen, 0, return getEncodedStringToUTF8(buffer, bufferLen, 0,
((char *)pDataBlock + pDataBlock->SystemNameOffset), pDataBlock->SystemNameLength); ((char *)pDataBlock + pDataBlock->SystemNameOffset), pDataBlock->SystemNameLength);
} }
inline bool ObjectTypeHasInstances(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType) { ALWAYS_INLINE
BOOL ObjectTypeHasInstances(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType) {
(void)pDataBlock; (void)pDataBlock;
return pObjectType->NumInstances != PERF_NO_INSTANCES && pObjectType->NumInstances > 0; return pObjectType && pObjectType->NumInstances != PERF_NO_INSTANCES && pObjectType->NumInstances > 0 ? TRUE : FALSE;
} }
PERF_OBJECT_TYPE *perflibFindObjectTypeByName(PERF_DATA_BLOCK *pDataBlock, const char *name) { PERF_OBJECT_TYPE *perflibFindObjectTypeByName(PERF_DATA_BLOCK *pDataBlock, const char *name) {
PERF_OBJECT_TYPE* pObjectType = NULL; PERF_OBJECT_TYPE* pObjectType = NULL;
for(DWORD o = 0; o < pDataBlock->NumObjectTypes; o++) { for(DWORD o = 0; o < pDataBlock->NumObjectTypes; o++) {
pObjectType = getObjectType(pDataBlock, pObjectType); pObjectType = getObjectType(pDataBlock, pObjectType);
if(!pObjectType) break;
if(strcmp(name, RegistryFindNameByID(pObjectType->ObjectNameTitleIndex)) == 0) if(strcmp(name, RegistryFindNameByID(pObjectType->ObjectNameTitleIndex)) == 0)
return pObjectType; return pObjectType;
} }
@ -515,6 +536,9 @@ failed:
} }
bool perflibGetObjectCounter(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType, COUNTER_DATA *cd) { bool perflibGetObjectCounter(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType, COUNTER_DATA *cd) {
if (unlikely(!pObjectType))
goto cleanup;
PERF_COUNTER_DEFINITION *pCounterDefinition = NULL; PERF_COUNTER_DEFINITION *pCounterDefinition = NULL;
for(DWORD c = 0; c < pObjectType->NumCounters ;c++) { for(DWORD c = 0; c < pObjectType->NumCounters ;c++) {
pCounterDefinition = getCounterDefinition(pDataBlock, pObjectType, pCounterDefinition); pCounterDefinition = getCounterDefinition(pDataBlock, pObjectType, pCounterDefinition);
@ -544,6 +568,7 @@ bool perflibGetObjectCounter(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObj
return cd->updated; return cd->updated;
} }
cleanup:
cd->previous = cd->current; cd->previous = cd->current;
cd->current = RAW_DATA_EMPTY; cd->current = RAW_DATA_EMPTY;
cd->updated = false; cd->updated = false;

View file

@ -71,7 +71,7 @@ int perflibQueryAndTraverse(DWORD id,
perflib_counter_cb counterCb, perflib_counter_cb counterCb,
void *data); void *data);
bool ObjectTypeHasInstances(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType); BOOL ObjectTypeHasInstances(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType);
BOOL getInstanceName(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType, PERF_INSTANCE_DEFINITION *pInstance, BOOL getInstanceName(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType, PERF_INSTANCE_DEFINITION *pInstance,
char *buffer, size_t bufferLen); char *buffer, size_t bufferLen);