@cryptotaxi247 / netdata-1 / commits / d57c5c503

more perflib error checking (#19631)

* more perflib error checking * more checks * fix comparison

Costa Tsaousis committed Feb 12, 2025 at 21:36 UTC d57c5c503b5ffffc77e74dcfc672b29a4ffcfb02
2 files changed +65 -40
src/libnetdata/os/windows-perflib/perflib.c
+64 -39
@@ -236,20 +236,22 @@ static BOOL getCounterData(
236
237 // --------------------------------------------------------------------------------------------------------------------
238
239 -static inline BOOL isValidPointer(PERF_DATA_BLOCK *pDataBlock __maybe_unused, void *ptr __maybe_unused) {
240 -#ifdef NETDATA_INTERNAL_CHECKS
241 - return (PBYTE)ptr >= (PBYTE)pDataBlock + pDataBlock->TotalByteLength ? FALSE : TRUE;
242 -#else
243 - return TRUE;
244 -#endif
239 +ALWAYS_INLINE
240 +static BOOL isValidPointer(PERF_DATA_BLOCK *pDataBlock, void *ptr) {
241 + return
242 + !pDataBlock ||
243 + (PBYTE)ptr < (PBYTE)pDataBlock ||
244 + (PBYTE)ptr >= (PBYTE)pDataBlock + pDataBlock->TotalByteLength ? FALSE : TRUE;
245 }
246
247 -static inline BOOL isValidStructure(PERF_DATA_BLOCK *pDataBlock __maybe_unused, void *ptr __maybe_unused, size_t length __maybe_unused) {
248 -#ifdef NETDATA_INTERNAL_CHECKS
249 - return (PBYTE)ptr + length > (PBYTE)pDataBlock + pDataBlock->TotalByteLength ? FALSE : TRUE;
250 -#else
251 - return TRUE;
252 -#endif
247 +ALWAYS_INLINE
248 +static BOOL isValidStructure(PERF_DATA_BLOCK *pDataBlock, void *ptr, size_t length) {
249 + return
250 + !pDataBlock ||
251 + !length || length > pDataBlock->TotalByteLength ||
252 + (PBYTE)ptr < (PBYTE)pDataBlock ||
253 + (PBYTE)ptr > (PBYTE)ptr + length || // Check for pointer arithmetic overflow
254 + (PBYTE)ptr + length > (PBYTE)pDataBlock + pDataBlock->TotalByteLength ? FALSE : TRUE;
255 }
256
257 static inline PERF_DATA_BLOCK *getDataBlock(BYTE *pBuffer) {
@@ -273,7 +275,8 @@ static inline PERF_DATA_BLOCK *getDataBlock(BYTE *pBuffer) {
275 return pDataBlock;
276 }
277
276 -static inline PERF_OBJECT_TYPE *getObjectType(PERF_DATA_BLOCK* pDataBlock, PERF_OBJECT_TYPE *lastObjectType) {
278 +ALWAYS_INLINE
279 +static PERF_OBJECT_TYPE *getObjectType(PERF_DATA_BLOCK* pDataBlock, PERF_OBJECT_TYPE *lastObjectType) {
280 PERF_OBJECT_TYPE* pObjectType = NULL;
281
282 if(!lastObjectType)
@@ -282,18 +285,20 @@ static inline PERF_OBJECT_TYPE *getObjectType(PERF_DATA_BLOCK* pDataBlock, PERF_
285 pObjectType = (PERF_OBJECT_TYPE *)((PBYTE)lastObjectType + lastObjectType->TotalByteLength);
286
287 if(pObjectType && (!isValidPointer(pDataBlock, pObjectType) || !isValidStructure(pDataBlock, pObjectType, pObjectType->TotalByteLength))) {
285 - nd_log(NDLS_COLLECTORS, NDLP_ERR,
286 - "WINDOWS: PERFLIB: Invalid ObjectType!");
288 + nd_log(NDLS_COLLECTORS, NDLP_ERR, "WINDOWS: PERFLIB: %s(): Invalid ObjectType!", __FUNCTION__);
289 pObjectType = NULL;
290 }
291
292 return pObjectType;
293 }
294
293 -inline PERF_OBJECT_TYPE *getObjectTypeByIndex(PERF_DATA_BLOCK *pDataBlock, DWORD ObjectNameTitleIndex) {
295 +ALWAYS_INLINE
296 +PERF_OBJECT_TYPE *getObjectTypeByIndex(PERF_DATA_BLOCK *pDataBlock, DWORD ObjectNameTitleIndex) {
297 PERF_OBJECT_TYPE *po = NULL;
298 for(DWORD o = 0; o < pDataBlock->NumObjectTypes ; o++) {
299 po = getObjectType(pDataBlock, po);
300 + if(!po) break;
301 +
302 if(po->ObjectNameTitleIndex == ObjectNameTitleIndex)
303 return po;
304 }
@@ -301,60 +306,68 @@ inline PERF_OBJECT_TYPE *getObjectTypeByIndex(PERF_DATA_BLOCK *pDataBlock, DWORD
306 return NULL;
307 }
308
304 -static inline PERF_INSTANCE_DEFINITION *getInstance(
309 +ALWAYS_INLINE
310 +static PERF_INSTANCE_DEFINITION *getInstance(
311 PERF_DATA_BLOCK *pDataBlock,
312 PERF_OBJECT_TYPE *pObjectType,
313 PERF_COUNTER_BLOCK *lastCounterBlock
314 ) {
309 - PERF_INSTANCE_DEFINITION *pInstance;
315 + if(unlikely(!pObjectType))
316 + return NULL;
317
318 + PERF_INSTANCE_DEFINITION *pInstance;
319 if(!lastCounterBlock)
320 pInstance = (PERF_INSTANCE_DEFINITION *)((PBYTE)pObjectType + pObjectType->DefinitionLength);
321 else
322 pInstance = (PERF_INSTANCE_DEFINITION *)((PBYTE)lastCounterBlock + lastCounterBlock->ByteLength);
323
324 if(pInstance && (!isValidPointer(pDataBlock, pInstance) || !isValidStructure(pDataBlock, pInstance, pInstance->ByteLength))) {
317 - nd_log(NDLS_COLLECTORS, NDLP_ERR,
318 - "WINDOWS: PERFLIB: Invalid Instance Definition!");
325 + nd_log(NDLS_COLLECTORS, NDLP_ERR, "WINDOWS: PERFLIB: %s(): Invalid Instance Definition!", __FUNCTION__);
326 pInstance = NULL;
327 }
328
329 return pInstance;
330 }
331
325 -static inline PERF_COUNTER_BLOCK *getObjectTypeCounterBlock(
332 +ALWAYS_INLINE
333 +static PERF_COUNTER_BLOCK *getObjectTypeCounterBlock(
334 PERF_DATA_BLOCK *pDataBlock,
335 PERF_OBJECT_TYPE *pObjectType
336 ) {
337 + if(unlikely(!pObjectType))
338 + return NULL;
339 +
340 PERF_COUNTER_BLOCK *pCounterBlock = (PERF_COUNTER_BLOCK *)((PBYTE)pObjectType + pObjectType->DefinitionLength);
341
342 if(pCounterBlock && (!isValidPointer(pDataBlock, pCounterBlock) || !isValidStructure(pDataBlock, pCounterBlock, pCounterBlock->ByteLength))) {
332 - nd_log(NDLS_COLLECTORS, NDLP_ERR,
333 - "WINDOWS: PERFLIB: Invalid ObjectType CounterBlock!");
343 + nd_log(NDLS_COLLECTORS, NDLP_ERR, "WINDOWS: PERFLIB: %s(): Invalid ObjectType CounterBlock!", __FUNCTION__);
344 pCounterBlock = NULL;
345 }
346
347 return pCounterBlock;
348 }
349
340 -static inline PERF_COUNTER_BLOCK *getInstanceCounterBlock(
350 +ALWAYS_INLINE
351 +static PERF_COUNTER_BLOCK *getInstanceCounterBlock(
352 PERF_DATA_BLOCK *pDataBlock,
342 - PERF_OBJECT_TYPE *pObjectType,
353 + PERF_OBJECT_TYPE *pObjectType __maybe_unused,
354 PERF_INSTANCE_DEFINITION *pInstance
355 ) {
345 - (void)pObjectType;
356 + if(unlikely(!pInstance))
357 + return NULL;
358 +
359 PERF_COUNTER_BLOCK *pCounterBlock = (PERF_COUNTER_BLOCK *)((PBYTE)pInstance + pInstance->ByteLength);
360
361 if(pCounterBlock && (!isValidPointer(pDataBlock, pCounterBlock) || !isValidStructure(pDataBlock, pCounterBlock, pCounterBlock->ByteLength))) {
349 - nd_log(NDLS_COLLECTORS, NDLP_ERR,
350 - "WINDOWS: PERFLIB: Invalid Instance CounterBlock!");
362 + nd_log(NDLS_COLLECTORS, NDLP_ERR, "WINDOWS: PERFLIB: %s(): Invalid Instance CounterBlock!", __FUNCTION__);
363 pCounterBlock = NULL;
364 }
365
366 return pCounterBlock;
367 }
368
357 -inline PERF_INSTANCE_DEFINITION *getInstanceByPosition(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType, DWORD instancePosition) {
369 +ALWAYS_INLINE
370 +PERF_INSTANCE_DEFINITION *getInstanceByPosition(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType, DWORD instancePosition) {
371 PERF_INSTANCE_DEFINITION *pi = NULL;
372 PERF_COUNTER_BLOCK *pc = NULL;
373 for(DWORD i = 0; i <= instancePosition ;i++) {
@@ -364,17 +377,19 @@ inline PERF_INSTANCE_DEFINITION *getInstanceByPosition(PERF_DATA_BLOCK *pDataBlo
377 return pi;
378 }
379
367 -static inline PERF_COUNTER_DEFINITION *getCounterDefinition(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType, PERF_COUNTER_DEFINITION *lastCounterDefinition) {
368 - PERF_COUNTER_DEFINITION *pCounterDefinition = NULL;
380 +ALWAYS_INLINE
381 +static PERF_COUNTER_DEFINITION *getCounterDefinition(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType, PERF_COUNTER_DEFINITION *lastCounterDefinition) {
382 + if(unlikely(!pObjectType))
383 + return NULL;
384
385 + PERF_COUNTER_DEFINITION *pCounterDefinition = NULL;
386 if(!lastCounterDefinition)
387 pCounterDefinition = (PERF_COUNTER_DEFINITION *)((PBYTE)pObjectType + pObjectType->HeaderLength);
388 else
389 pCounterDefinition = (PERF_COUNTER_DEFINITION *)((PBYTE)lastCounterDefinition + lastCounterDefinition->ByteLength);
390
391 if(pCounterDefinition && (!isValidPointer(pDataBlock, pCounterDefinition) || !isValidStructure(pDataBlock, pCounterDefinition, pCounterDefinition->ByteLength))) {
376 - nd_log(NDLS_COLLECTORS, NDLP_ERR,
377 - "WINDOWS: PERFLIB: Invalid Counter Definition!");
392 + nd_log(NDLS_COLLECTORS, NDLP_ERR, "WINDOWS: PERFLIB: %s(): Invalid Counter Definition!", __FUNCTION__);
393 pCounterDefinition = NULL;
394 }
395
@@ -383,7 +398,8 @@ static inline PERF_COUNTER_DEFINITION *getCounterDefinition(PERF_DATA_BLOCK *pDa
398
399 // --------------------------------------------------------------------------------------------------------------------
400
386 -static inline BOOL getEncodedStringToUTF8(char *dst, size_t dst_len, DWORD CodePage, char *start, DWORD length) {
401 +ALWAYS_INLINE
402 +static BOOL getEncodedStringToUTF8(char *dst, size_t dst_len, DWORD CodePage, char *start, DWORD length) {
403 static __thread wchar_t unicode[PERFLIB_MAX_NAME_LENGTH];
404
405 WCHAR *tempBuffer; // Temporary buffer for Unicode data
@@ -411,29 +427,34 @@ static inline BOOL getEncodedStringToUTF8(char *dst, size_t dst_len, DWORD CodeP
427 return TRUE;
428 }
429
414 -inline BOOL getInstanceName(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType, PERF_INSTANCE_DEFINITION *pInstance,
430 +ALWAYS_INLINE
431 +BOOL getInstanceName(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType, PERF_INSTANCE_DEFINITION *pInstance,
432 char *buffer, size_t bufferLen) {
433 (void)pDataBlock;
417 - if (!pInstance || !buffer || !bufferLen) return FALSE;
434 + if (!pObjectType || !pInstance || !buffer || !bufferLen)
435 + return FALSE;
436
437 return getEncodedStringToUTF8(buffer, bufferLen, pObjectType->CodePage,
438 ((char *)pInstance + pInstance->NameOffset), pInstance->NameLength);
439 }
440
423 -inline BOOL getSystemName(PERF_DATA_BLOCK *pDataBlock, char *buffer, size_t bufferLen) {
441 +ALWAYS_INLINE
442 +BOOL getSystemName(PERF_DATA_BLOCK *pDataBlock, char *buffer, size_t bufferLen) {
443 return getEncodedStringToUTF8(buffer, bufferLen, 0,
444 ((char *)pDataBlock + pDataBlock->SystemNameOffset), pDataBlock->SystemNameLength);
445 }
446
428 -inline bool ObjectTypeHasInstances(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType) {
447 +ALWAYS_INLINE
448 +BOOL ObjectTypeHasInstances(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType) {
449 (void)pDataBlock;
430 - return pObjectType->NumInstances != PERF_NO_INSTANCES && pObjectType->NumInstances > 0;
450 + return pObjectType && pObjectType->NumInstances != PERF_NO_INSTANCES && pObjectType->NumInstances > 0 ? TRUE : FALSE;
451 }
452
453 PERF_OBJECT_TYPE *perflibFindObjectTypeByName(PERF_DATA_BLOCK *pDataBlock, const char *name) {
454 PERF_OBJECT_TYPE* pObjectType = NULL;
455 for(DWORD o = 0; o < pDataBlock->NumObjectTypes; o++) {
456 pObjectType = getObjectType(pDataBlock, pObjectType);
457 + if(!pObjectType) break;
458 if(strcmp(name, RegistryFindNameByID(pObjectType->ObjectNameTitleIndex)) == 0)
459 return pObjectType;
460 }
@@ -515,6 +536,9 @@ failed:
536 }
537
538 bool perflibGetObjectCounter(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType, COUNTER_DATA *cd) {
539 + if (unlikely(!pObjectType))
540 + goto cleanup;
541 +
542 PERF_COUNTER_DEFINITION *pCounterDefinition = NULL;
543 for(DWORD c = 0; c < pObjectType->NumCounters ;c++) {
544 pCounterDefinition = getCounterDefinition(pDataBlock, pObjectType, pCounterDefinition);
@@ -544,6 +568,7 @@ bool perflibGetObjectCounter(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObj
568 return cd->updated;
569 }
570
571 +cleanup:
572 cd->previous = cd->current;
573 cd->current = RAW_DATA_EMPTY;
574 cd->updated = false;
src/libnetdata/os/windows-perflib/perflib.h
+1 -1
@@ -71,7 +71,7 @@ int perflibQueryAndTraverse(DWORD id,
71 perflib_counter_cb counterCb,
72 void *data);
73
74 -bool ObjectTypeHasInstances(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType);
74 +BOOL ObjectTypeHasInstances(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType);
75
76 BOOL getInstanceName(PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectType, PERF_INSTANCE_DEFINITION *pInstance,
77 char *buffer, size_t bufferLen);