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);