Vulnerability Description: CWE-190: Integer Overflow or Wraparound
Software Version: 7.1.3
CVSS: 7.5
Severity: High
NVD: https://nvd.nist.gov/vuln/detail/cve-2026-16529
Credits: Francisco Alisson Bezerra, Lucas Gabriel Alves, Massimiliano Brolli
A signed integer overflow in __pmGetPDU() (pdu.c:661) permanently corrupts the process-wide static variable maxsize, rendering the affected daemon unable to read any PDU for the remainder of its lifetime. No authentication or prior session state is required. When php->len = 0x7FFFFFFF, the expression PDU_CHUNK * (1 + php->len / PDU_CHUNK) overflows to -2147483648. Every subsequent call to __pmFindPDUBuf(maxsize) returns NULL, causing silent connection failures. Two attack vectors were confirmed: pmlogger TCP 4330 (conditional on PMLOGGER_LOCAL being unset) and pmcd TCP 44321 during SASL negotiation.
Prerequisites: Vector 1 (pmlogger TCP 4330): Default installation, no credentials required. Bound to loopback by default; remotely exploitable only if PMLOGGER_LOCAL is unset. Vector 2 (pmcd TCP 44321): SASL configured (standard in major distro packages). Bound to loopback by default; remotely exploitable only if the operator altered the binding configuration.
Step-by-step Instructions and PoC
__pmGetPDU() in pdu.c maintains a process-wide static variable maxsize (initialized to PDU_CHUNK = 1024) that tracks the largest PDU buffer allocated in the current process lifetime. When a PDU arrives with php->len > maxsize, the function computes a new size with: tmpsize = PDU_CHUNK * (1 + php->len / PDU_CHUNK). With php->len = 0x7FFFFFFF, this expression overflows signed int, producing tmpsize = -2147483648.
maxsize is then permanently set to this negative value. Every subsequent call to __pmFindPDUBuf(maxsize) returns NULL immediately (negative size is invalid), causing all future PDU read operations in the process to fail silently. The affected daemon continues running but cannot receive any further PDUs - archive writing stops, client connections fail, and no recovery is possible without a service restart.
Affected Source Files and Lines
src/libpcp/src/pdu.c:655-670: __pmGetPDU() - integer overflow at line 661; maxsize corrupted at line 662
Image 1 - __pmGetPDU() (pdu.c:655). Highlighted lines 661-662: multiplication overflows when php->len = 0x7FFFFFFF.
Affected Endpoints
TCP 4330: pmlogger control port (Vector 1)
TCP 44321: pmcd SASL negotiation (Vector 2)
The proof-of-concept (poc_pmlogger_dos.py) connects to pmlogger on the control port (TCP 4330), receives the initial challenge, then sends a PDU_LOG_CONTROL header with len=0x7FFFFFFF. The multiplication overflow in __pmGetPDU() permanently corrupts the static maxsize variable, preventing pmlogger from allocating PDU buffers for any subsequent request. A second valid PDU sent immediately after confirms the persistent DoS: pmlogger no longer responds to any client.
Image 2 - Connection to a local instance of pmlogger.
Image 3 - Execution of the proof-of-concept.
Image 4 - pmlogger in DoS state (does not accept connections anymore).
Image 5 - Bad allocations logs generated for pmlogger.
Security Impact
The vulnerability can cause a complete denial of service of the PCP monitoring infrastructure. All client connections fail, metric collection stops, PMDA agents disconnect, and no new agents can be loaded. In addition, pmlogger ceases archive recording and pmlc becomes unable to perform management operations, requiring a service restart to restore functionality.