diff --git a/pcp-6.3.7-OOB-pmDecodeInstance.patch b/pcp-6.3.7-OOB-pmDecodeInstance.patch new file mode 100644 index 0000000..773d2e0 --- /dev/null +++ b/pcp-6.3.7-OOB-pmDecodeInstance.patch @@ -0,0 +1,41 @@ +From b743fc5879 Mon Sep 17 00:00:00 2001 +From: Nathan Scott +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) + +--- +diff --git a/src/libpcp/src/p_instance.c b/src/libpcp/src/p_instance.c +index 6881ff37ef..7d836e75a0 100644 +--- a/src/libpcp/src/p_instance.c ++++ b/src/libpcp/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", diff --git a/pcp-6.3.7-OOB-pmDecodeLabel.patch b/pcp-6.3.7-OOB-pmDecodeLabel.patch new file mode 100644 index 0000000..d515502 --- /dev/null +++ b/pcp-6.3.7-OOB-pmDecodeLabel.patch @@ -0,0 +1,39 @@ +From e512482e7d Mon Sep 17 00:00:00 2001 +From: Nathan Scott +Subject: [PATCH] libpcp: fix OOB read in __pmDecodeLabel via negative jsonoff (CWE-125) + +The bounds check 'if (pdu_length < jsonoff + jsonlen)' uses signed +arithmetic. When jsonoff is negative (high bit set after ntohl) and +jsonlen is a small positive value, their sum wraps to a small positive +number, passing the check. The subsequent memcpy reads from +label_pdu + jsonoff, an address before the start of the PDU buffer. + +Fix: reject negative jsonoff and jsonlen explicitly, then use unsigned +(size_t) arithmetic for the bounds check to prevent signed wraparound. + +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) + +--- +diff --git a/src/libpcp/src/p_label.c b/src/libpcp/src/p_label.c +index 10a348c8f0..95dbc86455 100644 +--- a/src/libpcp/src/p_label.c ++++ b/src/libpcp/src/p_label.c +@@ -446,10 +446,11 @@ __pmDecodeLabel(__pmPDU *pdubuf, int *ident, int *type, pmLabelSet **setsp, int + } + + /* check JSON content fits within the PDU bounds */ +- if (pdu_length < jsonoff + jsonlen) { ++ if (jsonoff < 0 || jsonlen < 0 || ++ (size_t)jsonoff + (size_t)jsonlen > pdu_length) { + if (pmDebugOptions.pdu) { +- fprintf(stderr, "__pmDecodeLabel: PM_ERR_IPC: labelset[%d] pdu_length %d < jsonoff %d + jsonlen %d\n", +- i, (int)pdu_length, jsonoff, jsonlen); ++ fprintf(stderr, "%s: PM_ERR_IPC: labelset[%d] pdu_length %d < jsonoff %d + jsonlen %d\n", ++ __FUNCTION__, i, (int)pdu_length, jsonoff, jsonlen); + } + goto corrupt; + } diff --git a/pcp-6.3.7-OOB-pmDecodeLogStatus.patch b/pcp-6.3.7-OOB-pmDecodeLogStatus.patch new file mode 100644 index 0000000..8a58ff7 --- /dev/null +++ b/pcp-6.3.7-OOB-pmDecodeLogStatus.patch @@ -0,0 +1,247 @@ +From 5366a546d6 Mon Sep 17 00:00:00 2001 +From: Nathan Scott +Subject: [PATCH] libpcp: fix OOB read in __pmDecodeLogStatus (CWE-125) + +For each of the six length-prefixed string fields in PDU_LOG_STATUS +(hostname, fqdn, timezone, zoneinfo for both pmcd and pmlogger), +strdup(p) was called before verifying that p+len falls within the +PDU buffer. strdup reads until a null byte, so a non-null-terminated +string causes reads past the PDU boundary into adjacent heap memory. + +Fix: for all six fields, move the p+len > pduend bounds check before +the string copy, and replace strdup(p) with strndup(p, len) to +respect the declared length regardless of null terminator presence. + +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) + +--- +diff --git a/src/libpcp/src/p_lstatus.c b/src/libpcp/src/p_lstatus.c +index d9053b5d1a..099ef7b5ff 100644 +--- a/src/libpcp/src/p_lstatus.c ++++ b/src/libpcp/src/p_lstatus.c +@@ -265,157 +265,157 @@ __pmDecodeLogStatus(__pmPDU *pdubuf, __pmLoggerStatus **result) + if (len == 0) + lsp->pmcd.hostname = NULL; + else { +- if (len > PM_MAX_HOSTNAMELEN) { +- /* cannot be longer than hostname in archive label */ ++ if (len < 0 || len > PM_MAX_HOSTNAMELEN) { ++ /* cannot be negative or longer than hostname in archive label */ + if (pmDebugOptions.pmlc || pmDebugOptions.pdu) +- fprintf(stderr, "__pmDecodeLogStatus: PM_ERR_IPC: pmcd.hostname too long (%d)\n", len); ++ fprintf(stderr, "__pmDecodeLogStatus: PM_ERR_IPC: invalid pmcd.hostname (%d)\n", len); + __pmFreeLogStatus(lsp, 1); + return PM_ERR_IPC; + } +- if ((lsp->pmcd.hostname = strdup(p)) == NULL) { ++ if (p + len > pduend) { ++ if (pmDebugOptions.pmlc || pmDebugOptions.pdu) ++ fprintf(stderr, "%s: PM_ERR_IPC: pmcd.hostname data[%ld] > PDU len (%d)\n", ++ __FUNCTION__, (long)(p + len - (char *)&pp->data[0]), pp->hdr.len); ++ __pmFreeLogStatus(lsp, 1); ++ return PM_ERR_IPC; ++ } ++ if ((lsp->pmcd.hostname = strndup(p, len)) == NULL) { + sts = -oserror(); + pmNoMem("__pmDecodeLogStatus: pmcd.hostname", len, PM_RECOV_ERR); + __pmFreeLogStatus(lsp, 1); + return sts; + } + p += len; +- if (p > pduend) { +- if (pmDebugOptions.pmlc || pmDebugOptions.pdu) +- fprintf(stderr, "__pmDecodeLogStatus: PM_ERR_IPC: pmcd.hostname data[%ld] > PDU len (%d)\n", +- (long)(p - (char *)&pp->data[0]), pp->hdr.len); +- __pmFreeLogStatus(lsp, 1); +- return PM_ERR_IPC; +- } + } + len = ntohl(pp->pmcd_fqdn_len); + if (len == 0) + lsp->pmcd.fqdn = NULL; + else { +- if (len > PM_MAX_HOSTNAMELEN) { +- /* cannot be longer than hostname in archive label */ ++ if (len < 0 || len > PM_MAX_HOSTNAMELEN) { ++ /* cannot be negative or longer than hostname in archive label */ + if (pmDebugOptions.pmlc || pmDebugOptions.pdu) +- fprintf(stderr, "__pmDecodeLogStatus: PM_ERR_IPC: pmcd.fqdn too long (%d)\n", len); ++ fprintf(stderr, "__pmDecodeLogStatus: PM_ERR_IPC: invalid pmcd.fqdn (%d)\n", len); + __pmFreeLogStatus(lsp, 1); + return PM_ERR_IPC; + } +- if ((lsp->pmcd.fqdn = strdup(p)) == NULL) { ++ if (p + len > pduend) { ++ if (pmDebugOptions.pmlc || pmDebugOptions.pdu) ++ fprintf(stderr, "%s: PM_ERR_IPC: pmcd.fqdn data[%ld] > PDU len (%d)\n", ++ __FUNCTION__, (long)(p + len - (char *)&pp->data[0]), pp->hdr.len); ++ __pmFreeLogStatus(lsp, 1); ++ return PM_ERR_IPC; ++ } ++ if ((lsp->pmcd.fqdn = strndup(p, len)) == NULL) { + sts = -oserror(); + pmNoMem("__pmDecodeLogStatus: pmcd.fqdn", len, PM_RECOV_ERR); + __pmFreeLogStatus(lsp, 1); + return sts; + } + p += len; +- if (p > pduend) { +- if (pmDebugOptions.pmlc || pmDebugOptions.pdu) +- fprintf(stderr, "__pmDecodeLogStatus: PM_ERR_IPC: pmcd.fqdn data[%ld] > PDU len (%d)\n", +- (long)(p - (char *)&pp->data[0]), pp->hdr.len); +- __pmFreeLogStatus(lsp, 1); +- return PM_ERR_IPC; +- } + } + len = ntohl(pp->pmcd_timezone_len); + if (len == 0) + lsp->pmcd.timezone = NULL; + else { +- if (len > PM_MAX_TIMEZONELEN) { +- /* cannot be longer than timezone in archive label */ ++ if (len < 0 || len > PM_MAX_TIMEZONELEN) { ++ /* cannot be negative or longer than timezone in archive label */ + if (pmDebugOptions.pmlc || pmDebugOptions.pdu) +- fprintf(stderr, "__pmDecodeLogStatus: PM_ERR_IPC: pmcd.timezone too long (%d)\n", len); ++ fprintf(stderr, "__pmDecodeLogStatus: PM_ERR_IPC: invalid pmcd.timezone (%d)\n", len); + __pmFreeLogStatus(lsp, 1); + return PM_ERR_IPC; + } +- if ((lsp->pmcd.timezone = strdup(p)) == NULL) { ++ if (p + len > pduend) { ++ if (pmDebugOptions.pmlc || pmDebugOptions.pdu) ++ fprintf(stderr, "%s: PM_ERR_IPC: pmcd.timezone data[%ld] > PDU len (%d)\n", ++ __FUNCTION__, (long)(p + len - (char *)&pp->data[0]), pp->hdr.len); ++ __pmFreeLogStatus(lsp, 1); ++ return PM_ERR_IPC; ++ } ++ if ((lsp->pmcd.timezone = strndup(p, len)) == NULL) { + sts = -oserror(); + pmNoMem("__pmDecodeLogStatus: pmcd.timezone", len, PM_RECOV_ERR); + __pmFreeLogStatus(lsp, 1); + return sts; + } + p += len; +- if (p > pduend) { +- if (pmDebugOptions.pmlc || pmDebugOptions.pdu) +- fprintf(stderr, "__pmDecodeLogStatus: PM_ERR_IPC: pmcd.timezone data[%ld] > PDU len (%d)\n", +- (long)(p - (char *)&pp->data[0]), pp->hdr.len); +- __pmFreeLogStatus(lsp, 1); +- return PM_ERR_IPC; +- } + } + len = ntohl(pp->pmcd_zoneinfo_len); + if (len == 0) + lsp->pmcd.zoneinfo = NULL; + else { +- if (len > PM_MAX_ZONEINFOLEN) { +- /* cannot be longer than zoneinfo in archive label */ ++ if (len < 0 || len > PM_MAX_ZONEINFOLEN) { ++ /* cannot be negative or longer than zoneinfo in archive label */ + if (pmDebugOptions.pmlc || pmDebugOptions.pdu) +- fprintf(stderr, "__pmDecodeLogStatus: PM_ERR_IPC: pmcd.zoneinfo too long (%d)\n", len); ++ fprintf(stderr, "__pmDecodeLogStatus: PM_ERR_IPC: invalid pmcd.zoneinfo (%d)\n", len); + __pmFreeLogStatus(lsp, 1); + return PM_ERR_IPC; + } +- if ((lsp->pmcd.zoneinfo = strdup(p)) == NULL) { ++ if (p + len > pduend) { ++ if (pmDebugOptions.pmlc || pmDebugOptions.pdu) ++ fprintf(stderr, "%s: PM_ERR_IPC: pmcd.zoneinfo data[%ld] > PDU len (%d)\n", ++ __FUNCTION__, (long)(p + len - (char *)&pp->data[0]), pp->hdr.len); ++ __pmFreeLogStatus(lsp, 1); ++ return PM_ERR_IPC; ++ } ++ if ((lsp->pmcd.zoneinfo = strndup(p, len)) == NULL) { + sts = -oserror(); + pmNoMem("__pmDecodeLogStatus: pmcd.zoneinfo", len, PM_RECOV_ERR); + __pmFreeLogStatus(lsp, 1); + return sts; + } + p += len; +- if (p > pduend) { +- if (pmDebugOptions.pmlc || pmDebugOptions.pdu) +- fprintf(stderr, "__pmDecodeLogStatus: PM_ERR_IPC: pmcd.zoneinfo data[%ld] > PDU len (%d)\n", +- (long)(p - (char *)&pp->data[0]), pp->hdr.len); +- __pmFreeLogStatus(lsp, 1); +- return PM_ERR_IPC; +- } + } + len = ntohl(pp->pmlogger_timezone_len); + if (len == 0) + lsp->pmlogger.timezone = NULL; + else { + if (len > PM_MAX_TIMEZONELEN) { +- /* cannot be longer than timezone in archive label */ ++ /* cannot be negative or longer than timezone in archive label */ + if (pmDebugOptions.pmlc || pmDebugOptions.pdu) + fprintf(stderr, "__pmDecodeLogStatusPM_ERR_IPC: : pmlogger.timezone too long (%d)\n", len); + __pmFreeLogStatus(lsp, 1); + return PM_ERR_IPC; + } +- if ((lsp->pmlogger.timezone = strdup(p)) == NULL) { ++ if (p + len > pduend) { ++ if (pmDebugOptions.pmlc || pmDebugOptions.pdu) ++ fprintf(stderr, "%s: PM_ERR_IPC: pmlogger.timezone data[%ld] > PDU len (%d)\n", ++ __FUNCTION__, (long)(p + len - (char *)&pp->data[0]), pp->hdr.len); ++ __pmFreeLogStatus(lsp, 1); ++ return PM_ERR_IPC; ++ } ++ if ((lsp->pmlogger.timezone = strndup(p, len)) == NULL) { + sts = -oserror(); + pmNoMem("__pmDecodeLogStatus: pmlogger.timezone", len, PM_RECOV_ERR); + __pmFreeLogStatus(lsp, 1); + return sts; + } + p += len; +- if (p > pduend) { +- if (pmDebugOptions.pmlc || pmDebugOptions.pdu) +- fprintf(stderr, "__pmDecodeLogStatus: PM_ERR_IPC: pmlogger.timezone data[%ld] > PDU len (%d)\n", +- (long)(p - (char *)&pp->data[0]), pp->hdr.len); +- __pmFreeLogStatus(lsp, 1); +- return PM_ERR_IPC; +- } + } + len = ntohl(pp->pmlogger_zoneinfo_len); + if (len == 0) + lsp->pmlogger.zoneinfo = NULL; + else { +- if (len > PM_MAX_ZONEINFOLEN) { +- /* cannot be longer than zoneinfo in archive label */ ++ if (len < 0 || len > PM_MAX_ZONEINFOLEN) { ++ /* cannot be negative or longer than zoneinfo in archive label */ + if (pmDebugOptions.pmlc || pmDebugOptions.pdu) +- fprintf(stderr, "__pmDecodeLogStatus: PM_ERR_IPC: pmlogger.zoneinfo too long (%d)\n", len); ++ fprintf(stderr, "__pmDecodeLogStatus: PM_ERR_IPC: invalid pmlogger.zoneinfo (%d)\n", len); ++ __pmFreeLogStatus(lsp, 1); ++ return PM_ERR_IPC; ++ } ++ if (p + len > pduend) { ++ if (pmDebugOptions.pmlc || pmDebugOptions.pdu) ++ fprintf(stderr, "%s: PM_ERR_IPC: pmlogger.zoneinfo data[%ld] > PDU len (%d)\n", ++ __FUNCTION__, (long)(p + len - (char *)&pp->data[0]), pp->hdr.len); + __pmFreeLogStatus(lsp, 1); + return PM_ERR_IPC; + } +- if ((lsp->pmlogger.zoneinfo = strdup(p)) == NULL) { ++ if ((lsp->pmlogger.zoneinfo = strndup(p, len)) == NULL) { + sts = -oserror(); + pmNoMem("__pmDecodeLogStatus: pmlogger.zoneinfo", len, PM_RECOV_ERR); + __pmFreeLogStatus(lsp, 1); + return sts; + } + p += len; +- if (p > pduend) { +- if (pmDebugOptions.pmlc || pmDebugOptions.pdu) +- fprintf(stderr, "__pmDecodeLogStatus: PM_ERR_IPC: pmlogger.zoneinfo data[%ld] > PDU len (%d)\n", +- (long)(p - (char *)&pp->data[0]), pp->hdr.len); +- __pmFreeLogStatus(lsp, 1); +- return PM_ERR_IPC; +- } + } + } + else if (version == LOG_PDU_VERSION2) { diff --git a/pcp-6.3.7-OOB-pmDiscoverDecodeMetaInDom.patch b/pcp-6.3.7-OOB-pmDiscoverDecodeMetaInDom.patch new file mode 100644 index 0000000..0d2198b --- /dev/null +++ b/pcp-6.3.7-OOB-pmDiscoverDecodeMetaInDom.patch @@ -0,0 +1,38 @@ +From 7f42013d33 Mon Sep 17 00:00:00 2001 +From: Nathan Scott +Subject: [PATCH] libpcp_web: add numinst overflow check in pmDiscoverDecodeMetaInDom (CWE-125/190) + +Defense-in-depth for the __pmLogLoadInDom streaming path fix (commit 1). +When __pmLogLoadInDom is called with acp=NULL from the pmproxy discover +code, a garbage numinst value read from a too-small buffer could be +passed to calloc(numinst, sizeof(char *)), causing an integer overflow +in the allocation size. + +Add explicit validation that numinst > 0 and does not overflow SIZE_MAX +before the calloc in pmDiscoverDecodeMetaInDom(). The primary fix +(rlen and numinst validation in __pmLogLoadInDom itself) prevents this +value from being garbage in the first place. + +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) + +--- +diff --git a/src/libpcp_web/src/discover.c b/src/libpcp_web/src/discover.c +index 0c7565340d..7363755746 100644 +--- a/src/libpcp_web/src/discover.c ++++ b/src/libpcp_web/src/discover.c +@@ -1954,6 +1954,11 @@ pmDiscoverDecodeMetaInDom(__int32_t *buf, int len, int type, __pmTimestamp *tsp, + */ + char **namelist; + int i; ++ if (lid.numinst <= 0 || ++ (size_t)lid.numinst > SIZE_MAX / sizeof(char *)) { ++ __pmFreeLogInDom(&lid); ++ return -EINVAL; ++ } + namelist = (char **)malloc(lid.numinst * sizeof(char *)); + if (namelist == NULL) { + pmNoMem("pmDiscoverDecodeMetaInDom", lid.numinst * sizeof(char *), PM_FATAL_ERR); diff --git a/pcp-6.3.7-OOB-pmLogLoadLabelSet.patch b/pcp-6.3.7-OOB-pmLogLoadLabelSet.patch new file mode 100644 index 0000000..14bd619 --- /dev/null +++ b/pcp-6.3.7-OOB-pmLogLoadLabelSet.patch @@ -0,0 +1,64 @@ +From ccd1bb1679 Mon Sep 17 00:00:00 2001 +From: Nathan Scott +Subject: [PATCH] libpcp: fix OOB read in __pmLogLoadLabelSet (CWE-125) + +__pmLogLoadLabelSet() reads timestamp, type, ident, and nsets fields +from tbuf at sequential offsets without checking that rlen is large +enough to contain them. When the pmproxy logger servlet delivers a +TYPE_LABEL record with hdr.len=13 (minimum accepted by the dispatcher), +rlen=1 and the function reads 20-24 bytes from a 1-byte buffer. + +Fix: add minimum-length guard at the top of __pmLogLoadLabelSet() +using LABELSET_V3_MINRLEN / LABELSET_V2_MINRLEN macros derived from +the on-disk __pmExtLabelSet_v3/v2 struct sizes (minus the len+type +header that rlen excludes). + +Test coverage will be added in a consolidated pducrash.c extension +covering vulns 9-13. + +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) + +--- +diff --git a/src/libpcp/src/e_labels.c b/src/libpcp/src/e_labels.c +index 8e94a112b0..169817266b 100644 +--- a/src/libpcp/src/e_labels.c ++++ b/src/libpcp/src/e_labels.c +@@ -56,6 +56,10 @@ typedef struct { + /* will be expanded if nsets > 0 */ + } __pmExtLabelSet_v2; + ++/* Minimum rlen (record body without len+type header) to read fixed fields */ ++#define LABELSET_V3_MINRLEN (sizeof(__pmExtLabelSet_v3) - 2 * sizeof(__int32_t)) ++#define LABELSET_V2_MINRLEN (sizeof(__pmExtLabelSet_v2) - 2 * sizeof(__int32_t)) ++ + /* + * pack a set of labels into a physical metadata record + * - lcp required to provide archive version +@@ -215,6 +219,23 @@ __pmLogLoadLabelSet(char *tbuf, int rlen, int rtype, __pmTimestamp *stamp, + *nsetsp = 0; + *labelsetsp = NULL; + ++ if (rtype == TYPE_LABEL_V2) { ++ if (rlen < (int)LABELSET_V2_MINRLEN) { ++ if (pmDebugOptions.logmeta) ++ fprintf(stderr, "%s: v2 rlen=%d too small (min=%d)\n", ++ __FUNCTION__, rlen, (int)LABELSET_V2_MINRLEN); ++ return PM_ERR_LOGREC; ++ } ++ } ++ else { ++ if (rlen < (int)LABELSET_V3_MINRLEN) { ++ if (pmDebugOptions.logmeta) ++ fprintf(stderr, "%s: v3 rlen=%d too small (min=%d)\n", ++ __FUNCTION__, rlen, (int)LABELSET_V3_MINRLEN); ++ return PM_ERR_LOGREC; ++ } ++ } ++ + k = 0; + if (rtype == TYPE_LABEL_V2) { + __pmLoadTimeval((__int32_t *)&tbuf[k], stamp); diff --git a/pcp-6.3.7-pducrash-oob-tests.patch b/pcp-6.3.7-pducrash-oob-tests.patch new file mode 100644 index 0000000..94693a8 --- /dev/null +++ b/pcp-6.3.7-pducrash-oob-tests.patch @@ -0,0 +1,158 @@ +From 7465d7cbdb Mon Sep 17 00:00:00 2001 +From: Nathan Scott +Subject: [PATCH] qa: extend pducrash with tests for vulns 9, 12, 13 + +Add three new test functions to pducrash.c exercising the OOB read +fixes: + +- decode_log_labelset: calls __pmLogLoadLabelSet with rlen=1 for both + V2 and V3 record types, verifying the minimum-length guard rejects + undersized records (vuln 9) + +- decode_log_status_oob: crafts a PDU_LOG_STATUS V3 with hostname_len + extending past the PDU boundary, verifying the bounds check now runs + before strdup (vuln 12) + +- decode_instance_overshoot: crafts a PDU_INSTANCE claiming 2 entries + but only containing 1, where the alignment-padded advance pushes ip + past pdu_end, verifying the signed pointer guard catches it (vuln 13) + +Co-Authored-By: Claude Opus 4.6 (1M context) + +--- +diff --git a/qa/513.out b/qa/513.out +index 7ccaa1f370..6ffe932b39 100644 +--- a/qa/513.out ++++ b/qa/513.out +@@ -277,6 +277,14 @@ QA output created by 513 + __pmLogLoadInDom: sts = -12373 (Corrupted record in a PCP archive) + [log_indom] checking out-of-range stridx with acp==NULL + __pmLogLoadInDom: sts = -12373 (Corrupted record in a PCP archive) ++[log_labelset] checking rlen too small for v3 header ++ __pmLogLoadLabelSet: sts = -12373 (Corrupted record in a PCP archive) ++[log_labelset] checking rlen too small for v2 header ++ __pmLogLoadLabelSet: sts = -12373 (Corrupted record in a PCP archive) ++[log_status_oob] checking hostname_len past PDU boundary ++ __pmDecodeLogStatus: sts = -12366 (IPC protocol failure) ++[instance_overshoot] checking alignment overshoot past pdu_end ++ __pmDecodeInstance: sts = -12366 (IPC protocol failure) + === filtered valgrind report === + Memcheck, a memory error detector + Command: src/pducrash +diff --git a/qa/src/pducrash.c b/qa/src/pducrash.c +index 76e1e0ce76..94a5f72d47 100644 +--- a/qa/src/pducrash.c ++++ b/qa/src/pducrash.c +@@ -1703,6 +1703,102 @@ decode_log_indom(const char *name) + } + } + ++/* ++ * Test __pmLogLoadLabelSet with undersized rlen (vuln 9). ++ */ ++static void ++decode_log_labelset(const char *name) ++{ ++ __pmTimestamp stamp; ++ pmLabelSet *sets = NULL; ++ int type, ident, nsets, sts; ++ char tiny[4]; ++ ++ fprintf(stderr, "[%s] checking rlen too small for v3 header\n", name); ++ memset(tiny, 0, sizeof(tiny)); ++ sts = __pmLogLoadLabelSet(tiny, 1, TYPE_LABEL, &stamp, &type, &ident, &nsets, &sets); ++ fprintf(stderr, " __pmLogLoadLabelSet: sts = %d (%s)\n", sts, pmErrStr(sts)); ++ if (sts >= 0 && sets) pmFreeLabelSets(sets, nsets); ++ ++ fprintf(stderr, "[%s] checking rlen too small for v2 header\n", name); ++ memset(tiny, 0, sizeof(tiny)); ++ sets = NULL; ++ sts = __pmLogLoadLabelSet(tiny, 1, TYPE_LABEL_V2, &stamp, &type, &ident, &nsets, &sets); ++ fprintf(stderr, " __pmLogLoadLabelSet: sts = %d (%s)\n", sts, pmErrStr(sts)); ++ if (sts >= 0 && sets) pmFreeLabelSets(sets, nsets); ++} ++ ++/* ++ * Test __pmDecodeLogStatus with hostname_len past PDU end (vuln 12). ++ */ ++static void ++decode_log_status_oob(const char *name) ++{ ++ __pmLoggerStatus *log; ++ int sts; ++ int save_ipc_version = __pmVersionIPC(0); ++ struct log_sts { ++ __pmPDUHdr hdr; ++ __int32_t buf[20+2*PM_LOG_MAXHOSTLEN+2*PM_TZ_MAXLEN]; ++ } *log_sts; ++ ++ __pmSetVersionIPC(0, LOG_PDU_VERSION3); ++ log_sts = (struct log_sts *)malloc(sizeof(*log_sts)); ++ ++ fprintf(stderr, "[%s] checking hostname_len past PDU boundary\n", name); ++ memset(log_sts, 0, sizeof(*log_sts)); ++ log_sts->hdr.len = 100; ++ log_sts->hdr.type = PDU_LOG_STATUS; ++ /* buf[13] is pmcd_hostname_len in V3 — set to extend past the PDU */ ++ log_sts->buf[13] = htonl(90); ++ sts = __pmDecodeLogStatus((__pmPDU *)log_sts, &log); ++ fprintf(stderr, " __pmDecodeLogStatus: sts = %d (%s)\n", sts, pmErrStr(sts)); ++ if (sts == 0) __pmFreeLogStatus(log, 1); ++ ++ free(log_sts); ++ __pmSetVersionIPC(0, save_ipc_version); ++} ++ ++/* ++ * Test __pmDecodeInstance with alignment-padding overshoot (vuln 13). ++ * Craft a PDU_INSTANCE with numinst=2 where the first entry's namelen ++ * causes the alignment-padded advance to push ip past pdu_end. ++ */ ++static void ++decode_instance_overshoot(const char *name) ++{ ++ pmInResult *inresult; ++ int sts; ++ struct { ++ __pmPDUHdr hdr; ++ pmInDom indom; ++ int numinst; ++ /* entry 0: inst + namelen + name (padded) */ ++ int inst0; ++ int namelen0; ++ char name0[4]; /* padded to 4 bytes */ ++ /* entry 1 would start here — but PDU ends before it */ ++ } *pdu; ++ ++ pdu = (typeof(pdu))malloc(sizeof(*pdu)); ++ ++ fprintf(stderr, "[%s] checking alignment overshoot past pdu_end\n", name); ++ memset(pdu, 0, sizeof(*pdu)); ++ pdu->hdr.len = sizeof(*pdu); ++ pdu->hdr.type = PDU_INSTANCE; ++ pdu->numinst = htonl(2); /* claim 2 entries but only room for 1 */ ++ pdu->inst0 = htonl(0); ++ pdu->namelen0 = htonl(3); /* 3 bytes + pad to 4 = alignment overshoot */ ++ pdu->name0[0] = 'a'; ++ pdu->name0[1] = 'b'; ++ pdu->name0[2] = 'c'; ++ sts = __pmDecodeInstance((__pmPDU *)pdu, &inresult); ++ fprintf(stderr, " __pmDecodeInstance: sts = %d (%s)\n", sts, pmErrStr(sts)); ++ if (sts >= 0) __pmFreeInResult(inresult); ++ ++ free(pdu); ++} ++ + typedef void (*decode_t)(const char *); + + struct pdu { +@@ -1738,6 +1834,9 @@ struct pdu { + { "desc_ids", decode_desc_ids }, + { "descs", decode_descs }, + { "log_indom", decode_log_indom }, ++ { "log_labelset", decode_log_labelset }, ++ { "log_status_oob", decode_log_status_oob }, ++ { "instance_overshoot", decode_instance_overshoot }, + }; + + int diff --git a/pcp-6.3.7-pmdaroot-peer-credentials.patch b/pcp-6.3.7-pmdaroot-peer-credentials.patch new file mode 100644 index 0000000..6ebcf1e --- /dev/null +++ b/pcp-6.3.7-pmdaroot-peer-credentials.patch @@ -0,0 +1,113 @@ +From 2a4bd9f81a Mon Sep 17 00:00:00 2001 +From: Nathan Scott +Subject: [PATCH] pmdaroot: add peer credential verification on Unix socket (CWE-403) + +Defense-in-depth for the FD_CLOEXEC fix: verify the UID of connecting +clients on the pmdaroot Unix socket using SO_PEERCRED (Linux) or +getpeereid (macOS/FreeBSD). Only root (UID 0) and the PCP service +user (typically 'pcp') are permitted to connect. Connections from +other UIDs are rejected with a log message. + +This prevents exploitation even if the pmdaroot socket fd were to +leak to an unprivileged process through a path not covered by +FD_CLOEXEC (e.g., direct socket file access). + +The PCP service UID is resolved once at startup via pmGetUsername() +and getpwnam(), cached in a static for use in the accept path. + +Co-Authored-By: Claude Opus 4.6 (1M context) + +--- +diff --git a/src/pmdas/root/root.c b/src/pmdas/root/root.c +index 2e65a2ea6d..7ec2e5bf9c 100644 +--- a/src/pmdas/root/root.c ++++ b/src/pmdas/root/root.c +@@ -23,6 +23,9 @@ + #include "docker.h" + #include "podman.h" + #include "domain.h" ++#if defined(HAVE_PWD_H) ++#include ++#endif + + #ifndef S_IRWXU + /* +@@ -37,6 +40,7 @@ static char socket_path[MAXPATHLEN]; + static __pmSockAddr *socket_addr; + static int socket_fd = -1; + static int pmcd_fd = -1; ++static uid_t pcp_uid; + + static __pmFdSet connected_fds; + int root_maximum_fd; +@@ -461,6 +465,42 @@ root_accept_client(void) + exit(1); + } + } ++#if defined(HAVE_STRUCT_UCRED) ++ { ++ struct ucred cred; ++ __pmSockLen len = sizeof(cred); ++ ++ if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &len) == 0) { ++ if (cred.uid != 0 && cred.uid != pcp_uid) { ++ pmNotifyErr(LOG_ERR, ++ "root_accept_client: rejected uid=%d (expected root or pcp[%d])\n", ++ cred.uid, pcp_uid); ++ close(fd); ++ root_client[i].fd = -1; ++ root_delete_client(&root_client[i]); ++ return NULL; ++ } ++ } ++ } ++#elif defined(HAVE_GETPEEREID) ++ { ++ uid_t uid; ++ gid_t gid; ++ ++ if (getpeereid(fd, &uid, &gid) == 0) { ++ if (uid != 0 && uid != pcp_uid) { ++ pmNotifyErr(LOG_ERR, ++ "root_accept_client: rejected uid=%d (expected root or pcp[%d])\n", ++ uid, pcp_uid); ++ close(fd); ++ root_client[i].fd = -1; ++ root_delete_client(&root_client[i]); ++ return NULL; ++ } ++ } ++ } ++#endif ++ + if (fd > root_maximum_fd) + root_maximum_fd = fd; + __pmFD_SET(fd, &connected_fds); +@@ -796,6 +836,19 @@ root_main(pmdaInterface *dp) + } + } + ++static void ++root_get_pcp_uid(void) ++{ ++#if defined(HAVE_PWD_H) ++ char *username; ++ struct passwd *pw; ++ ++ pmGetUsername(&username); ++ if ((pw = getpwnam(username)) != NULL) ++ pcp_uid = pw->pw_uid; ++#endif ++} ++ + static void + root_check_user(void) + { +@@ -815,6 +868,7 @@ static void + root_prep(void) + { + root_check_user(); ++ root_get_pcp_uid(); + root_setup_socket(); + atexit(root_close_socket); + } diff --git a/pcp-6.3.7-pmieconf-command-injection.patch b/pcp-6.3.7-pmieconf-command-injection.patch new file mode 100644 index 0000000..b0a81fd --- /dev/null +++ b/pcp-6.3.7-pmieconf-command-injection.patch @@ -0,0 +1,142 @@ +From cdc9676ab6 Mon Sep 17 00:00:00 2001 +From: Nathan Scott +Subject: [PATCH] pmieconf: fix command injection via $HOME and -f (CWE-78) + +The write_pmiefile() function constructed a shell command via +pmsprintf("/bin/mkdir -p %s", fname) and passed it to system(). +The fname value derives from either $HOME or the -f command-line +argument without sanitization, enabling command injection through +shell metacharacters in the path. + +Fix: replace system("/bin/mkdir -p ...") with __pmMakePath() which +creates directories recursively using mkdir() syscalls directly, +with no shell involvement. + +Add qa/2103 verifying that legitimate directory creation works and +that shell metacharacters in -f and $HOME paths do not result in +command execution. + +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) + +--- +diff --git a/qa/2103 b/qa/2103 +new file mode 100755 +index 0000000000..c068ae92f0 +--- /dev/null ++++ b/qa/2103 +@@ -0,0 +1,62 @@ ++#!/bin/sh ++# PCP QA Test No. 2103 ++# Verify pmieconf does not execute shell metacharacters in -f path ++# (CWE-78 fix verification) ++# ++# Copyright (c) 2026 Red Hat. All Rights Reserved. ++# ++ ++seq=`basename $0` ++echo "QA output created by $seq" ++ ++# get standard environment, filters and checks ++. ./common.product ++. ./common.filter ++. ./common.check ++ ++which pmieconf >/dev/null 2>&1 || _notrun "pmieconf not installed" ++ ++_cleanup() ++{ ++ cd $here ++ $sudo rm -rf $tmp $tmp.* ++} ++ ++status=0 # success is the default! ++trap "_cleanup; exit \$status" 0 1 2 3 15 ++ ++# real QA test starts here ++ ++echo "=== normal -f path should work ===" ++mkdir -p $tmp.dir ++pmieconf -f $tmp.dir/subdir/test.pmie modify global delta "2min" >$tmp.out 2>&1 ++_sts=$? ++if [ -f $tmp.dir/subdir/test.pmie ]; then ++ echo "directory creation and file write succeeded" ++else ++ echo "FAIL: file not created (exit=$_sts)" ++ cat $tmp.out ++fi ++ ++echo ++echo "=== -f path with semicolon should not execute commands ===" ++_bad="$tmp.dir/bad;touch $tmp.dir/pwned" ++pmieconf -f "$_bad" modify global delta "2min" >$tmp.out 2>&1 ++if [ -f "$tmp.dir/pwned" ]; then ++ echo "FAIL: shell metacharacter was executed" ++else ++ echo "no command execution from semicolon in path" ++fi ++ ++echo ++echo "=== verify no injected file from HOME variable ===" ++_badhome="$tmp.dir/home;touch $tmp.dir/pwned2" ++HOME="$_badhome" pmieconf modify global delta "2min" >$tmp.out 2>&1 ++if [ -f "$tmp.dir/pwned2" ]; then ++ echo "FAIL: shell metacharacter in HOME was executed" ++else ++ echo "no command execution from HOME injection" ++fi ++ ++# success, all done ++exit +diff --git a/qa/2103.out b/qa/2103.out +new file mode 100644 +index 0000000000..a5054675e2 +--- /dev/null ++++ b/qa/2103.out +@@ -0,0 +1,9 @@ ++QA output created by 2103 ++=== normal -f path should work === ++directory creation and file write succeeded ++ ++=== -f path with semicolon should not execute commands === ++no command execution from semicolon in path ++ ++=== verify no injected file from HOME variable === ++no command execution from HOME injection +diff --git a/qa/group b/qa/group +index 9c158034fd..c096e80cc8 100644 +--- a/qa/group ++++ b/qa/group +@@ -2221,4 +2221,5 @@ pmcd.pdu + 2104 libpcp local security + 2101 linux_sockets local security + 2102 pmlogmv local security ++2103 pmieconf local security + 4751 libpcp threads valgrind local pcp helgrind +diff --git a/src/pmieconf/rules.c b/src/pmieconf/rules.c +index 4bd173fcfe..f0b3ce68c6 100644 +--- a/src/pmieconf/rules.c ++++ b/src/pmieconf/rules.c +@@ -1805,7 +1805,6 @@ write_pmiefile(char *program, int autocreate) + { + time_t now = time(NULL); + char *p, *msg = NULL; +- char buf[MAXPATHLEN+10]; + char *fname = get_pmiefile(); + FILE *fp; + int i; +@@ -1816,9 +1815,8 @@ write_pmiefile(char *program, int autocreate) + + *p = '\0'; /* p is the dirname of fname */ + if (stat(fname, &sbuf) < 0) { +- pmsprintf(buf, sizeof(buf), "/bin/mkdir -p %s", fname); +- if (system(buf) < 0) { +- pmsprintf(errmsg, sizeof(errmsg), "failed to create directory \"%s\"", p); ++ if (__pmMakePath(fname, 0755) < 0) { ++ pmsprintf(errmsg, sizeof(errmsg), "failed to create directory \"%s\"", fname); + return errmsg; + } + } diff --git a/pcp-6.3.7-pmlogmv-command-injection.patch b/pcp-6.3.7-pmlogmv-command-injection.patch new file mode 100644 index 0000000..967be6d --- /dev/null +++ b/pcp-6.3.7-pmlogmv-command-injection.patch @@ -0,0 +1,338 @@ +From dc73ec0f57 Mon Sep 17 00:00:00 2001 +From: Nathan Scott +Subject: [PATCH] pmlogmv: fix command injection in pmlogcp/pmlogmv (CWE-78) + +The do_link() function used system("cp src dst") to copy archive files +when link() fails with EXDEV. The source filename was not validated by +check_name() and was embedded directly into the shell command, enabling +command injection via crafted archive filenames. The do_checksum() +function similarly used system() for command detection and popen() for +checksum execution. + +Fix: +- Replace system("cp ...") with copy_file() using open/read/write + syscalls directly, eliminating shell involvement entirely +- Replace system("if which ...") checksum detection with access() checks +- Replace popen("md5sum + +--- +diff --git a/qa/2102 b/qa/2102 +new file mode 100755 +index 0000000000..5f8a4ef1cc +--- /dev/null ++++ b/qa/2102 +@@ -0,0 +1,67 @@ ++#!/bin/sh ++# PCP QA Test No. 2102 ++# Verify pmlogmv rejects shell metacharacters in filenames ++# and that normal move operations still work (CWE-78 fix) ++# ++# Copyright (c) 2026 Red Hat. All Rights Reserved. ++# ++ ++seq=`basename $0` ++echo "QA output created by $seq" ++ ++# get standard environment, filters and checks ++. ./common.product ++. ./common.filter ++. ./common.check ++ ++_cleanup() ++{ ++ cd $here ++ $sudo rm -rf $tmp $tmp.* ++} ++ ++status=0 # success is the default! ++trap "_cleanup; exit \$status" 0 1 2 3 15 ++ ++_filter() ++{ ++ sed \ ++ -e "s,$tmp,TMP,g" \ ++ -e "s/pmlogmv/TOOL/" \ ++ # end ++} ++ ++# real QA test starts here ++ ++echo "=== normal pmlogmv should succeed ===" ++for ext in meta 0 index ++do ++ [ -f tmparch/foo.$ext ] && cp tmparch/foo.$ext $tmp.src.$ext ++done ++pmlogmv $tmp.src $tmp.mvdest 2>&1 | _filter ++if [ -f $tmp.mvdest.meta ] || [ -f $tmp.mvdest.0 ]; then ++ echo "move succeeded" ++else ++ echo "FAIL: move did not create files" ++fi ++ ++echo ++echo "=== pmlogmv with backtick in destination should be rejected ===" ++pmlogmv tmparch/foo "$tmp.bad\`id\`" >$tmp.out 2>&1 ++_sts=$? ++_filter <$tmp.out ++echo "exit status: $_sts" ++ ++echo ++echo "=== pmlogmv with semicolon in destination should be rejected ===" ++pmlogmv tmparch/foo "$tmp.bad;id" >$tmp.out 2>&1 ++_sts=$? ++_filter <$tmp.out ++echo "exit status: $_sts" ++ ++echo ++echo "=== pmlogmv with dollar in destination should be rejected ===" ++pmlogmv tmparch/foo '$tmp.bad${IFS}' >$tmp.out 2>&1 ++_sts=$? ++_filter <$tmp.out ++echo "exit status: $_sts" ++ ++# success, all done ++exit +diff --git a/qa/2102.out b/qa/2102.out +new file mode 100644 +index 0000000000..5a3fec6ca8 +--- /dev/null ++++ b/qa/2102.out +@@ -0,0 +1,15 @@ ++QA output created by 2102 ++=== normal pmlogmv should succeed === ++move succeeded ++ ++=== pmlogmv with backtick in destination should be rejected === ++TOOL: name (TMP.bad`id`) unsafe [shell metacharacter '`'] ++exit status: 1 ++ ++=== pmlogmv with semicolon in destination should be rejected === ++TOOL: name (TMP.bad;id) unsafe [shell metacharacter ';'] ++exit status: 1 ++ ++=== pmlogmv with dollar in destination should be rejected === ++TOOL: name ($tmp.bad${IFS}) unsafe [shell metacharacter '$'] ++exit status: 1 +diff --git a/qa/group b/qa/group +index 0d9ef9ffb6..9c158034fd 100644 +--- a/qa/group ++++ b/qa/group +@@ -2220,4 +2220,5 @@ pmcd.pdu + 2100 pmproxy local security + 2104 libpcp local security + 2101 linux_sockets local security ++2102 pmlogmv local security + 4751 libpcp threads valgrind local pcp helgrind +diff --git a/src/pmlogmv/pmlogmv.c b/src/pmlogmv/pmlogmv.c +index ee59e07b7e..742fa8d740 100644 +--- a/src/pmlogmv/pmlogmv.c ++++ b/src/pmlogmv/pmlogmv.c +@@ -17,6 +17,8 @@ + */ + + #include ++#include ++#include + #include + #include + #include +@@ -73,12 +75,12 @@ myoverrides(int opt, pmOptions *optsp) + static int + check_name(char *name) + { +- char *meta = " $?*[(|;&<>"; ++ char *meta = " $?*[(|;&<>`{}\\!\n\t"; + char *p; + + for (p = meta; *p; p++) { + if (index(name, *p) != NULL) { +- fprintf(stderr, "pmlogmv: newname (%s) unsafe [shell metacharacter '%c']\n", name, *p); ++ fprintf(stderr, "pmlogmv: name (%s) unsafe [shell metacharacter '%c']\n", name, *p); + return -1; + } + } +@@ -144,54 +146,54 @@ setup_sufftab(void) + void + do_checksum(const char *file, char *sum) + { +- char cmd[MAXPATHLEN+40]; + static char *executable = NULL; + FILE *fp; + static int trunc_warn = 0; + + if (executable == NULL) { +- /* +- * one-trip to initialize the "checksum" command ... +- * prefer md5sum, then sha256sum, then sha1sum, then sum, +- * else do nothing +- */ +- snprintf(cmd, sizeof(cmd), "if which md5sum >/dev/null 2>&1; then exit 0; fi; exit 1"); +- if (system(cmd) == 0) +- executable = "md5sum"; +- else { +- snprintf(cmd, sizeof(cmd), "if which sha256sum >/dev/null 2>&1; then exit 0; fi; exit 1"); +- if (system(cmd) == 0) +- executable = "sha256sum"; +- else { +- snprintf(cmd, sizeof(cmd), "if which sha1sum >/dev/null 2>&1; then exit 0; fi; exit 1"); +- if (system(cmd) == 0) +- executable = "sha1sum"; +- else { +- snprintf(cmd, sizeof(cmd), "if which sum >/dev/null 2>&1; then exit 0; fi; exit 1"); +- if (system(cmd) == 0) +- executable = "sum"; +- else { +- executable = "none"; +- fprintf(stderr, "pmlogmv: warning: no checksum command found, checksums skipped\n"); +- } +- } ++ static const char *candidates[] = { ++ "md5sum", "sha256sum", "sha1sum", "sum", NULL ++ }; ++ const char **cp; ++ char path[MAXPATHLEN]; ++ ++ executable = "none"; ++ for (cp = candidates; *cp != NULL; cp++) { ++ snprintf(path, sizeof(path), "/usr/bin/%s", *cp); ++ if (access(path, X_OK) == 0) { ++ executable = (char *)*cp; ++ break; ++ } ++ snprintf(path, sizeof(path), "/usr/sbin/%s", *cp); ++ if (access(path, X_OK) == 0) { ++ executable = (char *)*cp; ++ break; + } + } ++ if (strcmp(executable, "none") == 0) ++ fprintf(stderr, "pmlogmv: warning: no checksum command found, checksums skipped\n"); + if (verbose && strcmp(executable, "none") != 0) + printf("checksum cmd: %s\n", executable); + } + sum[0] = '\0'; + if (strcmp(executable, "none") == 0) + return; +- snprintf(cmd, sizeof(cmd), "%s <%s", executable, file); +- if ((fp = popen(cmd, "r")) == NULL) { +- /* +- * abandon checksuming ... +- */ +- fprintf(stderr, "pmlogmv: pipe(\"%s\") failed: %s\n", cmd, strerror(errno)); +- executable = "none"; ++ { ++ __pmExecCtl_t *argp = NULL; ++ int sts; ++ ++ if ((sts = __pmProcessAddArg(&argp, executable)) < 0 || ++ (sts = __pmProcessAddArg(&argp, file)) < 0) { ++ executable = "none"; ++ return; ++ } ++ if ((sts = __pmProcessPipe(&argp, "r", PM_EXEC_TOSS_NONE, &fp)) < 0) { ++ fprintf(stderr, "pmlogmv: __pmProcessPipe(\"%s\") failed: %s\n", executable, pmErrStr(sts)); ++ executable = "none"; ++ return; ++ } + } +- else { ++ { + char *p = sum; + int c; + while ((c = fgetc(fp)) != EOF) { +@@ -200,9 +202,6 @@ do_checksum(const char *file, char *sum) + break; + } + if (p >= &sum[MAX_CHECKSUM]) { +- /* +- * avoid buffer overrun, report only once unless -V +- */ + if (trunc_warn++ == 0 || verbose) + fprintf(stderr, "pmlogmv: warning: checksum truncated after %d characters\n", MAX_CHECKSUM); + *p = '\0'; +@@ -210,10 +209,54 @@ do_checksum(const char *file, char *sum) + } + *p++ = c; + } +- pclose(fp); ++ __pmProcessPipeClose(fp); ++ } ++} ++ ++/* ++ * copy a file using read/write - no shell involvement ++ */ ++static int ++copy_file(const char *src, const char *dst) ++{ ++ int sfd, dfd; ++ struct stat sbuf; ++ ssize_t nread, nwritten; ++ char buf[BUFSIZ]; ++ ++ if ((sfd = open(src, O_RDONLY)) < 0) ++ return -1; ++ if (fstat(sfd, &sbuf) < 0) { ++ close(sfd); ++ return -1; ++ } ++ if ((dfd = open(dst, O_WRONLY|O_CREAT|O_EXCL, sbuf.st_mode & 0777)) < 0) { ++ close(sfd); ++ return -1; ++ } ++ while ((nread = read(sfd, buf, sizeof(buf))) > 0) { ++ char *p = buf; ++ while (nread > 0) { ++ nwritten = write(dfd, p, nread); ++ if (nwritten < 0) { ++ close(sfd); ++ close(dfd); ++ unlink(dst); ++ return -1; ++ } ++ nread -= nwritten; ++ p += nwritten; ++ } + } ++ close(sfd); ++ if (nread < 0 || close(dfd) < 0) { ++ unlink(dst); ++ return -1; ++ } ++ return 0; + } + ++ + /* + * make link for one physical file + * return codes: +@@ -267,7 +310,6 @@ do_link(int vol) + #endif + /* link() failed cross-device, need to copy ... */ + int sts; +- char cmd[2*MAXPATHLEN+4]; + char sum_src[MAX_CHECKSUM+1]; + char sum_dst[MAX_CHECKSUM+1]; + if (checksum) { +@@ -280,8 +322,7 @@ do_link(int vol) + printf("source checksum: %s\n", sum_src); + } + +- snprintf(cmd, sizeof(cmd), "cp %s %s", src, dst); +- if ((sts = system(cmd)) != 0) { ++ if ((sts = copy_file(src, dst)) != 0) { + fprintf(stderr, "pmlogmv: copy %s -> %s failed: %s\n", src, dst, strerror(errno)); + return -1; + } diff --git a/pcp-6.3.7-pmproxy-rest-certreqd.patch b/pcp-6.3.7-pmproxy-rest-certreqd.patch new file mode 100644 index 0000000..4a1e81a --- /dev/null +++ b/pcp-6.3.7-pmproxy-rest-certreqd.patch @@ -0,0 +1,43 @@ +From 81a9efe96d Mon Sep 17 00:00:00 2001 +From: Nathan Scott +Subject: [PATCH] pmproxy: enforce -Q (CERT_REQD) for REST API connections + +The -Q flag (PM_SERVER_FEATURE_CERT_REQD) was only enforced in the +legacy PCP wire protocol path (deprecated.c). The modern HTTP/REST +API path had no check, allowing unauthenticated plain-HTTP clients +to access all endpoints even when -Q was specified. + +Add enforcement in on_headers_complete() alongside the existing -S +(CREDS_REQD) check: when CERT_REQD is active, reject requests where +the connection is not TLS or no client certificate was presented. +Returns HTTP 403 Forbidden. If OpenSSL is not compiled in, all +connections are rejected when -Q is set since TLS is unavailable. + +Co-Authored-By: Claude Opus 4.6 (1M context) + +--- +diff --git a/src/pmproxy/src/http.c b/src/pmproxy/src/http.c +index cfbc8aec0c..e0d28ffc28 100644 +--- a/src/pmproxy/src/http.c ++++ b/src/pmproxy/src/http.c +@@ -1094,6 +1094,20 @@ on_headers_complete(http_parser *request) + } + } + ++ /* client certificate required for all servlets */ ++ if (__pmServerHasFeature(PM_SERVER_FEATURE_CERT_REQD)) { ++#ifdef HAVE_OPENSSL ++ if (!client->stream.secure || ++ !client->secure.ssl || ++ SSL_get_peer_certificate(client->secure.ssl) == NULL) { ++ client->u.http.parser.status_code = HTTP_STATUS_FORBIDDEN; ++ } ++#else ++ /* no TLS support compiled in, reject all connections */ ++ client->u.http.parser.status_code = HTTP_STATUS_FORBIDDEN; ++#endif ++ } ++ + return sts; + } + diff --git a/pcp-6.3.7-scanmeta-LogLoadInDom-caller.patch b/pcp-6.3.7-scanmeta-LogLoadInDom-caller.patch new file mode 100644 index 0000000..bcf02ee --- /dev/null +++ b/pcp-6.3.7-scanmeta-LogLoadInDom-caller.patch @@ -0,0 +1,44 @@ +From be9ade9950 Mon Sep 17 00:00:00 2001 +From: Nathan Scott +Subject: [PATCH] qa/src/scanmeta.c: fix call to __pmLogLoadInDom() + +scanmeta was *using* the acp == NULL guard to dodge the rlen test and +calling with rlen == 0 (this QA app was simply assuming the record +was valid, at least to the point that the buffer could be correctly +decoded). + +Fix involves re-extracting the correct record length and calling +__pmLogLoadInDom() with rlen != 0. + +--- +diff --git a/qa/src/scanmeta.c b/qa/src/scanmeta.c +index 1f884ecbb6..3e65fb5028 100644 +--- a/qa/src/scanmeta.c ++++ b/qa/src/scanmeta.c +@@ -143,7 +143,7 @@ free_elt_fields(elt_t *ep) + } + + void +-do_indom(__int32_t *buf, int type) ++do_indom(__int32_t *buf, int type, int len) + { + int sts; + static __pmTimestamp prior_stamp = { 0, 0 }; +@@ -156,7 +156,7 @@ do_indom(__int32_t *buf, int type) + elt_t *tp; + elt_t *dp = &dup; + +- if ((sts = __pmLogLoadInDom(NULL, 0, type, &lid, &buf)) < 0) { ++ if ((sts = __pmLogLoadInDom(NULL, len, type, &lid, &buf)) < 0) { + fprintf(stderr, "__pmLoadLoadInDom: failed: %s\n", pmErrStr(sts)); + return; + } +@@ -689,7 +689,7 @@ main(int argc, char *argv[]) + case TYPE_INDOM_V2: + if (!iflag) + break; +- do_indom(buf, hdr.type); ++ do_indom(buf, hdr.type, hdr.len); + break; + + case TYPE_LABEL: diff --git a/pcp-6.3.7-timezone-zoneinfo-validation.patch b/pcp-6.3.7-timezone-zoneinfo-validation.patch new file mode 100644 index 0000000..51ca295 --- /dev/null +++ b/pcp-6.3.7-timezone-zoneinfo-validation.patch @@ -0,0 +1,243 @@ +From f86c0f4cda Mon Sep 17 00:00:00 2001 +From: Nathan Scott +Subject: [PATCH] libpcp, libpcp_web: validate timezone and zoneinfo strings + +The timezone and zoneinfo fields from archive labels and PDU_LOG_STATUS +are used via pmNewZone() -> setenv("TZ", ...), causing glibc to resolve +Olson timezone paths against /usr/share/zoneinfo/. A crafted value +like "../../etc/passwd" would cause glibc to open arbitrary files. + +Fix at two layers: +- Front door: add check_tz() check in pmLogGroupLabel() alongside the + existing check_hostname() check, rejecting unsafe timezone/zoneinfo + before any data is written to disk +- Consumption: add check_tz() check in pmNewZone() as defense-in-depth, + protecting against malicious archives created by other means + +The allowlist permits alphanumeric characters plus /_+-.:" which covers +both Olson paths (America/New_York) and POSIX TZ strings (EST5EDT). +Leading slashes and ".." path components are rejected. + +Add qa/src/check_tz.c and qa/2107 exercising pmNewZone() with valid +and malicious timezone strings. + +Co-Authored-By: Claude Opus 4.6 (1M context) + +--- +diff --git a/qa/2107 b/qa/2107 +new file mode 100755 +index 0000000000..d4017c02fe +--- /dev/null ++++ b/qa/2107 +@@ -0,0 +1,60 @@ ++#!/bin/sh ++# PCP QA Test No. 2107 ++# Verify pmNewZone rejects unsafe timezone strings containing ++# path traversal or invalid characters ++# ++# Copyright (c) 2026 Red Hat. All Rights Reserved. ++# ++ ++seq=`basename $0` ++echo "QA output created by $seq" ++ ++# get standard environment, filters and checks ++. ./common.product ++. ./common.filter ++. ./common.check ++ ++_cleanup() ++{ ++ cd $here ++ $sudo rm -rf $tmp $tmp.* ++} ++ ++status=0 # success is the default! ++trap "_cleanup; exit \$status" 0 1 2 3 15 ++ ++# real QA test starts here ++ ++echo "=== valid Olson timezone ===" ++src/check_tz "America/New_York" ++ ++echo ++echo "=== valid POSIX timezone ===" ++src/check_tz "EST5EDT" ++ ++echo ++echo "=== valid simple timezone ===" ++src/check_tz "UTC" ++ ++echo ++echo "=== path traversal should be rejected ===" ++src/check_tz "../../etc/passwd" ++ ++echo ++echo "=== leading slash should be rejected ===" ++src/check_tz "/etc/localtime" ++ ++echo ++echo "=== semicolon should be rejected ===" ++src/check_tz "UTC;id" ++ ++echo ++echo "=== backtick should be rejected ===" ++src/check_tz 'UTC`id`' ++ ++echo ++echo "=== empty string should be accepted ===" ++src/check_tz "" ++ ++# success, all done ++exit +diff --git a/qa/2107.out b/qa/2107.out +new file mode 100644 +index 0000000000..42cf4d6adb +--- /dev/null ++++ b/qa/2107.out +@@ -0,0 +1,24 @@ ++QA output created by 2107 ++=== valid Olson timezone === ++pmNewZone("America/New_York") -> 0 (accepted) ++ ++=== valid POSIX timezone === ++pmNewZone("EST5EDT") -> 0 (accepted) ++ ++=== valid simple timezone === ++pmNewZone("UTC") -> 0 (accepted) ++ ++=== path traversal should be rejected === ++pmNewZone("../../etc/passwd") -> Invalid argument (rejected) ++ ++=== leading slash should be rejected === ++pmNewZone("/etc/localtime") -> Invalid argument (rejected) ++ ++=== semicolon should be rejected === ++pmNewZone("UTC;id") -> Invalid argument (rejected) ++ ++=== backtick should be rejected === ++pmNewZone("UTC`id`") -> Invalid argument (rejected) ++ ++=== empty string should be accepted === ++pmNewZone("") - skipped (empty string) +diff --git a/qa/group b/qa/group +index c096e80cc8..a80d1039dc 100644 +--- a/qa/group ++++ b/qa/group +@@ -2222,4 +2222,5 @@ pmcd.pdu + 2101 linux_sockets local security + 2102 pmlogmv local security + 2103 pmieconf local security ++2107 libpcp local security + 4751 libpcp threads valgrind local pcp helgrind +diff --git a/qa/src/GNUlocaldefs b/qa/src/GNUlocaldefs +index 6ee74c7f16..c0b158a1a6 100644 +--- a/qa/src/GNUlocaldefs ++++ b/qa/src/GNUlocaldefs +@@ -55,7 +55,7 @@ CFILES = disk_test.c exercise.c context_test.c chkoptfetch.c \ + dumpstack.c usergroup.c derived_help.c ready-or-not.c cleanmapdir.c \ + throttle.c throttle_timeout.c y2038.c bigpmcdpmids.c pdu-gadget.c \ + newcontext.c \ +- check_cloexec.c ++ check_cloexec.c check_tz.c + + ifeq ($(shell test -f ../localconfig && echo 1), 1) + include ../localconfig +@@ -580,6 +580,11 @@ check_cloexec: check_cloexec.c + $(CCF) $(CDEFS) -o $@ $@.c $(LDLIBS) + $(LINKER_MAKERULE) + ++check_tz: check_tz.c ++ rm -f $@ ++ $(CCF) $(CDEFS) -o $@ $@.c $(LDLIBS) ++ $(LINKER_MAKERULE) ++ + check_import: check_import.c + rm -f $@ + $(CCF) $(CDEFS) -o $@ $@.c $(LDLIBS) -lpcp_import +diff --git a/qa/src/check_tz.c b/qa/src/check_tz.c +new file mode 100644 +index 0000000000..ad96444f9c +--- /dev/null ++++ b/qa/src/check_tz.c +@@ -0,0 +1,31 @@ ++/* ++ * Verify pmNewZone accepts/rejects timezone strings correctly. ++ */ ++ ++#include ++ ++int ++main(int argc, char **argv) ++{ ++ int sts; ++ ++ pmSetProgname(argv[0]); ++ ++ if (argc != 2) { ++ fprintf(stderr, "Usage: %s timezone\n", pmGetProgname()); ++ return 1; ++ } ++ ++ if (argv[1][0] == '\0') { ++ printf("pmNewZone(\"\") - skipped (empty string)\n"); ++ return 0; ++ } ++ ++ sts = pmNewZone(argv[1]); ++ if (sts >= 0) ++ printf("pmNewZone(\"%s\") -> %d (accepted)\n", argv[1], sts); ++ else ++ printf("pmNewZone(\"%s\") -> %s (rejected)\n", argv[1], pmErrStr(sts)); ++ ++ return 0; ++} +diff --git a/src/libpcp/src/tz.c b/src/libpcp/src/tz.c +index 0aab541776..169846acc9 100644 +--- a/src/libpcp/src/tz.c ++++ b/src/libpcp/src/tz.c +@@ -25,6 +25,7 @@ + * lock initialization in pmNewContext(). + */ + ++#include + #include "pmapi.h" + #include "libpcp.h" + #include "sha256.h" +@@ -573,6 +574,22 @@ pmUseZone(const int tz_handle) + return 0; + } + ++static int ++valid_tz(const char *tz) ++{ ++ const char *p; ++ ++ if (tz == NULL || tz[0] == '\0' || tz[0] == '/') ++ return 0; ++ for (p = tz; *p; p++) { ++ if (!isalnum((unsigned char)*p) && strchr("/_+-.:,\"'", *p) == NULL) ++ return 0; ++ } ++ if (strstr(tz, "..") != NULL) ++ return 0; ++ return 1; ++} ++ + int + pmNewZone(const char *tz) + { +@@ -580,6 +597,13 @@ pmNewZone(const char *tz) + int hack = 0; + int sts; + ++ if (!valid_tz(tz)) { ++ if (pmDebugOptions.context) ++ fprintf(stderr, "%s: rejecting unsafe timezone: %s\n", ++ __FUNCTION__, tz ? tz : "(null)"); ++ return -EINVAL; ++ } ++ + PM_LOCK(__pmLock_extcall); + + len = (int)strlen(tz); diff --git a/pcp-RHEL-213658.patch b/pcp-RHEL-213658.patch new file mode 100644 index 0000000..388b7fe --- /dev/null +++ b/pcp-RHEL-213658.patch @@ -0,0 +1,256 @@ +From c5cbeceb7d Mon Sep 17 00:00:00 2001 +From: Nathan Scott +Subject: [PATCH] linux_sockets pmda: fix command injection via network.persocket.filter (CWE-78) + +The sockets_check_filter() validation helper returns 1 for safe input +and 0 for unsafe input. The guard in sockets_store() tested +if (sockets_check_filter(av.cp)) — rejecting safe input and accepting +malicious input containing shell metacharacters. The accepted filter +was later passed to popen() via shell interpretation, enabling arbitrary +command execution as the PMDA process user. + +Fix: +- Invert the guard: if (!sockets_check_filter(av.cp)) +- Replace popen()/pclose() in ss_open_stream() with the libpcp + __pmProcessAddArg()/__pmProcessPipe()/__pmProcessPipeClose() API + which uses execvp() internally, eliminating shell interpretation + of the filter string entirely +- Add qa/2101 verifying that valid filters are accepted and shell + metacharacters (semicolons, backticks, pipes) are rejected + +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) + +Resolves: RHEL-213658 CVE-2026-16524 +--- +diff --git a/qa/2101 b/qa/2101 +new file mode 100755 +index 0000000000..733b7f70c9 +--- /dev/null ++++ b/qa/2101 +@@ -0,0 +1,70 @@ ++#!/bin/sh ++# PCP QA Test No. 2101 ++# Verify linux_sockets PMDA filter validation rejects shell metacharacters ++# and accepts valid filter expressions (CWE-78 fix verification) ++# ++# Copyright (c) 2026 Red Hat. All Rights Reserved. ++# ++ ++seq=`basename $0` ++echo "QA output created by $seq" ++ ++# get standard environment, filters and checks ++. ./common.product ++. ./common.filter ++. ./common.check ++ ++[ $PCP_PLATFORM = linux ] || _notrun "Linux-specific sockets testing" ++[ -f $PCP_PMDAS_DIR/sockets/pmdasockets ] || _notrun "sockets PMDA not installed" ++ ++_cleanup() ++{ ++ _cleanup_pmda sockets ++ cd $here ++ $sudo rm -rf $tmp $tmp.* ++} ++ ++status=0 # success is the default! ++trap "_cleanup; exit \$status" 0 1 2 3 15 ++ ++_prepare_pmda sockets ++_stop_auto_restart pmcd ++ ++# install the sockets PMDA ++cd $PCP_PMDAS_DIR/sockets ++$sudo ./Remove >/dev/null 2>&1 ++$sudo ./Install $tmp.out 2>&1 ++cat $tmp.out >>$seq_full ++ ++# check the PMDA is alive ++pmprobe -v network.persocket.filter >$tmp.probe 2>&1 ++grep -q 'No PMCD agent' $tmp.probe && _notrun "sockets PMDA failed to install" ++ ++# real QA test starts here ++ ++echo "=== valid filter should be accepted ===" ++pmstore network.persocket.filter "sport == 22" 2>&1 \ ++| grep -q 'Bad input' && echo "FAIL: valid filter rejected" || echo "valid filter accepted" ++ ++echo ++echo "=== shell metacharacter semicolon should be rejected ===" ++pmstore network.persocket.filter ';id' 2>&1 \ ++| grep -q 'Bad input' && echo "metacharacter rejected" || echo "FAIL: metacharacter not rejected" ++ ++echo ++echo "=== shell metacharacter backtick should be rejected ===" ++pmstore network.persocket.filter '`id`' 2>&1 \ ++| grep -q 'Bad input' && echo "metacharacter rejected" || echo "FAIL: metacharacter not rejected" ++ ++echo ++echo "=== shell metacharacter pipe should be rejected ===" ++pmstore network.persocket.filter '|cat /etc/passwd' 2>&1 \ ++| grep -q 'Bad input' && echo "metacharacter rejected" || echo "FAIL: metacharacter not rejected" ++ ++echo ++echo "=== shell metacharacter dollar should be rejected ===" ++pmstore network.persocket.filter '${IFS}id' 2>&1 \ ++| grep -q 'Bad input' && echo "metacharacter rejected" || echo "FAIL: metacharacter not rejected" ++ ++# success, all done ++exit +diff --git a/qa/2101.out b/qa/2101.out +new file mode 100644 +index 0000000000..02f9ac5655 +--- /dev/null ++++ b/qa/2101.out +@@ -0,0 +1,15 @@ ++QA output created by 2101 ++=== valid filter should be accepted === ++valid filter accepted ++ ++=== shell metacharacter semicolon should be rejected === ++metacharacter rejected ++ ++=== shell metacharacter backtick should be rejected === ++metacharacter rejected ++ ++=== shell metacharacter pipe should be rejected === ++metacharacter rejected ++ ++=== shell metacharacter dollar should be rejected === ++metacharacter rejected +diff --git a/qa/group b/qa/group +index c7db6290b2..0d9ef9ffb6 100644 +--- a/qa/group ++++ b/qa/group +@@ -2219,4 +2219,5 @@ pmcd.pdu + 2105 libpcp local security + 2100 pmproxy local security + 2104 libpcp local security ++2101 linux_sockets local security + 4751 libpcp threads valgrind local pcp helgrind +diff --git a/src/pmdas/linux_sockets/pmda.c b/src/pmdas/linux_sockets/pmda.c +index 5a3018d8aa..59e69a6756 100644 +--- a/src/pmdas/linux_sockets/pmda.c ++++ b/src/pmdas/linux_sockets/pmda.c +@@ -162,11 +162,9 @@ sockets_check_filter(const char *string) + const char *p; + + for (p = string; *p; p++) { +- if (isspace(*p)) ++ if (isspace(*p) || isalnum(*p)) + continue; +- if (isalnum(*p)) +- continue; +- if (*p == '(' || *p == ')') ++ if (strchr("()=!<>:.*/-,", *p) != NULL) + continue; + return 0; /* disallow */ + } +@@ -191,7 +189,7 @@ sockets_store(pmResult *result, pmdaExt *pmda) + case 0: /* network.persocket.filter */ + if ((sts = pmExtractValue(vsp->valfmt, &vsp->vlist[0], + PM_TYPE_STRING, &av, PM_TYPE_STRING)) >= 0) { +- if (sockets_check_filter(av.cp)) { ++ if (!sockets_check_filter(av.cp)) { + sts = PM_ERR_BADSTORE; + free(av.cp); + break; +diff --git a/src/pmdas/linux_sockets/ss_stream.c b/src/pmdas/linux_sockets/ss_stream.c +index 421c65fd16..833fc275a0 100644 +--- a/src/pmdas/linux_sockets/ss_stream.c ++++ b/src/pmdas/linux_sockets/ss_stream.c +@@ -14,18 +14,19 @@ + + #include + #include ++#include + #include "ss_stats.h" + + #define SS_OPTIONS "-noemitauO" + +-char *ss_filter = NULL; /* storable: network.persocket.filter */ ++char *ss_filter; /* storable: network.persocket.filter */ ++static int using_pipe; /* pipe is normal operation, QA uses files */ + + FILE * + ss_open_stream() + { +- FILE *fp; ++ FILE *fp = NULL; + char *path; +- char cmd[MAXPATHLEN]; + + if (ss_filter == NULL) { + /* pmstore to network.persocket.filter frees this if changing */ +@@ -38,17 +39,51 @@ ss_open_stream() + fp = fopen(path, "r"); + if (pmDebugOptions.appl0) + fprintf(stderr, "ss_open_stream: open PCPQA_PMDA_SOCKETS=%s\n", path); ++ using_pipe = 0; + } else { ++ __pmExecCtl_t *argp = NULL; ++ int sts; ++ + if (access((path = "/usr/sbin/ss"), X_OK) != 0) { + if (access((path = "/usr/bin/ss"), X_OK) != 0) { + fprintf(stderr, "Error: no \"ss\" binary found\n"); + return NULL; + } + } +- pmsprintf(cmd, sizeof(cmd), "%s %s %s", path, SS_OPTIONS, ss_filter); +- fp = popen(cmd, "r"); ++ if ((sts = __pmProcessAddArg(&argp, path)) < 0 || ++ (sts = __pmProcessAddArg(&argp, SS_OPTIONS)) < 0) { ++ if (pmDebugOptions.appl0) ++ fprintf(stderr, "ss_open_stream: __pmProcessAddArg failed: %s\n", ++ pmErrStr(sts)); ++ return NULL; ++ } ++ if (ss_filter[0] != '\0') { ++ char *s, *tok, *saveptr; ++ ++ if ((s = strdup(ss_filter)) == NULL) ++ return NULL; ++ for (tok = strtok_r(s, " \t", &saveptr); tok != NULL; ++ tok = strtok_r(NULL, " \t", &saveptr)) { ++ if ((sts = __pmProcessAddArg(&argp, tok)) < 0) { ++ free(s); ++ if (pmDebugOptions.appl0) ++ fprintf(stderr, "ss_open_stream: __pmProcessAddArg failed: %s\n", ++ pmErrStr(sts)); ++ return NULL; ++ } ++ } ++ free(s); ++ } ++ if ((sts = __pmProcessPipe(&argp, "r", PM_EXEC_TOSS_NONE, &fp)) < 0) { ++ if (pmDebugOptions.appl0) ++ fprintf(stderr, "ss_open_stream: __pmProcessPipe failed: %s\n", ++ pmErrStr(sts)); ++ return NULL; ++ } + if (pmDebugOptions.appl0) +- fprintf(stderr, "ss_open_stream: popen %s\n", cmd); ++ fprintf(stderr, "ss_open_stream: exec %s %s %s\n", ++ path, SS_OPTIONS, ss_filter); ++ using_pipe = 1; + } + + return fp; +@@ -57,8 +92,8 @@ ss_open_stream() + void + ss_close_stream(FILE *fp) + { +- if (getenv("PCPQA_PMDA_SOCKETS") != NULL) +- fclose(fp); ++ if (using_pipe) ++ __pmProcessPipeClose(fp); + else +- pclose(fp); ++ fclose(fp); + } diff --git a/pcp-RHEL-213687.patch b/pcp-RHEL-213687.patch new file mode 100644 index 0000000..a7535f6 --- /dev/null +++ b/pcp-RHEL-213687.patch @@ -0,0 +1,207 @@ +From 7e27614006 Mon Sep 17 00:00:00 2001 +From: Nathan Scott +Subject: [PATCH] libpcp, libpcp_pmda: set FD_CLOEXEC on AF_UNIX sockets (CWE-403) + +The __pmInitSocket() function returns early for AF_UNIX sockets, +skipping all subsequent socket hardening including FD_CLOEXEC. +This causes the pmdaroot Unix socket fd to be inherited by child +processes spawned via popen()/fork(), enabling privilege escalation +when combined with the linux_sockets command injection (vuln 3): +an attacker's popen() child inherits the pmdaroot fd and can send +a PDUROOT_STARTPMDA_REQ to execute commands as root. + +Fix: +- Set FD_CLOEXEC on AF_UNIX sockets in __pmInitSocket() before the + early return, matching the behavior TCP sockets get via + __pmConnectRestoreFlags() +- Set FD_CLOEXEC on pmdarootfd in pmdaRootConnect() after connect() + succeeds, as belt-and-suspenders for this critical fd +- Add qa/src/check_cloexec.c and qa/2104 verifying FD_CLOEXEC is set + on sockets created by __pmCreateUnixSocket() + +Note: SO_PEERCRED peer credential verification on the pmdaroot server +side is a separate hardening measure to be addressed as a follow-up. + +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) + +Resolves: RHEL-213687 CVE-2026-16526 +--- +diff --git a/qa/2104 b/qa/2104 +new file mode 100755 +index 0000000000..0b2b0b602e +--- /dev/null ++++ b/qa/2104 +@@ -0,0 +1,31 @@ ++#!/bin/sh ++# PCP QA Test No. 2104 ++# Verify AF_UNIX sockets have FD_CLOEXEC set (CWE-403 fix) ++# ++# Copyright (c) 2026 Red Hat. All Rights Reserved. ++# ++ ++seq=`basename $0` ++echo "QA output created by $seq" ++ ++# get standard environment, filters and checks ++. ./common.product ++. ./common.filter ++. ./common.check ++ ++[ -f src/check_cloexec ] || _notrun "check_cloexec not built" ++ ++_cleanup() ++{ ++ cd $here ++ $sudo rm -rf $tmp $tmp.* ++} ++ ++status=0 # success is the default! ++trap "_cleanup; exit \$status" 0 1 2 3 15 ++ ++# real QA test starts here ++src/check_cloexec ++ ++# success, all done ++exit +diff --git a/qa/2104.out b/qa/2104.out +new file mode 100644 +index 0000000000..900a95ec75 +--- /dev/null ++++ b/qa/2104.out +@@ -0,0 +1,2 @@ ++QA output created by 2104 ++FD_CLOEXEC is set +diff --git a/qa/group b/qa/group +index e538db58e6..c7db6290b2 100644 +--- a/qa/group ++++ b/qa/group +@@ -2218,4 +2218,5 @@ pmcd.pdu + 1992 pmda.uwsgi local + 2105 libpcp local security + 2100 pmproxy local security ++2104 libpcp local security + 4751 libpcp threads valgrind local pcp helgrind +diff --git a/qa/src/GNUlocaldefs b/qa/src/GNUlocaldefs +index f838260680..6ee74c7f16 100644 +--- a/qa/src/GNUlocaldefs ++++ b/qa/src/GNUlocaldefs +@@ -54,7 +54,8 @@ CFILES = disk_test.c exercise.c context_test.c chkoptfetch.c \ + stampconv.c time_stamp.c archend.c scandata.c wait_for_values.c \ + dumpstack.c usergroup.c derived_help.c ready-or-not.c cleanmapdir.c \ + throttle.c throttle_timeout.c y2038.c bigpmcdpmids.c pdu-gadget.c \ +- newcontext.c ++ newcontext.c \ ++ check_cloexec.c + + ifeq ($(shell test -f ../localconfig && echo 1), 1) + include ../localconfig +@@ -574,6 +575,11 @@ sortinst: sortinst.c + # --- need libpcp_import + # + ++check_cloexec: check_cloexec.c ++ rm -f $@ ++ $(CCF) $(CDEFS) -o $@ $@.c $(LDLIBS) ++ $(LINKER_MAKERULE) ++ + check_import: check_import.c + rm -f $@ + $(CCF) $(CDEFS) -o $@ $@.c $(LDLIBS) -lpcp_import +@@ -880,6 +886,8 @@ xmktime.o: libpcp.h + xxx.o: libpcp.h + y2038.o: libpcp.h + ++check_cloexec.o: libpcp.h ++ + bozo: + @echo CFILES_TARGETS=$(CFILES_TARGETS) + @echo "patsubst ->" $(patsubst %.c,%,$(CFILES_TARGETS)) +diff --git a/qa/src/check_cloexec.c b/qa/src/check_cloexec.c +new file mode 100644 +index 0000000000..ebc438d301 +--- /dev/null ++++ b/qa/src/check_cloexec.c +@@ -0,0 +1,38 @@ ++/* ++ * Verify that AF_UNIX sockets created by __pmCreateUnixSocket() ++ * have FD_CLOEXEC set. ++ */ ++ ++#include ++#include "libpcp.h" ++#include ++ ++int ++main(int argc, char **argv) ++{ ++ int fd, flags; ++ ++ pmSetProgname(argv[0]); ++ ++ fd = __pmCreateUnixSocket(); ++ if (fd < 0) { ++ fprintf(stderr, "Error: __pmCreateUnixSocket failed: %s\n", ++ pmErrStr(fd)); ++ return 1; ++ } ++ ++ flags = fcntl(fd, F_GETFD); ++ if (flags < 0) { ++ fprintf(stderr, "Error: fcntl F_GETFD failed\n"); ++ close(fd); ++ return 1; ++ } ++ ++ if (flags & FD_CLOEXEC) ++ printf("FD_CLOEXEC is set\n"); ++ else ++ printf("FAIL: FD_CLOEXEC is NOT set\n"); ++ ++ close(fd); ++ return 0; ++} +diff --git a/src/libpcp/src/auxconnect.c b/src/libpcp/src/auxconnect.c +index 62f6f54517..67227e3c6b 100644 +--- a/src/libpcp/src/auxconnect.c ++++ b/src/libpcp/src/auxconnect.c +@@ -516,8 +516,12 @@ __pmInitSocket(int fd, int family) + } + + #if defined(HAVE_STRUCT_SOCKADDR_UN) +- if (family == AF_UNIX) ++ if (family == AF_UNIX) { ++ int fdFlags; ++ if ((fdFlags = __pmGetFileDescriptorFlags(fd)) >= 0) ++ __pmSetFileDescriptorFlags(fd, fdFlags | FD_CLOEXEC); + return fd; ++ } + #endif + + /* Avoid 200 ms delay. This option is not supported for unix domain sockets. */ +diff --git a/src/libpcp_pmda/src/root.c b/src/libpcp_pmda/src/root.c +index 1d3223b572..3950e4f1ec 100644 +--- a/src/libpcp_pmda/src/root.c ++++ b/src/libpcp_pmda/src/root.c +@@ -32,7 +32,7 @@ pmdaRootConnect(const char *path) + char *tmpdir; + char socketpath[MAXPATHLEN]; + char errmsg[PM_MAXERRMSGLEN]; +- int fd, sts, version, features; ++ int fd, sts, version, features, fdFlags; + + /* Initialize the socket address. */ + if ((addr = __pmSockAddrAlloc()) == NULL) +@@ -72,6 +72,9 @@ pmdaRootConnect(const char *path) + return sts; + } + ++ if ((fdFlags = __pmGetFileDescriptorFlags(fd)) >= 0) ++ __pmSetFileDescriptorFlags(fd, fdFlags | FD_CLOEXEC); ++ + /* Check server connection information */ + if ((sts = __pmdaRecvRootPDUInfo(fd, &version, &features)) < 0) { + pmNotifyErr(LOG_ERR, diff --git a/pcp-RHEL-213711.patch b/pcp-RHEL-213711.patch new file mode 100644 index 0000000..e7e79cb --- /dev/null +++ b/pcp-RHEL-213711.patch @@ -0,0 +1,196 @@ +From d96ba5a716 Mon Sep 17 00:00:00 2001 +From: Nathan Scott +Subject: [PATCH] pmproxy: fix missing -Q and -S authentication flags (CWE-306) + +The pmproxy -Q (require client certificate) and -S (require +authenticated clients) flags existed as case blocks in the option +parser but were absent from the short_options string and the longopts +table, making them permanently unreachable. An unauthenticated HTTP +client could access all REST API endpoints including /store and /derive. + +Fix: +- Add Q and S to short_options so pmgetopt_r() delivers them +- Add --certreqd and --reqauth entries to the longopts table +- Document both flags in the pmproxy(1) man page +- Add qa/2100 verifying the flags are accepted and that -S correctly + rejects unauthenticated REST API requests with HTTP 403 + +Note: -S enforcement in the REST API path already exists in http.c and +webapi.c. -Q (CERT_REQD) enforcement is only implemented for the +legacy PCP wire protocol path, not the REST API; this is a pre-existing +limitation to be addressed separately. + +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) + +Resolves: RHEL-213711 CVE-2026-16527 +--- +diff --git a/man/man1/pmproxy.1 b/man/man1/pmproxy.1 +index f2f831b6ec..65d66c5d21 100644 +--- a/man/man1/pmproxy.1 ++++ b/man/man1/pmproxy.1 +@@ -229,6 +229,9 @@ Specify an alternate + number to listen on for client connections. + The default value is 44322. + .TP ++\fB\-Q\f1, \fB\-\-certreqd\f1 ++Require that all client connections provide a trusted client certificate. ++.TP + \f3\-r\f1 \f2port\f1, \f3\-\-keyport\f1=\f2port\f1 + Specify an alternate key-value server + .I port +@@ -243,6 +246,9 @@ The default value is + .IR $PCP_RUN_DIR/pmproxy.socket . + This option implies \f3pmproxy\f1 is running in \f3timeseries\f1 mode. + .TP ++\fB\-S\f1, \fB\-\-reqauth\f1 ++Require that all client connections be authenticated. ++.TP + \fB\-t\f1, \fB\-\-timeseries\f1 + Operate in automatic archive timeseries discovery mode. + This mode of operation will enable the +diff --git a/qa/2100 b/qa/2100 +new file mode 100755 +index 0000000000..1de957a2f1 +--- /dev/null ++++ b/qa/2100 +@@ -0,0 +1,85 @@ ++#!/bin/sh ++# PCP QA Test No. 2100 ++# Verify pmproxy -Q and -S authentication flags are accepted ++# and that -S (reqauth) enforces authentication on REST API ++# ++# Copyright (c) 2026 Red Hat. All Rights Reserved. ++# ++ ++seq=`basename $0` ++echo "QA output created by $seq" ++ ++# get standard environment, filters and checks ++. ./common.product ++. ./common.filter ++. ./common.check ++ ++which curl >/dev/null 2>&1 || _notrun "no curl executable installed" ++ ++_cleanup() ++{ ++ [ -n "$__pid" ] && kill $__pid 2>/dev/null ++ wait $__pid 2>/dev/null ++ cd $here ++ $sudo rm -rf $tmp $tmp.* ++} ++ ++status=0 # success is the default! ++__pid="" ++trap "_cleanup; exit \$status" 0 1 2 3 15 ++ ++# real QA test starts here ++ ++echo "=== checking -Q and -S appear in usage ===" ++pmproxy --help 2>&1 | grep -E '\-[QS]' | sed -e 's/^ *//' ++ ++echo ++echo "=== checking -S enforces authentication on REST API ===" ++__port=`_find_free_port` ++$PCP_BINADM_DIR/pmproxy -S -f -p $__port -l $tmp.log & ++__pid=$! ++sleep 1 ++if kill -0 $__pid 2>/dev/null; then ++ echo "pmproxy with -S started" ++ ++ # unauthenticated request should be rejected ++ __code=`curl -s -o /dev/null -w '%{http_code}' "http://localhost:$__port/pmapi/context?hostspec=localhost" 2>/dev/null` ++ if [ "$__code" = "403" ]; then ++ echo "unauthenticated request correctly rejected (HTTP $__code)" ++ else ++ echo "FAIL: expected HTTP 403, got HTTP $__code" ++ fi ++ ++ kill $__pid ++ wait $__pid 2>/dev/null ++ __pid="" ++else ++ echo "FAIL: pmproxy with -S did not start" ++fi ++ ++echo ++echo "=== checking without -S allows unauthenticated access ===" ++__port=`_find_free_port` ++$PCP_BINADM_DIR/pmproxy -f -p $__port -l $tmp.log2 & ++__pid=$! ++sleep 1 ++if kill -0 $__pid 2>/dev/null; then ++ echo "pmproxy without -S started" ++ ++ # unauthenticated request should succeed ++ __code=`curl -s -o /dev/null -w '%{http_code}' "http://localhost:$__port/pmapi/context?hostspec=localhost" 2>/dev/null` ++ if [ "$__code" = "200" ]; then ++ echo "unauthenticated request correctly allowed (HTTP $__code)" ++ else ++ echo "FAIL: expected HTTP 200, got HTTP $__code" ++ fi ++ ++ kill $__pid ++ wait $__pid 2>/dev/null ++ __pid="" ++else ++ echo "FAIL: pmproxy without -S did not start" ++fi ++ ++# success, all done ++exit +diff --git a/qa/2100.out b/qa/2100.out +new file mode 100644 +index 0000000000..5302aea77a +--- /dev/null ++++ b/qa/2100.out +@@ -0,0 +1,12 @@ ++QA output created by 2100 ++=== checking -Q and -S appear in usage === ++-Q, --certreqd require client certificate authentication ++-S, --reqauth require all client connections to be authenticated ++ ++=== checking -S enforces authentication on REST API === ++pmproxy with -S started ++unauthenticated request correctly rejected (HTTP 403) ++ ++=== checking without -S allows unauthenticated access === ++pmproxy without -S started ++unauthenticated request correctly allowed (HTTP 200) +diff --git a/qa/group b/qa/group +index 80a861c5f6..e538db58e6 100644 +--- a/qa/group ++++ b/qa/group +@@ -2217,4 +2217,5 @@ pmcd.pdu + 1991 pcp netstat python local + 1992 pmda.uwsgi local + 2105 libpcp local security ++2100 pmproxy local security + 4751 libpcp threads valgrind local pcp helgrind +diff --git a/src/pmproxy/src/pmproxy.c b/src/pmproxy/src/pmproxy.c +index 845479c467..ff18396bfa 100644 +--- a/src/pmproxy/src/pmproxy.c ++++ b/src/pmproxy/src/pmproxy.c +@@ -82,7 +82,9 @@ static pmLongOptions longopts[] = { + PMAPI_OPTIONS_HEADER("Connection options"), + { "interface", 1, 'i', "ADDR", "accept connections on this IP address" }, + { "port", 1, 'p', "PORT", "accept connections on this port" }, ++ { "certreqd", 0, 'Q', 0, "require client certificate authentication" }, + { "socket", 1, 's', "PATH", "Unix domain socket file [default $PCP_RUN_DIR/pmproxy.socket]" }, ++ { "reqauth", 0, 'S', 0, "require all client connections to be authenticated" }, + { "keyport", 1, 'r', "PORT", "Connect to key server on this TCP/IP port (implies --timeseries)" }, + { "keyhost", 1, 'h', "HOST", "Connect to key server on this host name (implies --timeseries)" }, + { "redisport", 1, 'r', "PORT", "Backwards-compatibility option, do not use" }, +@@ -95,7 +97,7 @@ static pmLongOptions longopts[] = { + }; + + static pmOptions opts = { +- .short_options = "Ac:dD:Ffh:i:l:L:p:r:s:tT:U:x:?", ++ .short_options = "Ac:dD:Ffh:i:l:L:p:Qr:s:StT:U:x:?", + .long_options = longopts, + }; + diff --git a/pcp-RHEL-213736.patch b/pcp-RHEL-213736.patch new file mode 100644 index 0000000..297b522 --- /dev/null +++ b/pcp-RHEL-213736.patch @@ -0,0 +1,2092 @@ +From ef848fb978 Mon Sep 17 00:00:00 2001 +From: Nathan Scott +Subject: [PATCH] libpcp: fix integer overflow in __pmGetPDU() (CWE-190) + +When php->len is near INT_MAX (e.g. 0x7FFFFFFF), the buffer size +computation PDU_CHUNK * (1 + php->len / PDU_CHUNK) overflows signed +int, producing a negative value that permanently corrupts the static +maxsize variable. Every subsequent __pmFindPDUBuf() call returns NULL, +rendering the affected daemon (pmlogger, pmcd) unable to process any +further PDUs for the remainder of its lifetime — a persistent denial +of service requiring a restart. + +Fix: add an overflow guard (php->len > INT_MAX - PDU_CHUNK) before +the multiplication, returning PM_ERR_TOOBIG for absurdly large PDU +lengths. This protects the NO_LIMIT code path used by pmcd and +pmlogger that is not covered by the existing ceiling check. + +Also add _filter_pmcd() to qa/common.pmcd.pdu to normalize fd=N in +pmcd log output, and qa/2105 with a crafted PDU exercising the +overflow. + +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) + +Resolves: RHEL-213736 CVE-2026-16529 +--- +diff --git a/qa/2105 b/qa/2105 +new file mode 100755 +index 0000000000..44b849ad39 +--- /dev/null ++++ b/qa/2105 +@@ -0,0 +1,17 @@ ++#!/bin/sh ++# PCP QA Test No. 2105 ++# Verify __pmGetPDU rejects PDU with len near INT_MAX ++# (integer overflow in buffer size computation, CWE-190) ++# ++# Copyright (c) 2026 Red Hat. All Rights Reserved. ++# ++ ++seq=`basename $0` ++echo "QA output created by $seq" ++ ++pdu_data=pdudata/pdu-getpdu-overflow ++grep_pattern="bad PDU len=.*exceeds maximum|PDU len=.*too large" ++ ++# this is one of the generic pmcd PDU exerciser tests ... ++# ++. ./common.pmcd.pdu +diff --git a/qa/2105.out b/qa/2105.out +new file mode 100644 +index 0000000000..a304f9d913 +--- /dev/null ++++ b/qa/2105.out +@@ -0,0 +1,10 @@ ++QA output created by 2105 ++expect error(s) to be logged ... ++__pmGetPDU: fd=N type=0x8000 bad PDU len=2147483647 in hdr exceeds maximum client PDU size (65536) ++ ++and no valgrind badness ... ++Memcheck, a memory error detector ++LEAK SUMMARY: ++definitely lost: 0 bytes in 0 blocks ++indirectly lost: 0 bytes in 0 blocks ++ERROR SUMMARY: 0 errors from 0 contexts ... +diff --git a/qa/common.pmcd.pdu b/qa/common.pmcd.pdu +index d9e3c6c5c9..9882284b5c 100644 +--- a/qa/common.pmcd.pdu ++++ b/qa/common.pmcd.pdu +@@ -55,6 +55,14 @@ _filter() + # end + } + ++_filter_pmcd() ++{ ++ sed \ ++ -e 's/fd=[0-9][0-9]*/fd=N/g' \ ++ -e 's/^\[.*\] pmcd([0-9]*) [A-Za-z]*: //' \ ++ # end ++} ++ + mkdir $tmp || exit 1 + cd $tmp + grep sampledso $PCP_PMCDCONF_PATH >pmcd.conf +@@ -91,7 +99,7 @@ wait + [ -s $tmp.err ] && cat $tmp.err + + echo "expect error(s) to be logged ..." +-grep -E "$grep_pattern" pmcd.log ++grep -E "$grep_pattern" pmcd.log | _filter_pmcd + + echo + echo "and no valgrind badness ..." +diff --git a/qa/group b/qa/group +index d4da513ce2..80a861c5f6 100644 +--- a/qa/group ++++ b/qa/group +@@ -2216,4 +2216,5 @@ pmcd.pdu + 1990 pcp buddyinfo python local + 1991 pcp netstat python local + 1992 pmda.uwsgi local ++2105 libpcp local security + 4751 libpcp threads valgrind local pcp helgrind +diff --git a/qa/pdudata/pdu-getpdu-overflow b/qa/pdudata/pdu-getpdu-overflow +new file mode 100644 +index 0000000000..e69de29bb2 +diff --git a/src/libpcp/src/pdu.c b/src/libpcp/src/pdu.c +index 5845932be1..0a4ae75b25 100644 +--- a/src/libpcp/src/pdu.c ++++ b/src/libpcp/src/pdu.c +@@ -658,6 +658,14 @@ check_read_len: + + PM_LOCK(pdu_lock); + if (php->len > maxsize) { ++ if (php->len > INT_MAX - PDU_CHUNK) { ++ PM_UNLOCK(pdu_lock); ++ if (pmDebugOptions.pdu) ++ pmNotifyErr(LOG_ERR, "%s: fd=%d PDU len=%d too large", ++ __FUNCTION__, fd, php->len); ++ __pmUnpinPDUBuf(pdubuf); ++ return PM_ERR_TOOBIG; ++ } + tmpsize = PDU_CHUNK * ( 1 + php->len / PDU_CHUNK); + maxsize = tmpsize; + } +diff --git a/src/pcp/atop/photoproc.c.orig b/src/pcp/atop/photoproc.c.orig +deleted file mode 100644 +index 6e789417db..0000000000 +--- a/src/pcp/atop/photoproc.c.orig ++++ /dev/null +@@ -1,386 +0,0 @@ +-/* +-** Copyright (C) 2015-2017,2019-2022 Red Hat. +-** +-** This program is free software; you can redistribute it and/or modify it +-** under the terms of the GNU General Public License as published by the +-** Free Software Foundation; either version 2, or (at your option) any +-** later version. +-** +-** This program is distributed in the hope that it will be useful, but +-** WITHOUT ANY WARRANTY; without even the implied warranty of +-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +-** See the GNU General Public License for more details. +-*/ +- +-#include +-#include +-#include +- +-#include "atop.h" +-#include "photoproc.h" +-#include "procmetrics.h" +- +-static pmID pmids[TASK_NMETRICS]; +-static pmDesc descs[TASK_NMETRICS]; +- +-extern char prependenv; +-extern regex_t envregex; +- +-/* +-** store the full command line +-** +-** the command line may be prepended by environment variables +-*/ +- +-#define ABBENVLEN 16 +- +-static void +-proccmd(struct tstat *task, int pid, char *name, pmResult *rp, pmDesc *dp, int offset) +-{ +- size_t env_len = 0, next_len; +- char *p, *q, *pc, *nametail = name; +- char environ[BUFSIZ]; +- +- strsep(&nametail, " "); /* remove process identifier prefix; might fail */ +- pc = nametail ? nametail : name; +- +- if (prependenv) +- { +- p = extract_string_inst(rp, dp, TASK_GEN_ENVIRON, &environ[0], +- sizeof environ, pid, offset); +- while ((p = strsep(&p, " "))) +- { +- if (!regexec(&envregex, p, 0, NULL, 0)) +- { +- if ((q = strchr(p, ' ')) == NULL) +- next_len = strlen(p); +- else +- next_len = q - p; +- +- if (env_len + next_len >= CMDLEN) +- { +- // try to add abbreviated env string +- // +- if (env_len + ABBENVLEN + 1 >= CMDLEN) +- { +- break; +- } +- else +- { +- p[ABBENVLEN-4] = '.'; +- p[ABBENVLEN-3] = '.'; +- p[ABBENVLEN-2] = '.'; +- p[ABBENVLEN-1] = '\0'; +- p[ABBENVLEN] = '\0'; +- next_len= ABBENVLEN; +- } +- } +- +- env_len += next_len; +- +- *(p+next_len-1) = ' '; // modify NULL byte to space +- +- strcpy(pc, p); +- pc += next_len; +- } +- } +- } +- +- strncpy(task->gen.cmdline, pc, CMDLEN-env_len); +- task->gen.cmdline[CMDLEN] = '\0'; +-} +- +-/* +-** sampled proc values into task structure, for one process/thread +-*/ +-static void +-update_task(struct tstat *task, int pid, char *name, pmResult *rp, pmDesc *dp, int offset) +-{ +- int key; +- char buf[32]; +- char cgname[CGRLEN+2]; +- +- memset(task, 0, sizeof(struct tstat)); +- +- proccmd(task, pid, name, rp, dp, offset); +- task->gen.isproc = 1; /* thread/process marker */ +- +- /* accumulate Pss from smaps (optional, relatively expensive) */ +- if (!calcpss) +- task->mem.pmem = (unsigned long long)-1; +- else +- task->mem.pmem = extract_ucount_t_inst(rp, dp, TASK_MEM_PMEM, pid, offset); +- +- /* determine wchan if wanted (optional, relatively expensive) */ +- if (getwchan) +- extract_string_inst(rp, dp, TASK_GEN_WCHAN, &task->cpu.wchan[0], +- sizeof task->cpu.wchan, pid, offset); +- +- /* /proc/pid/cgroup */ +- extract_string_inst(rp, dp, TASK_GEN_CONTAINER, &task->gen.utsname[0], +- sizeof task->gen.utsname, pid, offset); +- if (task->gen.utsname[0] != '\0') +- supportflags |= CONTAINERSTAT; +- +- cgname[0] = '\0'; +- extract_string_inst(rp, dp, TASK_GEN_CGROUP, &cgname[0], +- sizeof cgname, pid, offset); +- if (cgname[0] == ':') +- { +- strncpy(task->gen.cgpath, &cgname[1], sizeof task->gen.cgpath); +- task->gen.cgpath[sizeof task->gen.cgpath - 1] = '\0'; +- supportflags |= CGROUPV2; +- } +- +- /* /proc/pid/stat */ +- extract_string_inst(rp, dp, TASK_GEN_NAME, &task->gen.name[0], +- sizeof(task->gen.name), pid, offset); +- extract_string_inst(rp, dp, TASK_GEN_STATE, &task->gen.state, +- sizeof(task->gen.state), pid, offset); +- +- task->gen.pid = extract_integer_inst(rp, dp, TASK_GEN_PID, pid, offset); +- task->gen.ppid = extract_integer_inst(rp, dp, TASK_GEN_PPID, pid, offset); +- if (task->gen.ppid <= 0 && pid != 1) +- task->gen.ppid = 1; +- task->mem.minflt = extract_count_t_inst(rp, dp, TASK_MEM_MINFLT, pid, offset); +- task->mem.majflt = extract_count_t_inst(rp, dp, TASK_MEM_MAJFLT, pid, offset); +- task->cpu.utime = extract_count_t_inst(rp, dp, TASK_CPU_UTIME, pid, offset); +- task->cpu.stime = extract_count_t_inst(rp, dp, TASK_CPU_STIME, pid, offset); +- task->cpu.prio = extract_integer_inst(rp, dp, TASK_CPU_PRIO, pid, offset); +- task->cpu.nice = extract_integer_inst(rp, dp, TASK_CPU_NICE, pid, offset); +- task->gen.btime = extract_integer_inst(rp, dp, TASK_GEN_BTIME, pid, offset); +- task->mem.vmem = extract_count_t_inst(rp, dp, TASK_MEM_VMEM, pid, offset); +- task->mem.rmem = extract_count_t_inst(rp, dp, TASK_MEM_RMEM, pid, offset); +- task->cpu.curcpu = extract_integer_inst(rp, dp, TASK_CPU_CURCPU, pid, offset); +- task->cpu.rtprio = extract_integer_inst(rp, dp, TASK_CPU_RTPRIO, pid, offset); +- task->cpu.policy = extract_integer_inst(rp, dp, TASK_CPU_POLICY, pid, offset); +- task->cpu.rundelay = extract_integer_inst(rp, dp, TASK_CPU_RUNDELAY, pid, offset); +- task->cpu.blkdelay = extract_integer_inst(rp, dp, TASK_CPU_BLKDELAY, pid, offset); +- +- task->cpu.nvcsw = extract_count_t_inst(rp, dp, TASK_CPU_NVCTXSW, pid, offset); +- task->cpu.nivcsw = extract_count_t_inst(rp, dp, TASK_CPU_NIVCTXSW, pid, offset); +- +- task->cpu.cgcpuweight = -2; /* not available */ +- task->cpu.cgcpumax = task->cpu.cgcpumaxr = -2; /* not available */ +- +- /* /proc/pid/status */ +- task->gen.nthr = extract_integer_inst(rp, dp, TASK_GEN_NTHR, pid, offset); +- task->gen.tgid = extract_integer_inst(rp, dp, TASK_GEN_TGID, pid, offset); +- if (task->gen.tgid <= 0) +- task->gen.tgid = pid; +- task->gen.ctid = extract_integer_inst(rp, dp, TASK_GEN_ENVID, pid, offset); +- task->gen.vpid = extract_integer_inst(rp, dp, TASK_GEN_VPID, pid, offset); +- +- task->gen.ruid = extract_integer_inst(rp, dp, TASK_GEN_RUID, pid, offset); +- task->gen.euid = extract_integer_inst(rp, dp, TASK_GEN_EUID, pid, offset); +- task->gen.suid = extract_integer_inst(rp, dp, TASK_GEN_SUID, pid, offset); +- task->gen.fsuid = extract_integer_inst(rp, dp, TASK_GEN_FSUID, pid, offset); +- task->gen.rgid = extract_integer_inst(rp, dp, TASK_GEN_RGID, pid, offset); +- task->gen.egid = extract_integer_inst(rp, dp, TASK_GEN_EGID, pid, offset); +- task->gen.sgid = extract_integer_inst(rp, dp, TASK_GEN_SGID, pid, offset); +- task->gen.fsgid = extract_integer_inst(rp, dp, TASK_GEN_FSGID, pid, offset); +- +- task->mem.vdata = extract_count_t_inst(rp, dp, TASK_MEM_VDATA, pid, offset); +- task->mem.vstack = extract_count_t_inst(rp, dp, TASK_MEM_VSTACK, pid, offset); +- task->mem.vexec = extract_count_t_inst(rp, dp, TASK_MEM_VEXEC, pid, offset); +- task->mem.vlibs = extract_count_t_inst(rp, dp, TASK_MEM_VLIBS, pid, offset); +- task->mem.vswap = extract_count_t_inst(rp, dp, TASK_MEM_VSWAP, pid, offset); +- task->mem.vlock = extract_count_t_inst(rp, dp, TASK_MEM_VLOCK, pid, offset); +- +- task->mem.cgmemmax = task->mem.cgmemmaxr = -2; /* not available */ +- task->mem.cgswpmax = task->mem.cgswpmaxr = -2; /* not available */ +- +- /* /proc/pid/io */ +- task->dsk.rsz = extract_count_t_inst(rp, dp, TASK_DSK_RSZ, pid, offset); +- task->dsk.wsz = extract_count_t_inst(rp, dp, TASK_DSK_WSZ, pid, offset); +- task->dsk.cwsz = extract_count_t_inst(rp, dp, TASK_DSK_CWSZ, pid, offset); +- +- /* user names (cached) */ +- key = task->gen.ruid; +- if (get_username(task->gen.ruid) == NULL && +- extract_string_inst(rp, dp, TASK_GEN_RUIDNM, buf, sizeof buf, pid, offset)) +- add_username(key, buf); +- if (key != task->gen.euid && get_username(task->gen.euid) == NULL && +- extract_string_inst(rp, dp, TASK_GEN_EUIDNM, buf, sizeof buf, pid, offset)) +- add_username(key, buf); +- if (key != task->gen.suid && get_username(task->gen.suid) == NULL && +- extract_string_inst(rp, dp, TASK_GEN_SUIDNM, buf, sizeof buf, pid, offset)) +- add_username(key, buf); +- if (key != task->gen.fsuid && get_username(task->gen.fsuid) == NULL && +- extract_string_inst(rp, dp, TASK_GEN_FSUIDNM, buf, sizeof buf, pid, offset)) +- add_username(key, buf); +- +- /* group names (cached) */ +- key = task->gen.rgid; +- if (get_groupname(task->gen.rgid) == NULL && +- extract_string_inst(rp, dp, TASK_GEN_RGIDNM, buf, sizeof buf, pid, offset)) +- add_groupname(key, buf); +- if (key != task->gen.egid && get_groupname(task->gen.egid) == NULL && +- extract_string_inst(rp, dp, TASK_GEN_EGIDNM, buf, sizeof buf, pid, offset)) +- add_groupname(key, buf); +- if (key != task->gen.sgid && get_groupname(task->gen.sgid) == NULL && +- extract_string_inst(rp, dp, TASK_GEN_SGIDNM, buf, sizeof buf, pid, offset)) +- add_groupname(key, buf); +- if (key != task->gen.fsgid && get_groupname(task->gen.fsgid) == NULL && +- extract_string_inst(rp, dp, TASK_GEN_FSGIDNM, buf, sizeof buf, pid, offset)) +- add_groupname(key, buf); +- +- /* +- ** normalization +- */ +- task->cpu.prio += 100; /* was subtracted by kernel */ +- +- switch (task->gen.state) +- { +- case 'R': +- task->gen.nthrrun = 1; +- break; +- case 'S': +- task->gen.nthrslpi = 1; +- break; +- case 'I': +- task->gen.nthridle = 1; +- break; +- case 'D': +- task->gen.nthrslpu = 1; +- break; +- } +- +- if (task->gen.tgid > 0 && task->gen.tgid != pid) +- task->gen.isproc = 0; +- +- if (task->dsk.rsz >= 0) +- supportflags |= IOSTAT; +- +- task->dsk.rio = task->dsk.rsz /= 512; /* sectors */ +- task->dsk.wio = task->dsk.wsz /= 512; /* sectors */ +- task->dsk.cwsz /= 512; /* sectors */ +-} +- +-/* +-** kernel.all.pid_max is unavailable, fall back to heuristics. +-** Firstly seek out the maximum PID from the proc indom for a +-** single sample, or (in the case of an archive) all available +-** samples. If that fails fallback to some sensible default. +-*/ +-int +-getmaxpid(void) +-{ +- char **insts; +- int *pids, maxpid = 0; +- unsigned long i, count; +- +- count = get_instances("maxpid", TASK_GEN_PID, descs, &pids, &insts); +- if (count > 0) { +- for (i = 0; i < count; i++) +- if (pids[i] > maxpid) +- maxpid = pids[i]; +- free(insts); +- free(pids); +- } +- if (!maxpid) +- return (1 << 15); +- return maxpid; +-} +- +-void +-setup_photoproc(void) +-{ +- unsigned long i; +- +- if (!hotprocflag) +- for (i = 0; i < TASK_NMETRICS; i++) +- procmetrics[i] += 3; /* skip "hot" */ +- +- setup_metrics(procmetrics, pmids, descs, TASK_NMETRICS); +- +- /* check if per-process network metrics are available */ +- netproc_probe(); +-} +- +-unsigned long +-photoproc(struct tstat **tasks, unsigned long *taskslen) +-{ +- static int setup; +- static pmID envid, pssid, wchanid; +- pmResult *result; +- char **insts; +- int *pids, offset; +- unsigned long count, i; +- +- if (!setup) +- { +- wchanid = pmids[TASK_GEN_WCHAN]; +- pssid = pmids[TASK_MEM_PMEM]; +- envid = pmids[TASK_GEN_ENVIRON]; +- setup = 1; +- } +- +- /* +- ** reading the smaps file for every process with every sample +- ** is quite 'expensive' from a CPU consumption point-of-view, +- ** so gathering this info is optional +- */ +- if (!calcpss) +- pmids[TASK_MEM_PMEM] = PM_ID_NULL; +- else +- pmids[TASK_MEM_PMEM] = pssid; +- +- /* +- ** similar situation reading the environment of every process +- */ +- if (!prependenv) +- pmids[TASK_GEN_ENVIRON] = PM_ID_NULL; +- else +- pmids[TASK_GEN_ENVIRON] = envid; +- +- /* +- ** determine thread's wchan, if wanted ('expensive' from +- ** a CPU consumption point-of-view) +- */ +- if (!getwchan) +- pmids[TASK_GEN_WCHAN] = PM_ID_NULL; +- else +- pmids[TASK_GEN_WCHAN] = wchanid; +- +- fetch_metrics("task", TASK_NMETRICS, pmids, &result); +- +- /* extract external process names (insts) */ +- count = fetch_instances("task", TASK_GEN_NAME, descs, &pids, &insts); +- if (count > *taskslen) +- { +- size_t size = count * sizeof(struct tstat); +- +- *tasks = (struct tstat *)realloc(*tasks, size); +- ptrverify(*tasks, "photoproc [%ld]\n", (long)size); +- *taskslen = count; +- } +- +- supportflags &= ~CONTAINERSTAT; +- +- for (i=0; i < count; i++) +- { +- if (pmDebugOptions.appl0) +- fprintf(stderr, "%s: updating process %d: %s\n", +- pmGetProgname(), pids[i], insts[i]); +- offset = get_instance_index(result, TASK_GEN_PID, pids[i]); +- update_task(&(*tasks)[i], pids[i], insts[i], result, descs, offset); +- } +- +- if (supportflags & NETATOP) +- netproc_update_tasks(tasks, count); +- +- if (supportflags & NETATOPBPF) +- netbpfproc_update_tasks(tasks, count); +- +- if (pmDebugOptions.appl0) +- fprintf(stderr, "%s: done %lu processes\n", pmGetProgname(), count); +- +- pmFreeResult(result); +- if (count > 0) { +- free(insts); +- free(pids); +- } +- +- return count; +-} +diff --git a/src/pmdas/ds389/pmdads389.pl.orig b/src/pmdas/ds389/pmdads389.pl.orig +deleted file mode 100644 +index 1679c0415e..0000000000 +--- a/src/pmdas/ds389/pmdads389.pl.orig ++++ /dev/null +@@ -1,465 +0,0 @@ +-# +-# Copyright (C) 2014-2015 Marko Myllynen +-# Copyright (C) 2021 Raul Mahiques +-# +-# This program is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License as published by the +-# Free Software Foundation; either version 2 of the License, or (at your +-# option) any later version. +-# +-# This program is distributed in the hope that it will be useful, but +-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +-# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# for more details. +-# +- +-use strict; +-use warnings; +-use PCP::PMDA; +-use POSIX; +- +-my $have_ldap = eval { +- require Net::LDAP; +- Net::LDAP->import(); +- use Net::LDAP::Util; +- 1; +-}; +-if (!$have_ldap) { die("Net::LDAP unavailable on this platform"); } +- +-# Default values +-our $aname = 'ds389'; +-our $server = 'localhost'; +-# Default LDAP version to use. +-our $ldapver = 3; +-our $binddn = 'cn=Directory Manager'; +-our $bindpw = 'Manager12'; +-# Default scope +-our $dfscope = 'base'; +-# Default LDAP filter +-our $dffilter = '(objectclass=*)'; +-# Default LDAP attributes to retrieve +-our $dattrs = ['*', '+']; +-# How often it will check +-our $query_interval = 2; # seconds +-# Metrics defaults +-our $mpm_type = PM_TYPE_U32; +-our $mpm_indom = PM_INDOM_NULL; +-our $mpm_sem = PM_SEM_INSTANT; +-# Format: dim_space, dim_time, dim_count, scale_space, scale_time, scale_count +-our $mpmda_units = '0,0,1,0,0,'.PM_COUNT_ONE; +-our @add_met = (); +-our %dclu; +- +-# Default base and metrics +-our %dataclusters = ( +- '0' => ['0','cn=monitor','cn.',$dfscope,$dffilter,$dattrs], +- '1' => ['0','cn=monitor,cn=userRoot,cn=ldbm database,cn=plugins,cn=config','userroot.',$dfscope,$dffilter,$dattrs], +- '2' => ['0','cn=monitor,cn=changelog,cn=ldbm database,cn=plugins,cn=config','changelog_mon.',$dfscope,$dffilter,$dattrs], +- '3' => ['0','cn=snmp,cn=monitor','snmp_mon.',$dfscope,$dffilter,$dattrs] +-); +-our @def_met = ( +- [0,0,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'threads'], +- [0,1,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'currentconnections'], +- [0,2,PM_TYPE_U64,$mpm_indom,PM_SEM_COUNTER,$mpmda_units,'totalconnections'], +- [0,3,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'currentconnectionsatmaxthreads'], +- [0,4,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'maxthreadsperconnhits'], +- [0,5,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'dtablesize'], +- [0,6,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'readwaiters'], +- [0,7,PM_TYPE_U64,$mpm_indom,$mpm_sem,$mpmda_units,'opsinitiated'], +- [0,8,PM_TYPE_U64,$mpm_indom,$mpm_sem,$mpmda_units,'opscompleted'], +- [0,9,PM_TYPE_U64,$mpm_indom,$mpm_sem,$mpmda_units,'entriessent'], +- [0,10,PM_TYPE_U64,$mpm_indom,$mpm_sem,'1,0,0,'.PM_SPACE_BYTE.',0,0','bytessent'], +- [0,11,$mpm_type,$mpm_indom,$mpm_sem,'0,1,0,0,'.PM_TIME_SEC.',0','uptime'], +- [0,12,PM_TYPE_STRING,$mpm_indom,PM_SEM_DISCRETE,'0,0,0,0,0,0','version'], +- [0,13,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'nbackends'], +- [1,0,$mpm_type,$mpm_indom,$mpm_sem,'0,0,0,0,0,0','readonly'], +- [1,1,PM_TYPE_U64,$mpm_indom,PM_SEM_COUNTER,$mpmda_units,'entrycachehits'], +- [1,2,PM_TYPE_U64,$mpm_indom,PM_SEM_COUNTER,$mpmda_units,'entrycachetries'], +- [1,3,PM_TYPE_U64,$mpm_indom,$mpm_sem,$mpmda_units,'entrycachehitratio'], +- [1,4,PM_TYPE_U64,$mpm_indom,$mpm_sem,'1,0,0,'.PM_SPACE_BYTE.',0,0','currententrycachesize'], +- [1,5,PM_TYPE_U64,$mpm_indom,PM_SEM_DISCRETE,'1,0,0,'.PM_SPACE_BYTE.',0,0','maxentrycachesize'], +- [1,6,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'currententrycachecount'], +- [1,7,PM_TYPE_32,$mpm_indom,$mpm_sem,$mpmda_units,'maxentrycachecount'], +- [1,8,PM_TYPE_U64,$mpm_indom,PM_SEM_COUNTER,$mpmda_units,'dncachehits'], +- [1,9,PM_TYPE_U64,$mpm_indom,PM_SEM_COUNTER,$mpmda_units,'dncachetries'], +- [1,10,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'dncachehitratio'], +- [1,11,$mpm_type,$mpm_indom,$mpm_sem,'1,0,0,'.PM_SPACE_BYTE.',0,0','currentdncachesize'], +- [1,12,$mpm_type,$mpm_indom,PM_SEM_DISCRETE,'1,0,0,'.PM_SPACE_BYTE.',0,0','maxdncachesize'], +- [1,13,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'currentdncachecount'], +- [1,14,PM_TYPE_32,$mpm_indom,$mpm_sem,$mpmda_units,'maxdncachecount'], +- [1,15,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'normalizeddncachehits'], +- [1,16,PM_TYPE_32,$mpm_indom,$mpm_sem,$mpmda_units,'normalizeddncachetries'], +- [1,17,PM_TYPE_32,$mpm_indom,$mpm_sem,$mpmda_units,'normalizeddncachehitratio'], +- [1,18,PM_TYPE_32,$mpm_indom,$mpm_sem,'1,0,0,'.PM_SPACE_BYTE.',0,0','currentnormalizeddncachesize'], +- [1,19,PM_TYPE_32,$mpm_indom,$mpm_sem,'1,0,0,'.PM_SPACE_BYTE.',0,0','maxnormalizeddncachesize'], +- [1,20,PM_TYPE_32,$mpm_indom,$mpm_sem,$mpmda_units,'currentnormalizeddncachecount'], +- [1,21,PM_TYPE_32,$mpm_indom,$mpm_sem,$mpmda_units,'normalizeddncachemisses'], +- [2,0,$mpm_type,$mpm_indom,$mpm_sem,'0,0,0,0,0,0','readonly'], +- [2,1,PM_TYPE_U64,$mpm_indom,PM_SEM_COUNTER,$mpmda_units,'entrycachehits'], +- [2,2,PM_TYPE_U64,$mpm_indom,PM_SEM_COUNTER,$mpmda_units,'entrycachetries'], +- [2,3,PM_TYPE_U64,$mpm_indom,$mpm_sem,$mpmda_units,'entrycachehitratio'], +- [2,4,PM_TYPE_U64,$mpm_indom,$mpm_sem,'1,0,0,'.PM_SPACE_BYTE.',0,0','currententrycachesize'], +- [2,5,PM_TYPE_U64,$mpm_indom,PM_SEM_DISCRETE,'1,0,0,'.PM_SPACE_BYTE.',0,0','maxentrycachesize'], +- [2,6,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'currententrycachecount'], +- [2,7,PM_TYPE_32,$mpm_indom,$mpm_sem,$mpmda_units,'maxentrycachecount'], +- [2,8,PM_TYPE_U64,$mpm_indom,PM_SEM_COUNTER,$mpmda_units,'dncachehits'], +- [2,9,PM_TYPE_U64,$mpm_indom,PM_SEM_COUNTER,$mpmda_units,'dncachetries'], +- [2,10,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'dncachehitratio'], +- [2,11,$mpm_type,$mpm_indom,$mpm_sem,'1,0,0,'.PM_SPACE_BYTE.',0,0','currentdncachesize'], +- [2,12,$mpm_type,$mpm_indom,PM_SEM_DISCRETE,'1,0,0,'.PM_SPACE_BYTE.',0,0','maxdncachesize'], +- [2,13,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'currentdncachecount'], +- [2,14,PM_TYPE_32,$mpm_indom,$mpm_sem,$mpmda_units,'maxdncachecount'], +- [3,0,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'anonymousbinds'], +- [3,1,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'unauthbinds'], +- [3,2,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'simpleauthbinds'], +- [3,3,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'strongauthbinds'], +- [3,4,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'bindsecurityerrors'], +- [3,5,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'inops'], +- [3,6,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'readops'], +- [3,7,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'compareops'], +- [3,8,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'addentryops'], +- [3,9,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'modifyentryops'], +- [3,10,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'modifyrdnops'], +- [3,11,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'listops'], +- [3,12,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'searchops'], +- [3,13,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'onelevelsearchops'], +- [3,14,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'wholesubtreesearchops'], +- [3,15,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'referrals'], +- [3,16,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'chainings'], +- [3,17,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'securityerrors'], +- [3,18,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'errors'], +- [3,19,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'connections'], +- [3,20,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'connectionseq'], +- [3,21,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'connectionsinmaxthreads'], +- [3,22,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'connectionsmaxthreadscount'], +- [3,23,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'bytesrecv'], +- [3,24,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'bytessent'], +- [3,25,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'entriesreturned'], +- [3,26,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'referralsreturned'], +- [3,27,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'masterentries'], +- [3,28,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'cacheentries'], +- [3,29,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'cachehits'], +- [3,30,$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'slavehits'] +-); +- +-our @def_replagr_met = ( +- [$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'nsds5ReplicaChangeCount'], +- [$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'nsds5replicareapactive'] +-); +- +-our @def_repl_met = ( +- [$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'nsds5replicareapactive'], +- [$mpm_type,$mpm_indom,$mpm_sem,'0,1,0,0,'.PM_TIME_SEC.',0','nsruvReplicaLastModified'], +- [$mpm_type,$mpm_indom,$mpm_sem,'0,1,0,0,'.PM_TIME_SEC.',0','nsds5replicaLastUpdateStart'], +- [$mpm_type,$mpm_indom,$mpm_sem,'0,1,0,0,'.PM_TIME_SEC.',0','nsds5replicaLastUpdateEnd'], +- [$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'nsds5replicaChangesSentSinceStartup'], +- [$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'replicaLastUpdateStatus'], +- [$mpm_type,$mpm_indom,$mpm_sem,'0,1,0,0,'.PM_TIME_SEC.',0','nsds5replicaLastInitStart'], +- [$mpm_type,$mpm_indom,$mpm_sem,'0,1,0,0,'.PM_TIME_SEC.',0','nsds5replicaLastInitEnd'], +- [$mpm_type,$mpm_indom,$mpm_sem,'0,1,0,0,'.PM_TIME_SEC.',0','nsds5replicaLastUpdateTime'], +- [$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'nsds5replicaUpdateInProgeress'], +- [$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'replicaChangesSkippedSinceStartup'], +- [$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'replicaChangesSentSinceStartup'] +-); +- +-our @def_mon_met = ( +- [$mpm_type,$mpm_indom,$mpm_sem,'0,0,0,0,0,0','readonly'], +- [PM_TYPE_U64,$mpm_indom,PM_SEM_COUNTER,$mpmda_units,'entrycachehits'], +- [PM_TYPE_U64,$mpm_indom,PM_SEM_COUNTER,$mpmda_units,'entrycachetries'], +- [PM_TYPE_U64,$mpm_indom,$mpm_sem,$mpmda_units,'entrycachehitratio'], +- [PM_TYPE_U64,$mpm_indom,$mpm_sem,'1,0,0,'.PM_SPACE_BYTE.',0,0','currententrycachesize'], +- [PM_TYPE_U64,$mpm_indom,PM_SEM_DISCRETE,'1,0,0,'.PM_SPACE_BYTE.',0,0','maxentrycachesize'], +- [$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'currententrycachecount'], +- [PM_TYPE_32,$mpm_indom,$mpm_sem,$mpmda_units,'maxentrycachecount'], +- [PM_TYPE_U64,$mpm_indom,PM_SEM_COUNTER,$mpmda_units,'dncachehits'], +- [PM_TYPE_U64,$mpm_indom,PM_SEM_COUNTER,$mpmda_units,'dncachetries'], +- [$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'dncachehitratio'], +- [$mpm_type,$mpm_indom,$mpm_sem,'1,0,0,'.PM_SPACE_BYTE.',0,0','currentdncachesize'], +- [$mpm_type,$mpm_indom,PM_SEM_DISCRETE,'1,0,0,'.PM_SPACE_BYTE.',0,0','maxdncachesize'], +- [$mpm_type,$mpm_indom,$mpm_sem,$mpmda_units,'currentdncachecount'], +- [PM_TYPE_32,$mpm_indom,$mpm_sem,$mpmda_units,'maxdncachecount'] +-); +- +- +-# Configuration files for overriding the above settings +-for my $file (pmda_config('PCP_PMDAS_DIR') . "/$aname/$aname.conf", "./$aname.conf") { +- eval `cat $file` unless ! -f $file; +-} +- +-unless (!keys %dclu) { +- %dataclusters = (%dataclusters, %dclu) +-} +- +-use vars qw( $ldap $pmda %metrics ); +- +-sub ds389_connection_setup { +- if (!defined($ldap)) { +- if (!pmda_install()) { $pmda->log("binding to $server"); } +- $ldap = Net::LDAP->new($server,version => $ldapver); +- if (!defined($ldap)) { +- if (!pmda_install()) { $pmda->log("bind failed, server down?"); } +- return; +- } +- my $mesg = $ldap->bind($binddn, password => $bindpw); +- if ($mesg->code) { +- $pmda->log("bind failed: " . $mesg->error); +- return; +- } +- $pmda->log("bind to $server ok"); +- } +-} +- +-# Function copied from https://github.com/389ds/389-ds-base/blob/389-ds-base-1.3.10/ldap/admin/src/scripts/repl-monitor.pl.in +-sub to_decimal_csn +-{ +- my ($maxcsn) = @_; +- if (!$maxcsn || $maxcsn eq "" || $maxcsn eq "Unavailable") { +- return "Unavailable"; +- } +- +- my ($tm, $seq, $masterid, $subseq) = unpack("a8 a4 a4 a4", $maxcsn); +- +- $tm = hex($tm); +- $seq = hex($seq); +- $masterid = hex($masterid); +- $subseq = hex($subseq); +- +- return "$tm $seq $masterid $subseq"; +-} +- +- +- +-sub ds389_time_to_epoch { +- my ($time) = @_; +- return mktime(substr($time,12,2), +- substr($time,10,2), +- substr($time,8,2), +- substr($time,6,2), +- substr($time,4,2) - 1, +- substr($time,0,4) - 1900); +-} +- +-sub ds389_process_entry { +- my ($entry, $prefix, $cluster) = @_; +- my $currtime; +- my $startrepltime = ''; +- my $endrepltime = ''; +- if ($entry && $entry->can('attributes')) { +- foreach my $attr ($entry->attributes) { +- my $value = $entry->get_value($attr); +- +- if ($attr eq 'currenttime') { +- $currtime = ds389_time_to_epoch($value); +- next; +- } +- +- if ($attr eq 'starttime') { +- my $starttime = ds389_time_to_epoch($value); +- $value = $currtime - $starttime; +- $attr = 'uptime'; +- } +- +- if ($attr eq 'nsds5replicaLastUpdateStatus') { +- if ($value =~ /No replication sessions started since server startup/i) { +- $value = 30 +- } elsif ($value =~ /agreement disabled/i) { +- $value = 31 +- } elsif ($value =~ /Problem connecting to the replica/i) { +- $value = 20 +- } else { +- $value = (split /\)/, (split /Error \(/, $value)[1])[0]; +- } +- $attr = 'replicaLastUpdateStatus'; +- } +- +- if ($attr eq 'nsds5replicaChangesSentSinceStartup' ) { +-# my $rep_id = (split /:/, $value)[0]; +- my ($sent, $skipped) = (split /\//, (split /:/, $value)[1]); +-# $attr = 'replica'.$rep_id.'ChangesSentSinceStartup'; +- $attr = 'replicaChangesSentSinceStartup'; +- $metrics{"$aname." . $prefix . $attr} = $sent; +- $value = $skipped; +-# $attr = 'replica'.$rep_id.'ChangesSkippedSinceStartup'; +- $attr = 'replicaChangesSkippedSinceStartup'; +- } +- +- if ($attr eq 'nsds5replicaUpdateInProgress' ) { +- if ($value =~ /^(true|TRUE)$/) { +- $value = 1; +- } else { +- $value = 0; +- } +- } +- +- if ($attr =~ /^(nsds5replicaLastInitEnd|nsds5replicaLastUpdateStart|nsds5replicaLastInitStart)$/i ) { +- $value = ds389_time_to_epoch($value); +- if ($attr eq 'nsds5replicaLastUpdateStart') { +- $startrepltime = $value; +- } +- $metrics{"$aname." . $prefix . $attr} = $value; +- } +- +- if ($endrepltime ne '' && $startrepltime ne '' ) { +- $attr = 'nsds5replicaLastUpdateTime'; +- $value = $endrepltime - $startrepltime; +- $startrepltime = $endrepltime = ''; +- } +- +- if ($attr =~ /^(nsds5replicaLastUpdateEnd)$/i ) { +- $value = ds389_time_to_epoch($value); +- $endrepltime = $value; +- } +- +- if ($attr =~ /^nsds5AgmtMaxCSN$/i ) { +- my $maxcsn = &to_decimal_csn((split /\;/, $value)[5]); +- $value = (split / /, $maxcsn)[0]; +- } +- +- $metrics{"$aname." . $prefix . $attr} = $value; +- } +- } +-} +- +-sub retrieve_ldap { +- my ($cluster, $ts, $base, $tname, $scope, $filter, $lattrs) = @_; +- my $mesg; +- +- if ((strftime("%s", localtime()) - $ts) > $query_interval) { +- $ts = strftime("%s", localtime()); +- $mesg = $ldap->search(scope => $scope, base => $base, filter => $filter, attrs => $lattrs); +- if ($mesg->code) { +- $pmda->log("search(scope: \"$scope\", base: \"$base\", filter: \"$filter\", attrs: \"". join(' ', @$lattrs) ."\") failed: " . $mesg->error); +- undef $ldap; +- return; +- } +- ds389_process_entry($mesg->entry, $tname, $cluster); +- } +-} +- +-sub ds389_fetch { +- if (!defined($ldap)) { +- ds389_connection_setup(); +- } +- return unless defined($ldap); +- +- my ($cluster) = @_; +- my $mesg; +- +- \&retrieve_ldap($cluster,$dataclusters{$cluster}[0],$dataclusters{$cluster}[1],$dataclusters{$cluster}[2],$dataclusters{$cluster}[3],$dataclusters{$cluster}[4], $dataclusters{$cluster}[5]); +-} +- +-sub ds389_fetch_callback { +- my ($cluster, $item, $inst) = @_; +- +- if (!defined($ldap)) { return (PM_ERR_AGAIN, 0); } +- if ($inst != PM_INDOM_NULL) { return (PM_ERR_INST, 0); } +- +- my $pmnm = pmda_pmid_name($cluster, $item); +- my $value = $metrics{$pmnm}; +- +- if (!defined($value)) { return (PM_ERR_APPVERSION, 0); } +- +- return ($value, 1); +-} +- +- +-sub ds389_simple_search { +- my ($scope, $base, $filter, $attrs) = @_; +- +- if (!defined($ldap)) { return; } +- my $mesg = $ldap->search(scope => $scope, base => $base, filter => $filter, attrs => $attrs); +- if ($mesg->code) { +- $pmda->log("search(scope: \"$scope\", base: \"$base\", filter: \"$filter\", attrs: \"". join(' ', @$attrs) ."\") failed: " . $mesg->error); +- undef $ldap; +- return; +- } +- return $mesg +-} +- +-sub push_to_met { +- my ($tc, @myarr) = @_; +- my $count = 0; +- foreach my $c (0 .. $#myarr) { +- push(@def_met, [$tc, $c, $myarr[$c][0], $myarr[$c][1], $myarr[$c][2], $myarr[$c][3], $myarr[$c][4]]); +- }; +-} +- +-$pmda = PCP::PMDA->new($aname, 130); +- +-# Add to the existing ones +-my $topclu = 0; +-foreach my $attr (keys %dataclusters) { +- if ($attr gt $topclu) { +- $topclu = $attr; +- } +-}; +- +-ds389_connection_setup(); +- +-my $mesg = ds389_simple_search('sub','cn=config','objectclass=*',['nsslapd-defaultnamingcontext','nsslapd-backend']); +- +-my $max = defined($mesg) ? $mesg->count : 0; +-for ( my $i = 0 ; $i < $max ; $i++ ) { +- my $entry = $mesg->entry ( $i ); +- foreach my $attr ($entry->attributes) { +- my $value = $entry->get_value($attr); +- my $value_short = $value =~ s/[,]*[a-zA-Z]*=/_/rgi; +- my $value_ldap = $value =~ s/=/\\3D/igr =~ s/,/\\2C/igr; +- if ($attr eq 'nsslapd-defaultnamingcontext') { +- $topclu++; +- $dataclusters{$topclu} = ['0',$value,$value_short . '.','sub','(&(nsuniqueid=ffffffff-ffffffff-ffffffff-ffffffff)(objectclass=nstombstone))',['nsds5agmtmaxcsn','nsds50ruv']]; +- my $mesg2 = ds389_simple_search('sub',"cn=$value_ldap,cn=mapping tree,cn=config",'objectclass=nsds5replicationagreement',['cn']); +- my $max2 = $mesg2->count; +- for ( my $i2 = 0 ; $i2 < $max2 ; $i2++ ) { +- my $entry2 = $mesg2->entry ( $i2 ); +- my $rplagr = $entry2->get_value('cn'); +- $topclu++; +- my $value2_short = (split /\./, $rplagr)[0]; +- $dataclusters{$topclu} = ['0',"cn=". $rplagr .",cn=replica,cn=". $value_ldap .",cn=mapping tree,cn=config",$value2_short . '.',$dfscope,$dffilter,$dattrs]; +- push_to_met($topclu, @def_repl_met); +- $topclu++; +- $dataclusters{$topclu} = ['0',"cn=replica,cn=". $value_ldap .",cn=mapping tree,cn=config","rpl_". $value2_short . '.',$dfscope,$dffilter,$dattrs]; +- push_to_met($topclu, @def_replagr_met); +- } +- } +- if (($attr eq 'nsslapd-backend') and ($value eq 'ipaca')) { +- $topclu++; +- $dataclusters{$topclu} = ['0',$value,$value_short . '.','sub','(&(nsuniqueid=ffffffff-ffffffff-ffffffff-ffffffff)(objectclass=nstombstone))',['nsds5agmtmaxcsn','nsds50ruv']]; +- my $mesg2 = ds389_simple_search('sub',"cn=o\\3D$value_ldap,cn=mapping tree,cn=config",'objectclass=nsds5replicationagreement',['cn']); +- my $max2 = $mesg2->count; +- for ( my $i2 = 0 ; $i2 < $max2 ; $i2++ ) { +- my $entry2 = $mesg2->entry ( $i2 ); +- my $rplagr = $entry2->get_value('cn'); +- $topclu++; +- my $value2_short = (split /\./, $rplagr)[0]; +- $dataclusters{$topclu} = ['0',"cn=". $rplagr .",cn=replica,cn=o\\3D". $value_ldap .",cn=mapping tree,cn=config",$value2_short . '.',$dfscope,$dffilter,$dattrs]; +- push_to_met($topclu, @def_repl_met); +- $topclu++; +- $dataclusters{$topclu} = ['0',"cn=replica,cn=o\\3D". $value_ldap .",cn=mapping tree,cn=config","rpl_". $value2_short . '.',$dfscope,$dffilter,$dattrs]; +- push_to_met($topclu, @def_replagr_met); +- $topclu++; +- $dataclusters{$topclu} = ['0',"cn=monitor,cn=$value,cn=ldbm database,cn=plugins,cn=config",$value ."_mon.",$dfscope,$dffilter,$dattrs]; +- push_to_met($topclu, @def_mon_met); +- } +- } +- }; +-}; +- +-# Add default metrics +-while (my ($i, @met) = each @def_met) { +- if (defined($dataclusters{$def_met[$i][0]})) { +- $pmda->add_metric(pmda_pmid($def_met[$i][0],$def_met[$i][1]), $def_met[$i][2], $def_met[$i][3],$def_met[$i][4], pmda_units(split(',',$def_met[$i][5])),"$aname.$dataclusters{$def_met[$i][0]}[2]$def_met[$i][6]", '', ''); +- } +-}; +- +-# Add metrics from the configuration file +-while (my ($i, @met) = each @add_met) { +- if (defined($dataclusters{$add_met[$i][0]})) { +- $pmda->add_metric(pmda_pmid($add_met[$i][0],$add_met[$i][1]), $add_met[$i][2], $add_met[$i][3],$add_met[$i][4], pmda_units(split(',',$add_met[$i][5])),"$aname.$dataclusters{$add_met[$i][0]}[2]$add_met[$i][6]", '', ''); +- } +-}; +- +-$pmda->set_refresh(\&ds389_fetch); +-$pmda->set_fetch_callback(\&ds389_fetch_callback); +-$pmda->set_user('pcp'); +-$pmda->run; +diff --git a/src/selinux/pcp.te.orig b/src/selinux/pcp.te.orig +deleted file mode 100644 +index 9cbd59bd2b..0000000000 +--- a/src/selinux/pcp.te.orig ++++ /dev/null +@@ -1,1095 +0,0 @@ +-policy_module(pcp, 2.0.0) +- +-######################################## +-# +-# Declarations +-# +- +- +-## +-##

+-## Allow pcp to bind to all unreserved_ports +-##

+-##
+-gen_tunable(pcp_bind_all_unreserved_ports, false) +- +-## +-##

+-## Allow pcp to read generic logs +-##

+-##
+-gen_tunable(pcp_read_generic_logs, false) +- +-attribute pcp_domain; +- +-pcp_domain_template(pmcd) +-pcp_domain_template(pmlogger) +-pcp_domain_template(pmproxy) +-pcp_domain_template(pmie) +-pcp_domain_template(plugin) +- +-type pcp_log_t; +-logging_log_file(pcp_log_t) +- +-type pcp_var_lib_t; +-files_type(pcp_var_lib_t) +- +-type pcp_var_run_t; +-files_pid_file(pcp_var_run_t) +- +-type pcp_tmp_t; +-files_tmp_file(pcp_tmp_t) +- +-type pcp_tmpfs_t; +-files_tmpfs_file(pcp_tmpfs_t) +- +-######################################## +-# +-# pcp domain local policy +-# +- +-allow pcp_domain self:capability { setuid setgid dac_read_search }; +-allow pcp_domain self:process signal_perms; +-allow pcp_domain self:tcp_socket create_stream_socket_perms; +-allow pcp_domain self:udp_socket create_socket_perms; +-allow pcp_domain self:netlink_route_socket create_socket_perms; +-allow pcp_domain self:unix_stream_socket connectto; +- +-corenet_tcp_connect_all_ephemeral_ports(pcp_domain) +- +-manage_dirs_pattern(pcp_domain, pcp_log_t, pcp_log_t) +-manage_files_pattern(pcp_domain, pcp_log_t, pcp_log_t) +-logging_log_filetrans(pcp_domain, pcp_log_t, { dir }) +- +-manage_dirs_pattern(pcp_domain, pcp_var_lib_t, pcp_var_lib_t) +-manage_files_pattern(pcp_domain, pcp_var_lib_t, pcp_var_lib_t) +-manage_sock_files_pattern(pcp_domain, pcp_var_lib_t, pcp_var_lib_t) +-manage_lnk_files_pattern(pcp_domain, pcp_var_lib_t, pcp_var_lib_t) +-exec_files_pattern(pcp_domain, pcp_var_lib_t, pcp_var_lib_t) +-files_var_lib_filetrans(pcp_domain, pcp_var_lib_t, { dir}) +- +-manage_dirs_pattern(pcp_domain, pcp_var_run_t, pcp_var_run_t) +-manage_files_pattern(pcp_domain, pcp_var_run_t, pcp_var_run_t) +-manage_sock_files_pattern(pcp_domain, pcp_var_run_t, pcp_var_run_t) +-manage_lnk_files_pattern(pcp_domain, pcp_var_run_t, pcp_var_run_t) +-files_pid_filetrans(pcp_domain, pcp_var_run_t, { dir file sock_file lnk_file }) +- +-manage_dirs_pattern(pcp_domain, pcp_tmp_t, pcp_tmp_t) +-manage_files_pattern(pcp_domain, pcp_tmp_t, pcp_tmp_t) +-manage_sock_files_pattern(pcp_domain, pcp_tmp_t, pcp_tmp_t) +-files_tmp_filetrans(pcp_domain, pcp_tmp_t, { dir file sock_file }) +- +-manage_dirs_pattern(pcp_domain, pcp_tmpfs_t, pcp_tmpfs_t) +-manage_files_pattern(pcp_domain, pcp_tmpfs_t, pcp_tmpfs_t) +-fs_tmpfs_filetrans(pcp_domain, pcp_tmpfs_t, { dir file }) +-can_exec(pcp_domain, pcp_tmpfs_t) +- +-dev_read_urand(pcp_domain) +- +-files_read_etc_files(pcp_domain) +- +-fs_getattr_all_fs(pcp_domain) +- +-miscfiles_read_generic_certs(pcp_domain) +- +-sysnet_read_config(pcp_domain) +- +-tunable_policy(`pcp_bind_all_unreserved_ports',` +- corenet_sendrecv_all_server_packets(pcp_pmcd_t) +- corenet_sendrecv_all_server_packets(pcp_pmlogger_t) +- corenet_tcp_bind_all_unreserved_ports(pcp_pmcd_t) +- corenet_tcp_bind_all_unreserved_ports(pcp_pmlogger_t) +-') +- +- +-######################################## +-# +-# pcp_pmcd local policy +-# +- +-allow pcp_pmcd_t self:capability { dac_read_search dac_override ipc_owner net_admin sys_admin sys_ptrace }; +-allow pcp_pmcd_t self:process { setsched }; +-allow pcp_pmcd_t self:unix_dgram_socket { create_socket_perms getattr }; +-allow pcp_pmcd_t self:cap_userns sys_ptrace; +- +-kernel_get_sysvipc_info(pcp_pmcd_t) +-kernel_manage_perf_event(pcp_pmcd_t) +-kernel_read_debugfs(pcp_pmcd_t) +-kernel_read_network_state(pcp_pmcd_t) +-kernel_read_system_state(pcp_pmcd_t) +-kernel_read_state(pcp_pmcd_t) +-kernel_read_fs_sysctls(pcp_pmcd_t) +-kernel_read_vm_sysctls(pcp_pmcd_t) +-kernel_read_rpc_sysctls(pcp_pmcd_t) +-kernel_search_network_sysctl(pcp_pmcd_t) +-kernel_read_net_sysctls(pcp_pmcd_t) +-kernel_read_psi(pcp_pmcd_t) +- +-corecmd_exec_bin(pcp_pmcd_t) +-corecmd_exec_shell(pcp_pmcd_t) +- +-corenet_tcp_connect_ntop_port(pcp_pmcd_t) +-corenet_all_recvfrom_netlabel(pcp_pmcd_t) +-corenet_tcp_sendrecv_generic_if(pcp_pmcd_t) +-corenet_tcp_sendrecv_generic_node(pcp_pmcd_t) +- +-corenet_sendrecv_all_client_packets(pcp_pmcd_t) +-corenet_tcp_connect_all_ports(pcp_pmcd_t) +-corenet_tcp_sendrecv_all_ports(pcp_pmcd_t) +- +-corenet_dontaudit_tcp_bind_all_reserved_ports(pcp_pmcd_t) +-corenet_dontaudit_udp_bind_all_reserved_ports(pcp_pmcd_t) +- +-dev_read_sysfs(pcp_pmcd_t) +-dev_read_urand(pcp_pmcd_t) +-dev_rw_lvm_control(pcp_pmcd_t) +- +-domain_read_all_domains_state(pcp_pmcd_t) +-domain_getattr_all_domains(pcp_pmcd_t) +- +-dev_getattr_all_blk_files(pcp_pmcd_t) +-dev_getattr_all_chr_files(pcp_pmcd_t) +- +-fs_getattr_all_fs(pcp_pmcd_t) +-fs_getattr_all_dirs(pcp_pmcd_t) +-fs_list_cgroup_dirs(pcp_pmcd_t) +-fs_read_cgroup_files(pcp_pmcd_t) +-fs_read_nfsd_files(pcp_pmcd_t) +-fs_search_tracefs_dirs(pcp_pmcd_t) +- +-init_read_utmp(pcp_pmcd_t) +- +-logging_send_syslog_msg(pcp_pmcd_t) +- +-lvm_domtrans(pcp_pmcd_t) +- +-storage_getattr_fixed_disk_dev(pcp_pmcd_t) +-storage_raw_read_fixed_disk(pcp_pmcd_t) +- +-userdom_read_user_tmp_files(pcp_pmcd_t) +-userdom_manage_unpriv_user_semaphores(pcp_pmcd_t) +- +-optional_policy(` +- acct_search_data(pcp_pmcd_t) +-') +- +-optional_policy(` +- cron_read_pid_files(pcp_pmcd_t) +-') +- +-optional_policy(` +- container_manage_lib_files(pcp_pmcd_t) +-') +- +-optional_policy(` +- mock_read_lib_files(pcp_pmcd_t) +-') +- +-optional_policy(` +- mysql_stream_connect(pcp_pmcd_t) +-') +- +-optional_policy(` +- dbus_system_bus_client(pcp_pmcd_t) +- +- optional_policy(` +- avahi_dbus_chat(pcp_pmcd_t) +- ') +-') +- +-optional_policy(` +- postfix_read_config(pcp_pmcd_t) +- postfix_search_spool(pcp_pmcd_t) +-') +- +-optional_policy(` +- raid_domtrans_mdadm(pcp_pmcd_t) +- raid_access_check_mdadm(pcp_pmcd_t) +-') +- +-tunable_policy(`pcp_read_generic_logs',` +- logging_read_generic_logs(pcp_pmcd_t) +- +-') +- +-######################################## +-# +-# pcp_pmproxy local policy +-# +- +-allow pcp_pmproxy_t self:process setsched; +-allow pcp_pmproxy_t self:unix_dgram_socket create_socket_perms; +-allow pcp_pmproxy_t self:capability { ipc_lock ipc_owner sys_resource }; +-optional_policy(` +- require { +- class io_uring { sqpoll }; +- } +- #RHBZ2223568 +- allow pcp_pmproxy_t self:io_uring { sqpoll }; +-') +- +-ifdef(`kernel_io_uring_use',` +- kernel_io_uring_use(pcp_pmproxy_t) +-') +-kernel_search_network_sysctl(pcp_pmproxy_t) +- +-logging_send_syslog_msg(pcp_pmproxy_t) +- +-optional_policy(` +- dbus_system_bus_client(pcp_pmproxy_t) +- +- optional_policy(` +- avahi_dbus_chat(pcp_pmproxy_t) +- ') +-') +- +-######################################## +-# +-# pcp_pmie local policy +-# +-allow pcp_pmie_t self:capability { chown fsetid sys_admin sys_ptrace }; +-allow pcp_pmie_t self:cap_userns sys_ptrace; +-allow pcp_pmie_t self:netlink_route_socket { create_socket_perms nlmsg_read }; +-allow pcp_pmie_t self:unix_dgram_socket { create_socket_perms sendto }; +- +-allow pcp_pmie_t pcp_pmcd_t:unix_stream_socket connectto; +- +-allow pcp_pmie_t pcp_pmcd_t:process signal; +- +-kernel_read_net_sysctls(pcp_pmie_t) +-kernel_read_network_state(pcp_pmie_t) +-kernel_read_system_state(pcp_pmie_t) +-kernel_dontaudit_request_load_module(pcp_pmie_t) +- +-can_exec(pcp_pmie_t, pcp_pmie_exec_t) +- +-corecmd_exec_bin(pcp_pmie_t) +-corecmd_getattr_all_executables(pcp_pmie_t) +- +-domain_read_all_domains_state(pcp_pmie_t) +- +-fs_dontaudit_getattr_nsfs_files(pcp_pmie_t) +-fs_search_cgroup_dirs(pcp_pmie_t) +- +-init_status(pcp_pmie_t) +-optional_policy(` +- init_manage_script_tmp_files(pcp_pmie_t) +-') +- +-logging_send_syslog_msg(pcp_pmie_t) +- +-systemd_exec_systemctl(pcp_pmie_t) +-systemd_read_unit_files(pcp_pmie_t) +-systemd_search_unit_dirs(pcp_pmie_t) +-systemd_status_systemd_services(pcp_pmie_t) +- +-userdom_read_user_tmp_files(pcp_pmie_t) +- +-files_manage_generic_tmp_dirs(pcp_pmie_t) +-files_manage_generic_tmp_files(pcp_pmie_t) +- +-######################################## +-# +-# pcp_pmlogger local policy +-# +- +-allow pcp_pmlogger_t self:capability { dac_read_search dac_override chown fowner sys_admin sys_ptrace }; +-allow pcp_pmlogger_t self:process { getattr setpgid }; +-allow pcp_pmlogger_t self:netlink_route_socket {create_socket_perms nlmsg_read }; +- +-allow pcp_pmlogger_t pcp_pmcd_t:unix_stream_socket connectto; +-allow pcp_pmlogger_t self:unix_dgram_socket create_socket_perms; +- +-allow pcp_pmlogger_t pcp_pmlogger_exec_t:file execute_no_trans; +-allow pcp_pmlogger_t ldconfig_exec_t:file { execute execute_no_trans }; +- +-dontaudit pcp_pmlogger_t self:cap_userns { sys_ptrace }; +- +-kernel_read_system_state(pcp_pmlogger_t) +-kernel_read_network_state(pcp_pmlogger_t) +-kernel_read_all_sysctls(pcp_pmlogger_t) +- +-corecmd_exec_bin(pcp_pmlogger_t) +- +-corenet_tcp_bind_dey_sapi_port(pcp_pmlogger_t) +-corenet_tcp_bind_commplex_link_port(pcp_pmlogger_t) +-corenet_tcp_bind_generic_node(pcp_pmlogger_t) +- +-domain_read_all_domains_state(pcp_pmlogger_t) +- +-fs_dontaudit_getattr_nsfs_files(pcp_pmlogger_t) +-fs_mount_tracefs(pcp_pmlogger_t) +-fs_getattr_all_fs(pcp_pmlogger_t) +- +-init_read_utmp(pcp_pmlogger_t) +-init_status(pcp_pmlogger_t) +-optional_policy(` +- init_manage_script_tmp_files(pcp_pmlogger_t) +-') +- +-logging_send_syslog_msg(pcp_pmlogger_t) +- +-systemd_exec_systemctl(pcp_pmlogger_t) +-systemd_getattr_unit_files(pcp_pmlogger_t) +-systemd_status_systemd_services(pcp_pmlogger_t) +- +-userdom_manage_tmp_dirs(pcp_pmlogger_t) +-userdom_manage_tmp_files(pcp_pmlogger_t) +- +-optional_policy(` +- hostname_exec(pcp_pmlogger_t) +-') +- +-optional_policy(` +- rpm_script_signal(pcp_pmlogger_t) +-') +- +-optional_policy(` +- userdom_setattr_user_home_content_files(pcp_pmlogger_t) +-') +- +-######################################## +-# +-# pcp_plugin local policy +-# +- +-domtrans_pattern(pcp_domain, pcp_plugin_exec_t, pcp_plugin_t) +- +-optional_policy(` +- unconfined_domain(pcp_plugin_t) +-') +- +- +-######################################## +-# +-# pcp_plugin local policy (previously pcpupstream) +-# +- +-require { +- attribute domain; +- attribute file_type; +- attribute pcp_domain; +- attribute userdomain; +- +- type configfs_t; #pcp.lio +- type debugfs_t; +- type default_t; +- type device_t; +- type etc_t; +- type fixed_disk_device_t; +- type fs_t; +- type fsadm_exec_t; +- type gpmctl_t; +- type haproxy_t; +- type haproxy_var_lib_t; +- type hostname_exec_t; +- type init_t; +- type initrc_tmp_t; +- type kernel_t; +- type kmsg_device_t; +- type ldconfig_exec_t; +- type mdadm_exec_t; +- type modules_object_t; # pcp.lio, pcp.bcc +- type mount_exec_t; +- type named_exec_t; +- type ndc_exec_t; +- type ntop_port_t; +- type pcp_log_t; +- type pcp_pmcd_t; +- type pcp_pmie_exec_t; # pmda.summary +- type pcp_pmie_t; +- type pcp_pmlogger_exec_t; +- type pcp_pmlogger_t; +- type pcp_pmproxy_t; +- type pcp_tmp_t; +- type pcp_tmpfs_t; +- type pcp_var_lib_t; +- type ping_exec_t; # pmda.netcheck +- type postgresql_var_run_t; +- type proc_kcore_t; +- type proc_mdstat_t; +- type proc_net_t; #RHBZ1517656 +- type samba_var_t; # pmda.samba +- type setfiles_exec_t; +- type su_exec_t; +- type sysctl_fs_t; #RHBZ1505888 +- type sysctl_irq_t; #pmda.bcc +- type sysctl_net_t; +- type sysfs_t; #RHBZ1545245 +- type syslogd_t; +- type syslogd_var_run_t; +- type system_cronjob_t; +- type tmp_t; +- type unconfined_t; #RHBZ1443632 +- type user_home_t; +- type user_tmp_t; +- type var_run_t; +- type virt_image_t; +- type websm_port_t; # pmda.openmetrics +- +- class blk_file { ioctl open read }; +- class capability { net_raw }; # pmda.netcheck +- class capability { kill dac_override sys_admin sys_ptrace sys_pacct net_admin chown sys_chroot ipc_lock ipc_owner sys_resource fowner sys_rawio fsetid }; +- class chr_file { open read write }; +- class dbus { send_msg }; +- class dir { add_name open read search write getattr lock ioctl }; +- class fifo_file { getattr read open unlink lock ioctl write }; # qa/455 +- class file { append create execute execute_no_trans getattr setattr ioctl lock open read write unlink }; +- class filesystem { mount quotaget }; +- class lnk_file { create read getattr setattr }; +- class msgq { unix_read }; +- class process { signull signal execmem setrlimit ptrace setcap }; #RHBZ1443632, pmda.netcheck (setcap) +- class sem { unix_read associate getattr read }; +- class shm { unix_read associate getattr read }; +- class sock_file { getattr write }; #RHBZ1633211, RHBZ1449671 +- class system { module_request }; +- class tcp_socket { name_bind name_connect }; +- class udp_socket { name_bind }; +- class unix_dgram_socket { create_socket_perms getattr sendto }; +- class unix_stream_socket connectto; +-} +- +-optional_policy(` +- require { +- class bpf { map_create map_read map_write prog_load prog_run }; +- } +- #RHBZ1633211, RHBZ1693332 +- allow pcp_pmcd_t self:bpf { map_create map_read map_write prog_load prog_run }; +-') +- +-optional_policy(` +- require { +- class capability2 { bpf }; +- } +- #RHBZ1952374 +- # pmda-bcc and pmda-bpftrace need the ability to run eBPF code +- allow pcp_pmcd_t self:capability2 bpf; +-') +- +-optional_policy(` +- require { +- class capability2 { syslog }; +- } +- # pmda-bcc needs the ability to read addresses in /proc/kallsyms +- allow pcp_pmcd_t self:capability2 syslog; +-') +- +-optional_policy(` +- require { +- type cluster_exec_t; +- } +- # pmda-hacluster (crm_mon, cibadmin, corosync-quorumtool, corosync-cfgtool) +- # type=AVC msg=audit(N): avc: denied { execute } for pid=PID comm="sh" name="corosync-cfgtool" dev=DEV ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:cluster_exec_t:s0 tclass=file permissive=0 +- allow pcp_pmcd_t cluster_exec_t:file { execute execute_no_trans }; +-') +- +-optional_policy(` +- require { +- type cluster_tmpfs_t; +- } +- # pmda-hacluster (crm_mon, cibadmin, corosync-quorumtool, corosync-cfgtool) +- # type=AVC msg=audit(N): avc: denied { write } for pid=PID comm="crm_mon" name="qb-request-stonith-ng-header" dev="tmpfs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:cluster_tmpfs_t:s0 tclass=file permissive=1 +- allow pcp_pmcd_t cluster_tmpfs_t:file { write }; +-') +- +-optional_policy(` +- require { +- type drbd_exec_t; +- } +- # pmda-hacluster (drbdsetup) +- # type=AVC msg=audit(N): avc: denied { execute_no_trans } for pid=PID comm="sh" path="/usr/sbin/drbdsetup" dev="vda1" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:drbd_exec_t:s0 tclass=file permissive=1 +- allow pcp_pmcd_t drbd_exec_t:file { execute execute_no_trans }; +-') +- +-optional_policy(` +- require { +- class file { map }; +- } +- # type=AVC msg=audit(N): avc: denied { map } for pid=PID comm="pmie" path="/usr/bin/pmie" dev="dm-0" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:pcp_pmie_exec_t:s0 tclass=file permissive=0 +- # type=AVC msg=audit(N): avc: denied { map } for pid=PID comm="ldconfig" path="/usr/sbin/ldconfig" dev="dm-1" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:ldconfig_exec_t:s0 tclass=file permissive=1 +- # type=AVC msg=audit(N): avc: denied { map } for pid=PID comm="smartctl" path="/usr/sbin/smartctl" dev="dm-1" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:fsadm_exec_t:s0 tclass=file permissive=1 +- # type=AVC msg=audit(N): avc: denied { map } for pid=PID comm="pmdanvidia" path="/usr/lib64/libnvidia-ml.so" dev="dm-2" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file permissive=0 +- allow pcp_pmcd_t default_t:file { map }; +- allow pcp_pmcd_t fsadm_exec_t:file { map }; +- allow pcp_pmcd_t hostname_exec_t:file { map }; +- allow pcp_pmie_t hostname_exec_t:file { map }; +- allow pcp_pmcd_t ldconfig_exec_t:file { map }; +- allow pcp_pmcd_t pcp_pmie_exec_t:file { map }; +- allow pcp_pmcd_t pcp_tmp_t:file { map }; +- allow pcp_pmcd_t ping_exec_t:file { map }; +- allow pcp_pmcd_t syslogd_var_run_t:file { map }; +-') +- +-optional_policy(` +- require { +- class rawip_socket { create getopt setopt read write }; +- } +- # pmda.netcheck +- allow pcp_pmcd_t self:rawip_socket { create getopt setopt read write }; +-') +- +-optional_policy(` +- require { +- class netlink_generic_socket { bind create getattr setopt write read }; +- } +- # pmda-hacluster requirements for checking drbdsetup +- # type=AVC msg=audit(N): avc: denied { write } for pid=PID comm="drbdsetup" scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=netlink_generic_socket permissive=1 +- allow pcp_pmcd_t self:netlink_generic_socket { bind create getattr setopt write read }; +-') +- +-optional_policy(` +- require { +- class netlink_kobject_uevent_socket { getattr read }; +- } +- # type=AVC msg=audit(N): avc: denied { getattr } for pid=PID comm="python3" path="socket:[36479]" dev="sockfs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=netlink_kobject_uevent_socket permissive=0 +- allow pcp_pmcd_t self:netlink_kobject_uevent_socket { getattr read }; +-') +- +-optional_policy(` +- require { +- class netlink_tcpdiag_socket { append bind connect create getattr getopt ioctl lock nlmsg_read nlmsg_write read setattr setopt shutdown write }; +- } +- # pmda-sockets +- # type=AVC msg=audit(N): avc: denied { create } for pid=PID comm="ss" scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=netlink_tcpdiag_socket permissive=1 +- # type=AVC msg=audit(N): avc: denied { setopt } for pid=PID comm="ss" scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=netlink_tcpdiag_socket permissive=1 +- # type=AVC msg=audit(N): avc: denied { bind } for pid=PID comm="ss" scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=netlink_tcpdiag_socket permissive=1 +- # type=AVC msg=audit(N): avc: denied { getattr } for pid=PID comm="ss" scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=netlink_tcpdiag_socket permissive=1 +- # type=AVC msg=audit(N): avc: denied { nlmsg_read } for pid=PID comm="ss" scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=netlink_tcpdiag_socket permissive=1 +- allow pcp_pmcd_t self:netlink_tcpdiag_socket { append bind connect create getattr getopt ioctl lock nlmsg_read nlmsg_write read setattr setopt shutdown write }; +-') +- +-optional_policy(` +- require { +- type mdadm_conf_t; +- } +- allow pcp_pmcd_t mdadm_conf_t:file { getattr open read }; +-') +- +-optional_policy(` +- require { +- type container_runtime_t; +- type container_runtime_tmpfs_t; +- type container_var_run_t; +- } +- # pmda.podman +- # type=AVC msg=audit(N): avc: denied { getattr write } for pid=PID comm="pmdapodman" path="/run/podman/podman.sock" dev="tmpfs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=unconfined_u:object_r:container_var_run_t:s0 tclass=sock_file permissive=0 +- allow pcp_pmcd_t container_var_run_t:file { getattr read open }; +- allow pcp_pmcd_t container_var_run_t:sock_file { getattr write }; +- allow pcp_pmcd_t container_runtime_t:unix_stream_socket connectto; +- allow pcp_pmcd_t container_runtime_tmpfs_t:dir getattr; +-') +- +-optional_policy(` +- require { +- type docker_var_lib_t; +- } +- # pmda.docker +- allow pcp_pmcd_t docker_var_lib_t:dir search; +-') +- +-optional_policy(` +- require { +- type dma_device_t; +- } +- # type=AVC msg=audit(N): avc: denied { getattr } for pid=PID comm="pmdaproc" path="/dev/dma_heap" dev="devtmpfs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:dma_device_t:s0 tclass=dir permissive=0 +- allow pcp_pmcd_t dma_device_t:dir getattr; +-') +- +-optional_policy(` +- require { +- type kmod_exec_t; +- } +- # pmda-bcc +- # type=AVC msg=audit(N): avc: denied { execute } for pid=PID comm="sh" name="kmod" dev="dm-0" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:kmod_exec_t:s0 tclass=file permissive=0 +- # type=AVC msg=audit(N): avc: denied { execute_no_trans } for pid=PID comm="sh" path="/usr/bin/kmod" dev="dm-0" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:kmod_exec_t:s0 tclass=file permissive=0 +- allow pcp_pmcd_t kmod_exec_t:file { execute execute_no_trans }; +-') +- +-optional_policy(` +- require { +- type nsfs_t; +- } +- # pmdalinux filesys.used metric +- # type=AVC msg=audit(N): avc: denied { read } for pid=PID comm="pmdalinux" dev="nsfs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:nsfs_t:s0 tclass=file permissive=1 +- allow pcp_pmcd_t nsfs_t:file { read open getattr }; +-') +-optional_policy(` +- require { +- type numad_t; +- } +- # type=AVC msg=audit(N): avc: denied { unix_read } for pid=PID comm="pmdalinux" key=KEY scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:numad_t:s0 tclass=msgq permissive=0 +- # type=AVC msg=audit(N): avc: denied { unix_read } for pid=PID comm="pmdalinux" key=KEY scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:numad_t:s0 tclass=msgq permissive=0 +- allow pcp_pmcd_t numad_t:msgq unix_read; +-') +- +-optional_policy(` +- require { +- type proc_security_t; +- } +- # type=AVC msg=audit(N): avc: denied { read } for pid=PID comm="bpftrace" name="randomize_va_space" dev="proc" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:proc_security_t:s0 tclass=file permissive=0 +- allow pcp_pmcd_t proc_security_t:file { getattr open read }; +-') +- +-optional_policy(` +- require { +- type rpcbind_var_run_t; +- } +- # pmda.shping +- allow pcp_pmcd_t rpcbind_var_run_t:sock_file write; +-') +- +-optional_policy(` +- require { +- type sbd_exec_t; +- } +- # pmda-hacluster +- # type=AVC msg=audit(N): avc: denied { execute_no_trans } for pid=PID comm="sh" path="/usr/sbin/sbd" dev="vda1" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:sbd_exec_t:s0 tclass=file permissive=1 +- allow pcp_pmcd_t sbd_exec_t:file { execute execute_no_trans }; +-') +- +-optional_policy(` +- require { +- type tracefs_t; +- } +- # pmda.perfevent, pmda.kvm +- # type=AVC msg=audit(N): avc: denied { mount } for pid=PID comm="pmdaperfevent" name="/" dev="tracefs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:tracefs_t:s0 tclass=filesystem permissive=0 +- # type=AVC msg=audit(N): avc: denied { search } for pid=PID comm="pmdaperfevent" name="/" dev="tracefs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:tracefs_t:s0 tclass=dir permissive=0 +- # type=AVC msg=audit(N): avc: denied { read } for pid=PID comm="pmdaperfevent" name="events" dev="tracefs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:tracefs_t:s0 tclass=dir permissive=0 +- # type=AVC msg=audit(N): avc: denied { open } for pid=PID comm="pmdaperfevent" path="/sys/kernel/debug/tracing/events" dev="tracefs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:tracefs_t:s0 tclass=dir permissive=0 +- # type=AVC msg=audit(N): avc: denied { read } for pid=PID comm="pmdaperfevent" name="id" dev="tracefs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:tracefs_t:s0 tclass=file permissive=0 +- # type=AVC msg=audit(N): avc: denied { open } for pid=PID comm="pmdaperfevent" path="/sys/kernel/debug/tracing/events/gfs2/gfs2_glock_state_change/id" dev="tracefs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:tracefs_t:s0 tclass=file permissive=0 +- # type=AVC msg=audit(N): avc: denied { read } for pid=PID comm="pmdakvm" name="kvm" dev="tracefs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:tracefs_t:s0 tclass=dir permissive=0 +- allow pcp_pmcd_t tracefs_t:filesystem { mount }; +- allow pcp_pmcd_t tracefs_t:file { getattr read open append write }; +- allow pcp_pmcd_t tracefs_t:dir { search read open }; +-') +- +-optional_policy(` +- require { +- type unconfined_service_t; +- } +- #RHBZ1709237 +- # type=AVC msg=audit(N): avc: denied { signull } for pid=PID comm="pmdaX" scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:unconfined_service_t:s0 tclass=process permissive=0 +- # type=AVC msg=audit(N): avc: denied { signal } for pid=PID comm="pmsignal" scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:system_r:unconfined_service_t:s0 tclass=process permissive=0 +- # type=AVC msg=audit(N): avc: denied { signal } for pid=PID comm="pmsignal" scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:system_r:unconfined_service_t:s0 tclass=process permissive=0 +- allow pcp_pmcd_t unconfined_service_t:process signull; +- allow pcp_pmlogger_t unconfined_service_t:process signal; +- allow pcp_pmie_t unconfined_service_t:process { signal signull }; +-') +- +-optional_policy(` +- require { +- type init_tmp_t; +- } +- # type=AVC msg=audit(N): avc: denied { write } for pid=PID comm="pmie_check" path="/var/tmp/pmie_rc.FTTTXkNr6/pmie" dev="dm-0" ino=755982 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:init_tmp_t:s0 tclass=file permissive=0 +- # type=AVC msg=audit(N): avc: denied { write } for pid=PID comm="pmlogger_check" path="/var/tmp/pmlogger_rc_start.mbj4oP4Vg/pmcheck.out" dev="dm-0" ino=51322314 scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:object_r:init_tmp_t:s0 tclass=file permissive=0 +- # type=AVC msg=audit(N): avc: denied { unlink } for pid=3012 comm="rm" name="pmie_check.log" dev="dm-0" ino=59069480 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:init_tmp_t:s0 tclass=file permissive=0 +- # type=AVC msg=audit(N): avc: denied { unlink } for pid=3778 comm="rm" name="pmlogger_check.log" dev="dm-0" ino=100870703 scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:object_r:init_tmp_t:s0 tclass=file permissive=0 +- # +- +- allow pcp_pmie_t init_tmp_t:file { write unlink }; +- allow pcp_pmlogger_t init_tmp_t:file { write unlink }; +-') +- +-optional_policy(` +- require { +- type unreserved_port_t; +- } +- # type=AVC msg=audit(N): avc: denied { name_bind } for pid=PID comm="pmdasimple" src=5650 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:unreserved_port_t:s0 tclass=tcp_socket permissive=0 +- # type=AVC msg=audit(N): avc: denied { name_connect } for pid=PID comm="pmcd" dest=5650 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:unreserved_port_t:s0 tclass=tcp_socket permissive=0 +- # type=AVC msg=audit(N): avc: denied { name_bind } for pid=PID comm="pmdastatsd" src=8126 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:unreserved_port_t:s0 tclass=udp_socket permissive=0 +- # type=AVC msg=audit(N): avc: denied { name_bind } for pid=PID comm=pmlogger src=4332 scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:object_r:unreserved_port_t:s0 tclass=tcp_socket permissive=0 +- allow pcp_pmcd_t unreserved_port_t:tcp_socket { name_bind name_connect }; +- allow pcp_pmcd_t unreserved_port_t:udp_socket { name_bind }; +- allow pcp_pmlogger_t unreserved_port_t:tcp_socket { name_bind }; +-') +- +-optional_policy(` +- require { +- type virt_var_run_t; +- } +- # pmda.libvirt +- # type=AVC msg=audit(N): avc: denied { write } for pid=PID comm="python3" name="libvirt-sock-ro" dev="tmpfs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:virt_var_run_t:s0 tclass=sock_file permissive=0 +- allow pcp_pmcd_t virt_var_run_t:sock_file write; +-') +- +-optional_policy(` +- # pmda.statsd +- # type=AVC msg=audit(N): avc: denied { name_bind } for pid=46938 comm=4E65742E204C697374656E6572 src=8125 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:statsd_port_t:s0 tclass=udp_socket permissive=1 +- corenet_udp_bind_statsd_port(pcp_pmcd_t); +-') +- +-optional_policy(` +- # pmda.zimbra +- # type=AVC msg=audit(N): avc: denied { write } for pid=PID comm="java" name="hsperfdata_zimbra" dev="dm-0" ino=42488265 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=unconfined_u:object_r:user_tmp_t:s0 tclass=dir permissive=0 +- # type=AVC msg=audit(N): avc: denied { kill } for pid=PID comm="zimbraprobe" capability=5 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=capability permissive=0 +- # type=AVC msg=audit(N): avc: denied { execute } for pid=PID comm="zimbraprobe" name="su" dev="dm-0" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:su_exec_t:s0 tclass=file permissive=0 +- allow pcp_pmcd_t self:capability kill; +- allow pcp_pmcd_t user_tmp_t:dir write; +- allow pcp_pmcd_t su_exec_t:file { execute execute_no_trans }; +- userdom_manage_tmp_dirs(pcp_pmcd_t) +- userdom_manage_tmp_files(pcp_pmcd_t) +-') +- +-#============= init_t ============== +-# type=AVC msg=audit(N): avc: denied { read } for pid=PID comm="pmcd" name="pmcd" dev="dm-1" ino=INO scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:pcp_log_t:s0 tclass=dir permissive=0 +-allow init_t pcp_log_t:dir read; +- +-allow init_t pcp_log_t:file getattr; +- +-# type=AVC msg=audit(N): avc: denied { getattr } for pid=PID comm="pmcd" path="/var/lib/pcp/pmns/root" dev="dm-1" ino=INO scontext=system_u:system_r:init_t:s0 tcontext=unconfined_u:object_r:pcp_var_lib_t:s0 tclass=file permissive=0 +-allow init_t pcp_var_lib_t:dir { add_name read write }; +- +-# type=AVC msg=audit(N): avc: denied { execute } for pid=PID comm="pmcd" name="Rebuild" dev="dm-1" ino=INO scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:pcp_var_lib_t:s0 tclass=file permissive=0 +-# execute +- +-allow init_t pcp_var_lib_t:file { append create execute execute_no_trans getattr ioctl open read write }; +- +-allow init_t pcp_var_lib_t:lnk_file read; +- +-# type=AVC msg=audit(N): avc: denied { open } for pid=PID comm="pmcd" path="/var/tmp/pcp.xxx/pcp.env.path" dev="dm-1" ino=INO scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:tmp_t:s0 tclass=file permissive=0 +-# +-allow init_t tmp_t:file open; +- +-# type=USER_AVC msg=audit(N): pid=PID uid=INO auid=4294967295 ses=4294967295 subj=system_u:system_r:system_dbusd_t:s0-s0:c0.c1023 msg='avc: denied { send_msg } for msgtype=method_return dest=:1.14778 spid=1 tpid=19555 scontext=system_u:system_r:init_t:s0 tcontext=system_u:system_r:system_cronjob_t:s0-s0:c0.c1023 tclass=dbus permissive=0 exe="/usr/bin/dbus-daemon" sauid=81 hostname=? addr=? terminal=?' +-allow init_t system_cronjob_t:dbus send_msg; +- +- +-#============= pcp_pmcd_t ============== +- +-#SYN AVC for testing +-# type=AVC msg=audit(N): avc: denied { execute execute_no_trans open read } for pid=PID comm="pmdaX" name="/" dev="tracefs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:user_home_t:s0 tclass=file permissive=0 +-allow pcp_pmcd_t user_home_t:file { execute execute_no_trans open read }; +- +-# type=AVC msg=audit(N): avc: denied { getattr write } for pid=PID comm="pmdapodman" path="/run/user/N/podman/podman.sock" dev="tmpfs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=unconfined_u:object_r:user_tmp_t:s0 tclass=sock_file permissive=0 +-allow pcp_pmcd_t user_tmp_t:sock_file { getattr write }; +- +-# type=AVC msg=audit(N): avc: denied { getattr write } for pid=PID comm="pmdapodman" path="/run/podman/podman.sock" dev="tmpfs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:var_run_t:s0 tclass=sock_file permissive=0 +-allow pcp_pmcd_t var_run_t:sock_file { getattr write }; +- +-# type=AVC msg=audit(N): avc: denied { append getattr ioctl open read write } for pid=PID comm="pmdaX" name="/" dev="tracefs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:debugfs_t:s0 tclass=file permissive=0 +-allow pcp_pmcd_t debugfs_t:file { append getattr ioctl open read write }; +-allow pcp_pmcd_t debugfs_t:dir read; +- +-# type=AVC msg=audit(N): avc: denied { execute execute_no_trans open read } for pid=PID comm="pmdaX" name="/" dev="tracefs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:pcp_pmie_exec_t:s0 tclass=file permissive=0 +-allow pcp_pmcd_t pcp_pmie_exec_t:file { execute execute_no_trans open read }; +- +-# type=AVC msg=audit(N): avc: denied { getattr open read unlink } for pid=PID comm="pmdaX" name="/" dev="tracefs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:pcp_var_lib_t:s0 tclass=fifo_file permissive=0 +-allow pcp_pmcd_t pcp_var_lib_t:fifo_file { getattr open read unlink }; #RHBZ1460131 +- +-# type=AVC msg=audit(N): avc: denied { getattr } for pid=PID comm="pmdaX" name="/" dev="tracefs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:proc_kcore_t:s0 tclass=file permissive=0 +-allow pcp_pmcd_t proc_kcore_t:file getattr; +- +-# type=AVC msg=audit(N): avc: denied { sys_chroot kill sys_resource } for pid=PID comm="pmdalinux" capability=18 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=capability +-# type=AVC msg=audit(N): avc: denied { chown } for pid=PID comm="pmdasimple" capability=0 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=capability +-# type=AVC msg=audit(N): avc: denied { sys_pacct } for pid=PID comm="pmdaproc" capability=20 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=capability permissive=0 +-allow pcp_pmcd_t self:capability { kill sys_pacct chown sys_chroot ipc_owner ipc_lock sys_resource }; +- +-# type=AVC msg=audit(N): avc: denied { write } for pid=PID comm="smbstatus" name="msg.lock" dev="dm-0" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:samba_var_t:s0 tclass=dir permissive=0 +-allow pcp_pmcd_t samba_var_t:dir { add_name write }; # pmda.samba +-allow pcp_pmcd_t samba_var_t:file { create }; # pmda.samba +- +-# type=AVC msg=audit(N): avc: denied { name_connect } for pid=PID comm="python3" dest=9090 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:websm_port_t:s0 tclass=tcp_socket permissive=0 +-allow pcp_pmcd_t websm_port_t:tcp_socket name_connect; # pmda.openmetrics +- +-# type=AVC msg=audit(N): avc: denied { execute } for pid=PID comm="sh" name="8641" dev="tmpfs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:pcp_tmp_t:s0 tclass=file permissive=0 +-# type=AVC msg=audit(N): avc: denied { execute_no_trans } for pid=PID comm="sh" path="/tmp/8641" dev="tmpfs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:pcp_tmp_t:s0 tclass=file permissive=0 +-allow pcp_pmcd_t pcp_tmp_t:file { execute execute_no_trans }; +- +-# type=AVC msg=audit(N): avc: denied { getattr } for pid=PID comm="sh" path="/usr/bin/hostname" dev="dm-1" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:hostname_exec_t:s0 tclass=file permissive=0 +-# type=AVC msg=audit(N): avc: denied { execute } for pid=PID comm="sh" name="hostname" dev="dm-1" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:hostname_exec_t:s0 tclass=file permissive=0 +-# type=AVC msg=audit(N): avc: denied { read } for pid=PID comm="sh" name="hostname" dev="dm-1" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:hostname_exec_t:s0 tclass=file permissive=0 +-# type=AVC msg=audit(N): avc: denied { open } for pid=PID comm="sh" path="/usr/bin/hostname" dev="dm-1" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:hostname_exec_t:s0 tclass=file permissive=0 +-# type=AVC msg=audit(N): avc: denied { execute_no_trans } for pid=PID comm="sh" path="/usr/bin/hostname" dev="dm-1" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:hostname_exec_t:s0 tclass=file permissive=0 +-allow pcp_pmcd_t hostname_exec_t:file { getattr execute read open execute_no_trans }; +- +-# https://bugzilla.redhat.com/show_bug.cgi?id=2050094 +-# type=AVC msg=audit(N): avc: denied { execute } for pid=PID comm="python3" path=2F6D656D66643A6C6962666669202864656C6574656429 dev="tmpfs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:pcp_tmpfs_t:s0 tclass=file permissive=0 +-# libffi (used by Python/ctypes) wants to execute from memfd:libffi (a memory mapped file) +-# similar to selinux-policy PR: https://github.com/fedora-selinux/selinux-policy/pull/1019 +-can_exec(pcp_pmcd_t, pcp_tmpfs_t) +- +-# type=AVC msg=audit(N): avc: denied { getattr } for pid=PID comm="pmdaproc" path="/dev/gpmctl" dev="devtmpfs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:gpmctl_t:s0 tclass=sock_file permissive=1 +-allow pcp_pmcd_t gpmctl_t:sock_file getattr; +- +-# type=AVC msg=audit(N): avc: denied { write } for pid=PID comm="pmdaX" name="/" dev="tracefs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:haproxy_var_lib_t:s0 tclass=sock_file permissive=0 +-allow pcp_pmcd_t haproxy_var_lib_t:sock_file write; +- +-# type=AVC msg=audit(N): avc: denied { write } for pid=PID comm="pmdaxfs" name="stats_clear" dev="proc" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:sysctl_fs_t:s0 tclass=file +-#RHBZ1505888 +-allow pcp_pmcd_t sysctl_fs_t:file write; +- +-# type=AVC msg=audit(N): avc: denied { quotaget } for pid=PID comm="pmdaxfs" scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:fs_t:s0 tclass=filesystem permissive=0 +-allow pcp_pmcd_t fs_t:filesystem quotaget; +- +- +-#RHBZ1545245 +-# type=AVC msg=audit(N): avc: denied { write } for pid=PID comm="pmdaX" name="/" dev="tracefs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:sysfs_t:s0 tclass=dir permissive=0 +-allow pcp_pmcd_t sysfs_t:dir write; +- +-# pmda.bcc +-# type=AVC msg=audit(N): avc: denied { read } for pid=PID comm="pmdaX" name="/" dev="tracefs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:modules_object_t:s0 tclass=lnk_file permissive=0 +-allow pcp_pmcd_t modules_object_t:lnk_file read; +- +-# type=AVC msg=audit(N): avc: denied { execute execute_no_trans open read } for pid=PID comm="pmdaX" name="/" dev="tracefs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:mdadm_exec_t:s0 tclass=file permissive=0 +-allow pcp_pmcd_t mdadm_exec_t:file { execute execute_no_trans open read }; +- +-# type=AVC msg=audit(N): avc: denied { execute } for pid=PID comm="pmdaX" name="unbound-control" dev="vda1" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:named_exec_t:s0 tclass=file permissive=0 +-allow pcp_pmcd_t named_exec_t:file execute; +-allow pcp_pmcd_t ndc_exec_t:file { execute execute_no_trans }; +- +-# type=AVC msg=audit(N): avc: denied { getattr open read } for pid=PID comm="pmdaX" name="/" dev="tracefs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:proc_mdstat_t:s0 tclass=file permissive=0 +-allow pcp_pmcd_t proc_mdstat_t:file { getattr open read }; +- +-#pmda.bcc +-# type=AVC msg=audit(N): avc: denied { execmem setrlimit ptrace } for pid=PID comm="pmdaX" name="/" dev="tracefs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:pcp_pmcd_t:s0 tclass=process permissive=0 +-allow pcp_pmcd_t self:process { execmem setrlimit ptrace }; +- +-# type=AVC msg=audit(N): avc: denied { search } for pid=PID comm="pmdaX" name="/" dev="tracefs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:sysctl_irq_t:s0 tclass=dir permissive=0 +-allow pcp_pmcd_t sysctl_irq_t:dir { search }; +- +-# type=AVC msg=audit(N): avc: denied { signull } for pid=PID comm="pmdaX" name="/" dev="tracefs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:kernel_t:s0 tclass=process permissive=0 +-allow pcp_pmcd_t kernel_t:process signull; +- +-# pmda-bcc -- failing to compile bpf files on Fedora 33 +-# type=AVC msg=audit(N): avc: denied { fsetid } for pid=PID comm="tar" capability=4 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=capability permissive=1 +-# type=AVC msg=audit(N): avc: denied { create } for pid=PID comm="tar" name="linux-event-codes.h" scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:pcp_tmp_t:s0 tclass=lnk_file permissive=1 +-# type=AVC msg=audit(N): avc: denied { setattr } for pid=PID comm="tar" name="linux-event-codes.h" dev="tmpfs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:pcp_tmp_t:s0 tclass=lnk_file permissive=1 +-# type=AVC msg=audit(N): avc: denied { getattr } for pid=PID comm="tar" path="/tmp/kheaders-.../include/dt-bindings/input/linux-event-codes.h" dev="tmpfs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:pcp_tmp_t:s0 tclass=lnk_file permissive=1 +-allow pcp_pmcd_t pcp_tmp_t:lnk_file { create getattr setattr }; +-allow pcp_pmcd_t self:capability { fsetid }; +- +-#RHBZ1690542 +-# type=AVC msg=audit(N): avc: denied { module_request } for pid=PID comm="pmdalinux" kmod="netdev-tun0" scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:kernel_t:s0 tclass=system permissive=0 +-allow pcp_pmcd_t kernel_t:system module_request; +- +-# type=AVC msg=audit(N): avc: denied { write } for pid=PID comm="python3" name=".s.PGSQL.5432" dev="tmpfs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:postgresql_var_run_t:s0 tclass=sock_file permissive=0 +-allow pcp_pmcd_t postgresql_var_run_t:sock_file { write }; +- +-allow pcp_pmcd_t ntop_port_t:tcp_socket name_connect; +- +-allow pcp_pmcd_t pcp_log_t:fifo_file { getattr open read }; +- +-allow pcp_pmcd_t virt_image_t:dir search; +- +-allow pcp_pmcd_t syslogd_var_run_t:dir read; +- +-allow pcp_pmcd_t syslogd_var_run_t:file { getattr open read }; +- +-#============= pcp_pmlogger_t ============== +-# type=AVC msg=audit(N): avc: denied { open write } for pid=PID comm="pmdaX" name="/" dev="tracefs" ino=INO scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:object_r:kmsg_device_t:s0 tclass=chr_file permissive=0 +-allow pcp_pmlogger_t kmsg_device_t:chr_file { open write }; +- +-# type=AVC msg=audit(N): avc: denied { sys_ptrace } for pid=PID comm="ps" capability=19 scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:system_r:pcp_pmlogger_t:s0 tclass=capability +-# type=AVC msg=audit(N): avc: denied { kill } for pid=PID comm="pmdaX" name="/" dev="tracefs" ino=INO scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:object_r:pcp_pmlogger_t:s0 tclass=capability permissive=0 +-allow pcp_pmlogger_t self:capability { sys_ptrace fowner fsetid kill }; +- +-# type=AVC msg=audit(N) : avc: denied { signal } for pid=PID comm=pmsignal scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=process +-allow pcp_pmlogger_t unconfined_t:process signal; +- +-# type=AVC msg=audit(N): avc: denied { setattr unlink } for pid=PID comm="mv" name="pmlogger_check.log" dev="dm-0" ino=INO scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=unconfined_u:object_r:user_tmp_t:s0 tclass=file permissive=0 +-allow pcp_pmlogger_t user_tmp_t:file { setattr unlink }; +- +-# type=AVC msg=audit(N): avc: denied { execute } for pid=PID comm="pmlogger_daily" name="setfiles" dev="dm-0" ino=INO scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:object_r:setfiles_exec_t:s0 tclass=file permissive=0 +-allow pcp_pmlogger_t setfiles_exec_t:file execute; +- +-# type=AVC msg=audit(N): avc: denied { write } for pid=PID comm="pmlogger" name="12" dev="dm-0" ino=INO scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:object_r:initrc_tmp_t:s0 tclass=dir permissive=0 +-# type=AVC msg=audit(N): avc: denied { unlink } for pid=PID comm="rm" name="pmlogger_check.log" dev="dm-0" ino=58981759 scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:object_r:initrc_tmp_t:s0 tclass=file permissive=0 +-# type=AVC msg=audit(N): avc: denied { write } for pid=PID comm="pmlock" name="pmlogger" scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:object_r:etc_t:s0 tclass=dir permissive=0 +-# type=AVC msg=audit(N): avc: denied { execute } for pid=PID comm="pmlogctl" name="mount" scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:object_r:mount_exec_t:s0 tclass=file permissive=0 +-# type=AVC msg=audit(N): avc: denied { write } for pid=PID comm="pmlogctl" name="cgroup.procs" scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:object_r:cgroup_t:s0 tclass=file permissive=0 +-allow pcp_pmlogger_t initrc_tmp_t:dir { add_name read write }; +-allow pcp_pmlogger_t initrc_tmp_t:file { create unlink }; +-allow pcp_pmlogger_t mount_exec_t:file { execute execute_no_trans }; +-allow pcp_pmlogger_t etc_t:dir { add_name read remove_name write }; +-allow pcp_pmlogger_t etc_t:file { create unlink write }; +-allow pcp_pmlogger_t cgroup_t:file { getattr read open append write }; +- +-# type=AVC msg=audit(N) : avc: denied { getattr } for pid=PID comm=pstree scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:system_r:init_t:s0 tclass=process permissive=0 +-allow pcp_pmlogger_t init_t:process getattr; +- +-# type=AVC msg=audit(N) : avc: denied { getattr } for pid=PID comm=mount path=/dev/dm-0 dev="devtmpfs" ino=INO scontext=system_u:system_r:pcp_pmlogger_t:s0 tcontext=system_u:object_r:fixed_disk_device_t:s0 tclass=blk_file permissive=0 +-allow pcp_pmlogger_t fixed_disk_device_t:blk_file getattr; +-allow pcp_pmlogger_t sysfs_t:lnk_file read; +- +-#============= pcp_pmie_t ============== +-# type=AVC msg=audit(N): avc: denied { execute execute_no_trans getattr open read } for pid=PID comm="pmdaX" name="/" dev="tracefs" ino=INO scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:hostname_exec_t:s0 tclass=file permissive=0 +-allow pcp_pmie_t hostname_exec_t:file { execute execute_no_trans getattr open read }; +- +-# type=AVC msg=audit(N): avc: denied { sys_ptrace } for pid=PID comm="ps" capability=19 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:system_r:pcp_pmie_t:s0 tclass=capability permissive=0 +-allow pcp_pmie_t self:capability { chown fowner dac_override kill net_admin sys_ptrace fsetid }; +- +-#RHBZ1517656 +-# type=AVC msg=audit(N): avc: denied { read } for pid=PID comm="pmdaX" name="/" dev="tracefs" ino=INO scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:proc_net_t:s0 tclass=file permissive=0 +-allow pcp_pmie_t proc_net_t:file read; +- +-#RHBZ2122883 +-# type=AVC audit(N): avc: denied { read } for pid=PID comm="pmie" name="net" dev="proc" ino=INO scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:proc_net_t:s0 tclass=lnk_file permissive=0 +-allow pcp_pmie_t proc_net_t:lnk_file read; +- +-#RHBZ1743040 +-# type=AVC msg=audit(N): avc: denied { setrlimit } for pid=PID comm="systemctl" scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:system_r:pcp_pmie_t:s0 tclass=process permissive=0 +-allow pcp_pmie_t self:process setrlimit; +- +-#RHBZ1623988 +-# type=AVC msg=audit(N): avc: denied { signal } for pid=PID comm="pmsignal" scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=process permissive=1 +-allow pcp_pmie_t unconfined_t:process signal; +- +-# type=AVC msg=audit(N): avc: denied { write } for pid=PID comm="pmie" name="02" dev="dm-0" ino=INO scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:initrc_tmp_t:s0 tclass=dir permissive=0 +-# type=AVC msg=audit(N): avc: denied { unlink } for pid=PID comm="rm" name="pmie_check.log" dev="dm-0" ino=17724510 scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:initrc_tmp_t:s0 tclass=file permissive=0 +-# type=AVC msg=audit(N): avc: denied { write } for pid=PID comm="pmlock" name="pmie" scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:etc_t:s0 tclass=dir permissive=0 +-# type=AVC msg=audit(N): avc: denied { execute } for pid=PID comm="pmiectl" name="mount" scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:mount_exec_t:s0 tclass=file permissive=0 +-allow pcp_pmie_t initrc_tmp_t:dir { add_name read write }; +-allow pcp_pmie_t initrc_tmp_t:file { create unlink }; +-allow pcp_pmie_t mount_exec_t:file { execute execute_no_trans }; +-allow pcp_pmie_t etc_t:dir { add_name read remove_name write }; +-allow pcp_pmie_t etc_t:file { create unlink write }; +-allow pcp_pmie_t cgroup_t:file { getattr read open append write }; +- +-# type=AVC msg=audit(N) : avc: denied { getattr } for pid=PID comm=mount path=/dev/dm-0 dev="devtmpfs" ino=INO scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=system_u:object_r:fixed_disk_device_t:s0 tclass=blk_file permissive=0 +-allow pcp_pmie_t fixed_disk_device_t:blk_file getattr; +-allow pcp_pmie_t sysfs_t:lnk_file read; +-allow pcp_pmie_t sysfs_t:file read; +-allow pcp_pmie_t sysfs_t:dir read; +- +-# type=AVC msg=audit(N): avc: denied { search } for pid=PID comm="ps" name="homedir" dev="device" ino=INO scontext=system_u:system_r:pcp_pmie_t:s0 tcontext=unconfined_u:object_r:user_home_dir_t:s0 tclass=dir permissive=0 +-allow pcp_pmie_t user_home_t:dir { open read search }; +- +-#============= pmda-lio ============== +-# type=AVC msg=audit(N): avc: denied { open read search write } for pid=PID comm="pmdaX" name="/" dev="tracefs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:configfs_t:s0 tclass=dir permissive=0 +-allow pcp_pmcd_t configfs_t:dir { add_name open read search write }; +- +-# type=AVC msg=audit(N): avc: denied { getattr ioctl open read } for pid=PID comm="pmdaX" name="/" dev="tracefs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:configfs_t:s0 tclass=file permissive=0 +-allow pcp_pmcd_t configfs_t:file { create getattr ioctl open read write }; +- +-# type=AVC msg=audit(N): avc: denied { getattr read } for pid=PID comm="pmdaX" name="/" dev="tracefs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:configfs_t:s0 tclass=lnk_file permissive=0 +-allow pcp_pmcd_t configfs_t:lnk_file { getattr read }; +- +-# type=AVC msg=audit(N): avc: denied { module_load } for pid=PID comm="pmdaX" scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=system permissive=0 +-allow pcp_pmcd_t self:system module_load; +- +-# type=AVC msg=audit(N): avc: denied { execute execute_no_trans getattr open read } for pid=PID comm="pmdaX" name="/" dev="tracefs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:ldconfig_exec_t:s0 tclass=file permissive=0 +-allow pcp_pmcd_t ldconfig_exec_t:file { execute execute_no_trans getattr open read }; +- +-#============= pcp_pmproxy_t ============== +-# type=AVC msg=audit(N) : avc: denied { net_admin } for pid=PID comm=pmproxy capability=net_admin scontext=system_u:system_r:pcp_pmproxy_t:s0 tcontext=system_u:system_r:pcp_pmproxy_t:s0 tclass=capability +-allow pcp_pmproxy_t self:capability { net_admin dac_override }; +- +-# type=AVC msg=audit(N) : avc: denied { read } for pid=PID comm=pmproxy name=disable_ipv6 dev="proc" ino=INO scontext=system_u:system_r:pcp_pmproxy_t:s0 tcontext=system_u:object_r:sysctl_net_t:s0 tclass=file +-# type=AVC msg=audit(N) : avc: denied { open } for pid=PID comm=pmproxy path=/proc/sys/net/ipv6/conf/all/disable_ipv6 dev="proc" ino=INO scontext=system_u:system_r:pcp_pmproxy_t:s0 tcontext=system_u:object_r:sysctl_net_t:s0 tclass=file +-# type=AVC msg=audit(N) : avc: denied { getattr } for pid=PID comm=pmproxy path=/proc/sys/net/ipv6/conf/all/disable_ipv6 dev="proc" ino=INO scontext=system_u:system_r:pcp_pmproxy_t:s0 tcontext=system_u:object_r:sysctl_net_t:s0 tclass=file +-allow pcp_pmproxy_t sysctl_net_t:file { getattr open read }; +- +-# type=AVC msg=audit(N): avc: denied { read } for pid=PID comm="pmproxy" name="unix" dev="proc" ino=INO scontext=system_u:system_r:pcp_pmproxy_t:s0 tcontext=system_u:object_r:proc_net_t:s0 tclass=file +-#RHBZ1517656 +-allow pcp_pmproxy_t proc_net_t:file read; +- +-# type=AVC msg=audit(N): avc: denied { read } for pid=PID comm="pmproxy" name="pmlogger" dev="dm-92" ino=INO scontext=system_u:system_r:pcp_pmproxy_t:s0 tcontext=system_u:object_r:pcp_log_t:s0 tclass=lnk_file +-allow pcp_pmproxy_t pcp_log_t:lnk_file read; +- +-#============= pmda-smart ============== +- +-# type=AVC msg=audit(N): avc: denied { read } for pid=PID comm="sh" name="smartctl" dev="dm-1" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:fsadm_exec_t:s0 tclass=file permissive=1 +-# type=AVC msg=audit(N): avc: denied { open } for pid=PID comm="sh" path="/usr/sbin/smartctl" dev="dm-1" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:fsadm_exec_t:s0 tclass=file permissive=1 +-# type=AVC msg=audit(N): avc: denied { execute_no_trans } for pid=PID comm="sh" path="/usr/sbin/smartctl" dev="dm-1" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:fsadm_exec_t:s0 tclass=file permissive=1 +-# type=AVC msg=audit(N): avc: denied { execute } for pid=PID comm="sh" name="smartctl" dev="dm-1" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:fsadm_exec_t:s0 tclass=file permissive=1 +-# type=AVC msg=audit(N): avc: denied { getattr } for pid=PID comm="sh" path="/usr/sbin/smartctl" dev="dm-1" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:fsadm_exec_t:s0 tclass=file permissive=1 +-# type=AVC msg=audit(N): avc: denied { sys_rawio } for pid=PID comm="smartctl" capability=17 scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:system_r:pcp_pmcd_t:s0 tclass=capability permissive=1 +-# type=AVC msg=audit(N): avc: denied { read } for pid=PID comm="smartctl" name="sda" dev="devtmpfs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:fixed_disk_device_t:s0 tclass=blk_file permissive=0 +- +-allow pcp_pmcd_t fsadm_exec_t:file { execute execute_no_trans getattr open read }; +-allow pcp_pmcd_t fixed_disk_device_t:blk_file { open read ioctl }; +- +-#============= pmda-nvidia ============== +-# type=AVC msg=audit(N): avc: denied { execute } for pid=PID comm="pmdanvidia" path="/usr/lib64/libnvidia-ml.so" dev="dm-2" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file permissive=0 +-# type=AVC msg=audit(N): avc: denied { read } for pid=PID comm="pmdanvidia" name="nvidia-cap2" dev="devtmpfs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=unconfined_u:object_r:device_t:s0 tclass=chr_file permissive=0 +-#RHEL-83594 +-allow pcp_pmcd_t default_t:file { execute }; +-allow pcp_pmcd_t device_t:chr_file { create open read setattr write }; +-allow pcp_pmcd_t device_t:dir { add_name remove_name write }; +-allow pcp_pmcd_t device_t:lnk_file { create unlink }; +-allow pcp_pmcd_t self:capability mknod; +- +-# type=AVC msg=audit(N): avc: denied { sys_rawio } for pid=PID comm="pmdaX" name="/" dev="tracefs" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:pcp_pmcd_t:s0 tclass=capability permissive=0 +-allow pcp_pmcd_t self:capability sys_rawio; +- +-#============= pmda-openvswitch ============== +-optional_policy(` +- require { +- type openvswitch_exec_t; +- } +- # pmda.openvswitch +- # type=AVC msg=audit(N): avc: denied { execute } for pid=PID comm="sh" name="ovs-vsctl" dev="dm-0" ino=INO scontext=system_u:system_r:pcp_pmcd_t:s0 tcontext=system_u:object_r:openvswitch_exec_t:s0 tclass=file permissive=0 +- allow pcp_pmcd_t openvswitch_exec_t:file { execute execute_no_trans }; +-') +- +-#============= pmda-netcheck ============== +-allow pcp_pmcd_t ping_exec_t:file { execute execute_no_trans }; +-allow pcp_pmcd_t self:capability net_raw; +-allow pcp_pmcd_t self:process setcap; +- +-optional_policy(` +- require { +- class icmp_socket { create getopt setopt read write }; +- } +- # pmda.netcheck +- allow pcp_pmcd_t self:icmp_socket { create getopt setopt read write }; +-') +- +-# permit pcp_domain to read all dirs,files and fifo_file in attribute file_type +-optional_policy(` +- files_list_non_auth_dirs(pcp_domain) +-') +-optional_policy(` +- files_list_non_security(pcp_domain) +-') +-files_read_all_files(pcp_pmcd_t) +-files_read_all_files(pcp_pmie_t) +-files_read_all_files(pcp_pmlogger_t) +-files_read_all_files(pcp_pmproxy_t) +- +-allow pcp_domain file_type:fifo_file read_fifo_file_perms; +- +-# permit pcp_pmcd_t domain to read shared memory and semaphores of all domain on system +-allow pcp_domain domain:shm r_sem_perms; +-allow pcp_domain domain:sem r_shm_perms; +-allow pcp_domain userdomain:shm r_sem_perms; +-allow pcp_domain userdomain:sem r_shm_perms; +- +-# permit pcp_domain stream connect to all domains +-allow pcp_domain domain:unix_stream_socket connectto; +- +-# permit pcp_domain to connect to all ports. +-corenet_tcp_connect_all_ports(pcp_domain) +- +-# all pcp_domain read access to all maps +-optional_policy(` +- files_mmap_all_files(pcp_domain); +-') +- +-# all pcp_domain watch access to all log files +-optional_policy(` +- logging_watch_all_log_dirs_path(pcp_domain); +-') +-optional_policy(` +- logging_watch_journal_dir(pcp_domain); +-') +-allow syslogd_t pcp_log_t:fifo_file { open read write }; +- +-#============= pcp_pmcd_t ============== +-# +-##============= pcp_pmie_t ============== +-#files_manage_generic_tmp_dirs(pcp_pmie_t) +-#files_manage_generic_tmp_files(pcp_pmie_t) +-# +-##============= pcp_pmlogger_t ============== +- +-#============= pmda-denki ================= +-require { +- type pcp_pmcd_t; +- type cpu_device_t; +- class chr_file { open read }; +-} +-#============= pcp_pmcd_t ============== +-allow pcp_pmcd_t cpu_device_t:chr_file read; +-allow pcp_pmcd_t cpu_device_t:chr_file open; diff --git a/pcp.spec b/pcp.spec index 7745940..0242a1c 100644 --- a/pcp.spec +++ b/pcp.spec @@ -1,6 +1,6 @@ Name: pcp Version: 6.3.7 -Release: 10%{?dist} +Release: 11%{?dist} Summary: System-level performance monitoring and performance management License: GPL-2.0-or-later AND LGPL-2.1-or-later AND CC-BY-3.0 URL: https://pcp.io @@ -31,6 +31,30 @@ Patch17: ds389.patch # https://github.com/performancecopilot/pcp/commit/b72da5135df7fb08ca432db1e2db24478f43aea2 # https://github.com/performancecopilot/pcp/commit/edfd909edac8ad4762aa150e330f92211df98c1c Patch18: pcp-RHEL-213747.patch +# https://issues.redhat.com/browse/RHEL-213736 +# https://github.com/performancecopilot/pcp/commit/ef848fb978c8b2f0bf8c6777bb478635aba6c6dc5 +Patch19: pcp-RHEL-213736.patch +# https://issues.redhat.com/browse/RHEL-213711 +# https://github.com/performancecopilot/pcp/commit/d96ba5a716c8b2f0bf8c6777bb478635aba6c6dc5 +Patch20: pcp-RHEL-213711.patch +# https://issues.redhat.com/browse/RHEL-213687 +# https://github.com/performancecopilot/pcp/commit/7e27614006ff6fc4925991edbedaf1eab6b14731 +Patch21: pcp-RHEL-213687.patch +# https://issues.redhat.com/browse/RHEL-213658 +# https://github.com/performancecopilot/pcp/commit/c5cbeceb7d8b2f0bf8c6777bb478635aba6c6dc5 +Patch22: pcp-RHEL-213658.patch +Patch23: pcp-6.3.7-pmlogmv-command-injection.patch +Patch24: pcp-6.3.7-pmieconf-command-injection.patch +Patch25: pcp-6.3.7-OOB-pmLogLoadLabelSet.patch +Patch26: pcp-6.3.7-OOB-pmDiscoverDecodeMetaInDom.patch +Patch27: pcp-6.3.7-OOB-pmDecodeLabel.patch +Patch28: pcp-6.3.7-OOB-pmDecodeLogStatus.patch +Patch29: pcp-6.3.7-OOB-pmDecodeInstance.patch +Patch30: pcp-6.3.7-pducrash-oob-tests.patch +Patch31: pcp-6.3.7-timezone-zoneinfo-validation.patch +Patch32: pcp-6.3.7-pmdaroot-peer-credentials.patch +Patch33: pcp-6.3.7-pmproxy-rest-certreqd.patch +Patch34: pcp-6.3.7-scanmeta-LogLoadInDom-caller.patch %if 0%{?fedora} >= 40 || 0%{?rhel} >= 10 ExcludeArch: %{ix86} @@ -3641,6 +3665,15 @@ fi %files zeroconf -f pcp-zeroconf-files.rpm %changelog +* Thu Aug 13 2026 Jan Kurik - 6.3.7-11 +- Backport PCP security CVE fixes for RHEL 9.9 +- Fix integer overflow in __pmGetPDU() (CVE-2026-16529) +- Fix missing pmproxy -Q/-S authentication flags (CVE-2026-16527) +- Set FD_CLOEXEC on AF_UNIX sockets (CVE-2026-16526) +- Fix command injection in linux_sockets PMDA (CVE-2026-16524) +- Backport applicable private-pcp security hardening fixes +- CVE-2026-16531 is not applicable (pmproxy logger servlet absent in 6.3.7) + * Thu Jul 30 2026 RHEL Packaging Agent - 6.3.7-10 - Fix arbitrary pointer dereference in __pmLogLoadInDom (CVE-2026-16530)