pcp/pcp-7.1.5-OOB-pmDecodeInstance.patch
Jan Kurik 4d55c1806b
Backport remaining private-pcp security hardening fixes for 7.1.5-6
Add patches for pmieconf/pmlogmv command injection, libpcp PDU decode
OOB guards, timezone validation, pmdaroot peer credentials, and pmproxy
REST CERT_REQD and logger authentication hardening.

Resolves: RHEL-213756 CVE-2026-16531
Resolves: RHEL-213746 CVE-2026-16530
Resolves: RHEL-213726 CVE-2026-16529
Resolves: RHEL-213717 CVE-2026-16527
Resolves: RHEL-213692 CVE-2026-16526
Resolves: RHEL-213661 CVE-2026-16524
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-12 12:10:43 +02:00

59 lines
2.6 KiB
Diff

From b743fc5879 Mon Sep 17 00:00:00 2001
From: Nathan Scott <nathans@redhat.com>
Subject: [PATCH] libpcp: fix OOB read in __pmDecodeInstance (CWE-125/195)
The __pmDecodeInstance() loop advances ip by the PDU alignment-padded
entry size after each instance. When namelen % 4 != 0, the padding
advance can push ip past pdu_end. The existing bounds check casts the
pointer difference to size_t: (size_t)(pdu_end - (char *)ip). When ip
is past pdu_end, this produces a negative ptrdiff_t that wraps to a
very large size_t, causing both bounds checks to silently pass.
Execution falls through to memcpy reading past the PDU buffer.
Fix: add an explicit signed pointer guard at the top of each loop
iteration — if ((char *)ip >= pdu_end) — before the size_t cast.
This ensures the subsequent unsigned comparison is always valid.
Reported-by: Francisco Alisson Bezerra, TIM Security Red Team
Reported-by: Lucas Gabriel Alves, TIM Security Red Team
Reported-by: Massimiliano Brolli, TIM Security Red Team
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---
diff --git a/src/libpcp/src/p_instance.c b/src/libpcp/src/p_instance.c
index de05972f14..8c3c125c48 100644
--- a/src/libpcp/src/p_instance.c
+++ b/src/libpcp/src/p_instance.c
@@ -289,6 +289,13 @@ __pmDecodeInstance(__pmPDU *pdubuf, pmInResult **result)
pdu_used = (char *)&pp->rest[0];
for (i = j = 0; i < res->numinst; i++) {
ip = (instlist_t *)&pp->rest[j/sizeof(__pmPDU)];
+ if ((char *)ip >= pdu_end) {
+ if (pmDebugOptions.pdu)
+ fprintf(stderr, "%s: PM_ERR_IPC: inst[%d] ip past pdu_end\n",
+ __FUNCTION__, i);
+ sts = PM_ERR_IPC;
+ goto badsts;
+ }
if (sizeof(instlist_t) - sizeof(ip->name) > (size_t)(pdu_end - (char *)ip)) {
if (pmDebugOptions.pdu) {
fprintf(stderr, "__pmDecodeInstance: PM_ERR_IPC: sizeof(instlist_t) %d - sizeof(name) %d > remainder %d\n",
diff --git a/src/libpcp3/src/p_instance.c b/src/libpcp3/src/p_instance.c
index 6881ff37ef..7d836e75a0 100644
--- a/src/libpcp3/src/p_instance.c
+++ b/src/libpcp3/src/p_instance.c
@@ -290,6 +290,13 @@ __pmDecodeInstance(__pmPDU *pdubuf, pmInResult **result)
pdu_used = (char *)&pp->rest[0];
for (i = j = 0; i < res->numinst; i++) {
ip = (instlist_t *)&pp->rest[j/sizeof(__pmPDU)];
+ if ((char *)ip >= pdu_end) {
+ if (pmDebugOptions.pdu)
+ fprintf(stderr, "%s: PM_ERR_IPC: inst[%d] ip past pdu_end\n",
+ __FUNCTION__, i);
+ sts = PM_ERR_IPC;
+ goto badsts;
+ }
if (sizeof(instlist_t) - sizeof(ip->name) > (size_t)(pdu_end - (char *)ip)) {
if (pmDebugOptions.pdu) {
fprintf(stderr, "__pmDecodeInstance: PM_ERR_IPC: sizeof(instlist_t) %d - sizeof(name) %d > remainder %d\n",