Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP1:GA
pcp.34705
0015-src-libpcp-src-p_result.c-hardening-of-res...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0015-src-libpcp-src-p_result.c-hardening-of-result-PDU-ev.patch of Package pcp.34705
From 5a7572c6e84dc5c7f42e170b90f275e96cfba77a Mon Sep 17 00:00:00 2001 From: Nathan Scott <nathans@redhat.com> Date: Tue, 13 Aug 2024 06:54:25 +1000 Subject: [PATCH 15/19] src/libpcp/src/p_result.c: hardening of result PDU event record decoding Updates to improve access to the result (store) PDU buffer when it contains event records; adds buffer size overrun checking for each component that has variable sizes encoded within the buffer. Addresses SUSE Issue D. (cherry picked from commit 1f45c69bac2b08613fda6e5438c25cf889b3224f) [ddiss: rebase without 48ee02dc6 ("libpcp: extra diagnostics associated with PM_ERR_IPC")] Acked-by: David Disseldorp <ddiss@suse.de> --- src/libpcp/src/endian.c | 13 +++- src/libpcp/src/internal.h | 4 + src/libpcp/src/p_result.c | 153 +++++++++++++++++++++++++++++++++++--- 3 files changed, 158 insertions(+), 12 deletions(-) diff --git a/src/libpcp/src/endian.c b/src/libpcp/src/endian.c index 6dee5338a..fc6d931f9 100644 --- a/src/libpcp/src/endian.c +++ b/src/libpcp/src/endian.c @@ -275,13 +275,17 @@ ntohEventArray(pmValueBlock * const vb, int highres) } void -__ntohpmValueBlock(pmValueBlock * const vb) +__ntohpmValueBlock_hdr(pmValueBlock * const vb) { unsigned int *ip = (unsigned int *)vb; /* Swab the first word, which contain vtype and vlen */ *ip = ntohl(*ip); +} +void +__ntohpmValueBlock_buf(pmValueBlock * const vb) +{ switch (vb->vtype) { case PM_TYPE_U64: case PM_TYPE_64: @@ -305,6 +309,13 @@ __ntohpmValueBlock(pmValueBlock * const vb) break; } } + +void +__ntohpmValueBlock(pmValueBlock * const vb) +{ + __ntohpmValueBlock_hdr(vb); + __ntohpmValueBlock_buf(vb); +} #endif #ifndef __htonpmPDUInfo diff --git a/src/libpcp/src/internal.h b/src/libpcp/src/internal.h index d0a2fd3c0..1e38f4796 100644 --- a/src/libpcp/src/internal.h +++ b/src/libpcp/src/internal.h @@ -60,6 +60,8 @@ extern int __pmGetDate(struct timespec *, char const *, struct timespec const *) #define __ntohpmLabel(a) /* noop */ #define __htonpmValueBlock(a) /* noop */ #define __ntohpmValueBlock(a) /* noop */ +#define __ntohpmValueBlock_hdr(a) /* noop */ +#define __ntohpmValueBlock_buf(a) /* noop */ #define __htonf(a) /* noop */ #define __ntohf(a) /* noop */ #define __htond(a) /* noop */ @@ -90,6 +92,8 @@ extern void __htonpmLabel(pmLabel * const) _PCP_HIDDEN; extern void __ntohpmLabel(pmLabel * const) _PCP_HIDDEN; extern void __htonpmValueBlock(pmValueBlock * const) _PCP_HIDDEN; extern void __ntohpmValueBlock(pmValueBlock * const) _PCP_HIDDEN; +extern void __ntohpmValueBlock_hdr(pmValueBlock * const) _PCP_HIDDEN; +extern void __ntohpmValueBlock_buf(pmValueBlock * const) _PCP_HIDDEN; extern void __htonf(char *) _PCP_HIDDEN; /* float */ #define __ntohf(v) __htonf(v) #define __htond(v) __htonll(v) /* double */ diff --git a/src/libpcp/src/p_result.c b/src/libpcp/src/p_result.c index 071b52bba..b5a49df68 100644 --- a/src/libpcp/src/p_result.c +++ b/src/libpcp/src/p_result.c @@ -323,6 +323,124 @@ __pmSendHighResResult(int fd, int from, const __pmResult *result) return __pmSendHighResResult_ctx(NULL, fd, from, result); } +/* Check that a network encoded event array is within a given buffer size */ +int +__pmEventArrayCheck(pmValueBlock * const vb, int highres, int pmid, int value, size_t check) +{ + char *base; + int r; /* records */ + int p; /* parameters in a record ... */ + int nrecords; + int nparams; + + if (highres) { + pmHighResEventArray *hreap = (pmHighResEventArray *)vb; + base = (char *)&hreap->ea_record[0]; + if (base > (char *)vb + check) { + if (pmDebugOptions.pdu) + fprintf(stderr, "__pmEventArrayCheck: PM_ERR_IPC: pmid[%d] value[%d] highres event records past end of PDU buffer\n", + pmid, value); + return PM_ERR_IPC; + } + nrecords = ntohl(hreap->ea_nrecords); + } + else { + pmEventArray *eap = (pmEventArray *)vb; + base = (char *)&eap->ea_record[0]; + if (base > (char *)vb + check) { + if (pmDebugOptions.pdu) + fprintf(stderr, "__pmEventArrayCheck: PM_ERR_IPC: pmid[%d] value[%d] event records past end of PDU buffer\n", + pmid, value); + return PM_ERR_IPC; + } + nrecords = ntohl(eap->ea_nrecords); + } + + /* walk packed event record array */ + for (r = 0; r < nrecords; r++) { + unsigned int flags, type; + size_t size, remaining; + + remaining = check - (base - (char *)vb); + if (highres) { + pmHighResEventRecord *hrerp = (pmHighResEventRecord *)base; + size = sizeof(hrerp->er_timestamp) + sizeof(hrerp->er_flags) + + sizeof(hrerp->er_nparams); + if (size > remaining) { + if (pmDebugOptions.pdu) + fprintf(stderr, "__pmEventArrayCheck: PM_ERR_IPC: pmid[%d] value[%d] record[%d] highres event record past end of PDU buffer\n", + pmid, value, r); + return PM_ERR_IPC; + } + nparams = ntohl(hrerp->er_nparams); + flags = ntohl(hrerp->er_flags); + } + else { + pmEventRecord *erp = (pmEventRecord *)base; + size = sizeof(erp->er_timestamp) + sizeof(erp->er_flags) + + sizeof(erp->er_nparams); + if (size > remaining) { + if (pmDebugOptions.pdu) + fprintf(stderr, "__pmEventArrayCheck: PM_ERR_IPC: pmid[%d] value[%d] record[%d] event record past end of PDU buffer\n", + pmid, value, r); + return PM_ERR_IPC; + } + nparams = ntohl(erp->er_nparams); + flags = ntohl(erp->er_flags); + } + + if (flags & PM_EVENT_FLAG_MISSED) + nparams = 0; + + base += size; + remaining = check - (base - (char *)vb); + + for (p = 0; p < nparams; p++) { + __uint32_t *tp; /* points to int holding vtype/vlen */ + pmEventParameter *epp = (pmEventParameter *)base; + + if (sizeof(pmEventParameter) > remaining) { + if (pmDebugOptions.pdu) + fprintf(stderr, "__pmEventArrayCheck: PM_ERR_IPC: pmid[%d] value[%d] record[%d] param[%d] event record past end of PDU buffer\n", + pmid, value, r, p); + return PM_ERR_IPC; + } + + tp = (__uint32_t *)&epp->ep_pmid; + tp++; /* now points to ep_type/ep_len */ + *tp = ntohl(*tp); + type = epp->ep_type; + size = epp->ep_len; + *tp = htonl(*tp); /* leave the buffer how we found it */ + + if (sizeof(pmID) + size > remaining) { + if (pmDebugOptions.pdu) + fprintf(stderr, "__pmEventArrayCheck: PM_ERR_IPC: pmid[%d] value[%d] record[%d] param[%d] event record past end of PDU buffer\n", + pmid, value, r, p); + return PM_ERR_IPC; + } + + base += sizeof(pmID) + PM_PDU_SIZE_BYTES(size); + + size = 8; /* 64-bit types */ + switch (type) { + case PM_TYPE_32: + case PM_TYPE_U32: + case PM_TYPE_FLOAT: + size = 4; /* 32-bit types */ + break; + } + if (sizeof(pmID) + size > remaining) { + if (pmDebugOptions.pdu) + fprintf(stderr, "__pmEventArrayCheck: PM_ERR_IPC: pmid[%d] value[%d] record[%d] param[%d] event record past end of PDU buffer\n", + pmid, value, r, p); + return PM_ERR_IPC; + } + } + } + return 0; +} + #if defined(HAVE_64BIT_PTR) int __pmDecodeValueSet(__pmPDU *pdubuf, int pdulen, __pmPDU *data, char *pduend, @@ -336,7 +454,7 @@ __pmDecodeValueSet(__pmPDU *pdubuf, int pdulen, __pmPDU *data, char *pduend, int i, j; /* * Note: all sizes are in units of bytes ... beware that 'data' is in - * units of __pmPDU + * units of __pmPDU (four bytes) */ int vsize; /* size of vlist_t's in PDU buffer */ int nvsize; /* size of pmValue's after decode */ @@ -433,7 +551,7 @@ __pmDecodeValueSet(__pmPDU *pdubuf, int pdulen, __pmPDU *data, char *pduend, return PM_ERR_IPC; } - __ntohpmValueBlock(pduvbp); + __ntohpmValueBlock_hdr(pduvbp); if (pduvbp->vlen < PM_VAL_HDR_SIZE || pduvbp->vlen > pdulen) { if (pmDebugOptions.pdu && pmDebugOptions.desperate) @@ -442,13 +560,19 @@ __pmDecodeValueSet(__pmPDU *pdubuf, int pdulen, __pmPDU *data, char *pduend, i, j, pduvbp->vlen); return PM_ERR_IPC; } - if (pduvbp->vlen > (size_t)(pduend - (char *)pduvbp)) { + if (pduvbp->vlen > check) { if (pmDebugOptions.pdu && pmDebugOptions.desperate) - fprintf(stderr, "%s: Bad: pmid[%d] value[%d] " - "pduvp past end of PDU buffer\n", - "__pmDecodeValueSet", i, j); + fprintf(stderr, "__pmDecodeValueSet: PM_ERR_IPC: pmid[%d] value[%d] pduvp past end of PDU buffer\n", + i, j); return PM_ERR_IPC; } + if (pduvbp->vtype == PM_TYPE_HIGHRES_EVENT || + pduvbp->vtype == PM_TYPE_EVENT) { + vindex = (pduvbp->vtype == PM_TYPE_HIGHRES_EVENT); + if (__pmEventArrayCheck(pduvbp, vindex, i, j, check) < 0) + return PM_ERR_IPC; + } + __ntohpmValueBlock_buf(pduvbp); vbsize += PM_PDU_SIZE_BYTES(pduvbp->vlen); if (pmDebugOptions.pdu && pmDebugOptions.desperate) { fprintf(stderr, " len: %d type: %d", @@ -700,7 +824,8 @@ __pmDecodeValueSet(__pmPDU *pdubuf, int pdulen, __pmPDU *data, char *pduend, "__pmDecodeValueSet", i, j); return PM_ERR_IPC; } - __ntohpmValueBlock(pduvbp); + + __ntohpmValueBlock_hdr(pduvbp); if (pduvbp->vlen < PM_VAL_HDR_SIZE || pduvbp->vlen > pdulen) { if (pmDebugOptions.pdu && pmDebugOptions.desperate) @@ -709,13 +834,19 @@ __pmDecodeValueSet(__pmPDU *pdubuf, int pdulen, __pmPDU *data, char *pduend, i, j, pduvbp->vlen); return PM_ERR_IPC; } - if (pduvbp->vlen > (size_t)(pduend - (char *)pduvbp)) { + if (pduvbp->vlen > check) { if (pmDebugOptions.pdu && pmDebugOptions.desperate) - fprintf(stderr, "%s: Bad: pmid[%d] value[%d] " - "pduvp past end of PDU buffer\n", - "__pmDecodeValueSet", i, j); + fprintf(stderr, "__pmDecodeValueSet: PM_ERR_IPC: pmid[%d] value[%d] pduvp past end of PDU buffer\n", + i, j); return PM_ERR_IPC; } + if (pduvbp->vtype == PM_TYPE_HIGHRES_EVENT || + pduvbp->vtype == PM_TYPE_EVENT) { + vindex = (pduvbp->vtype == PM_TYPE_HIGHRES_EVENT); + if (__pmEventArrayCheck(pduvbp, vindex, i, j, check) < 0) + return PM_ERR_IPC; + } + __ntohpmValueBlock_buf(pduvbp); pduvp->value.pval = pduvbp; } } -- 2.43.0
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor