From d8d179124975fdaa481a1dd437ed65e36f2adfef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20MANELLI?= Date: Mon, 5 Jan 2026 09:18:53 +0100 Subject: [PATCH 1/3] fix: CVE-2019-5544 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit openslp has a heap overflow vulnerability that when exploited may result in memory corruption and a crash of slpd or in remote code execution. CVE-2019-5544 has been assigned to this issue. VMware would like to thank the 360Vulcan team working with the 2019 Tianfu Cup Pwn Contest for reporting this issue to us. VMware Security Response Center Signed-off-by: Andrés MANELLI --- openslp/common/slp_buffer.c | 23 ++++++++++++++ openslp/common/slp_buffer.h | 9 ++++++ openslp/slpd/slpd_process.c | 60 +++++++++++++++++++++++++++++++------ 3 files changed, 83 insertions(+), 9 deletions(-) diff --git a/openslp/common/slp_buffer.c b/openslp/common/slp_buffer.c index 1cab3f55..9abbe4fe 100644 --- a/openslp/common/slp_buffer.c +++ b/openslp/common/slp_buffer.c @@ -30,6 +30,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *-------------------------------------------------------------------------*/ +/* Copyright (c) 2019 VMware, Inc. + * SPDX-License-Identifier: BSD-3-Clause + * This file is provided under the BSD-3-Clause license. + * See COPYING file for more details and other copyrights + * that may apply. + */ + /** Functions for managing SLP message buffers. * * This file provides a higher level abstraction over malloc and free that @@ -153,4 +160,20 @@ void SLPBufferFree(SLPBuffer buf) xfree(buf); } +/** Report remaining free buffer size in bytes. + * + * Check if buffer is allocated and if so return bytes left in a + * @c SLPBuffer object. + * + * @param[in] buf The SLPBuffer to be freed. + */ +size_t +RemainingBufferSpace(SLPBuffer buf) +{ + if (buf->allocated == 0) { + return 0; + } + return buf->end - buf->curpos; +} + /*=========================================================================*/ diff --git a/openslp/common/slp_buffer.h b/openslp/common/slp_buffer.h index 314aba68..308bf155 100644 --- a/openslp/common/slp_buffer.h +++ b/openslp/common/slp_buffer.h @@ -30,6 +30,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *-------------------------------------------------------------------------*/ +/* Copyright (c) 2019 VMware, Inc. + * SPDX-License-Identifier: BSD-3-Clause + * This file is provided under the BSD-3-Clause license. + * See COPYING file for more details and other copyrights + * that may apply. + */ + /** Header file that defines SLP message buffer management routines. * * Includes structures, constants and functions that used to handle memory @@ -78,6 +85,8 @@ SLPBuffer SLPBufferListRemove(SLPBuffer * list, SLPBuffer buf); SLPBuffer SLPBufferListAdd(SLPBuffer * list, SLPBuffer buf); +size_t RemainingBufferSpace(SLPBuffer buf); + /*! @} */ #endif /* SLP_BUFFER_H_INCLUDED */ diff --git a/openslp/slpd/slpd_process.c b/openslp/slpd/slpd_process.c index 0698ab84..ae5c37dc 100644 --- a/openslp/slpd/slpd_process.c +++ b/openslp/slpd/slpd_process.c @@ -30,6 +30,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *-------------------------------------------------------------------------*/ +/* Copyright (c) 2019 VMware, Inc. + * SPDX-License-Identifier: BSD-3-Clause + * This file is provided under the BSD-3-Clause license. + * See COPYING file for more details and other copyrights + * that may apply. + */ + /** Processes incoming SLP messages. * * @file slpd_process.c @@ -523,13 +530,27 @@ static int ProcessSrvRqst(SLPMessage * message, SLPBuffer * sendbuf, { for (i = 0; i < db->urlcount; i++) { - /* urlentry is the url from the db result */ urlentry = db->urlarray[i]; + if (urlentry->opaque != NULL) { + const int64_t newsize = size + urlentry->opaquelen; + if (urlentry->opaquelen <= 0 || newsize > INT_MAX) + { + SLPDLog("Invalid opaquelen %d or sizeo of opaque url is too big, size=%d\n", + urlentry->opaquelen, size); + errorcode = SLP_ERROR_PARSE_ERROR; + goto FINISHED; + } + size += urlentry->opaquelen; + } + else + { + /* urlentry is the url from the db result */ + size += urlentry->urllen + 6; /* 1 byte for reserved */ + /* 2 bytes for lifetime */ + /* 2 bytes for urllen */ + /* 1 byte for authcount */ + } - size += urlentry->urllen + 6; /* 1 byte for reserved */ - /* 2 bytes for lifetime */ - /* 2 bytes for urllen */ - /* 1 byte for authcount */ #ifdef ENABLE_SLPv2_SECURITY /* make room to include the authblock that was asked for */ if (G_SlpdProperty.securityEnabled @@ -603,7 +624,7 @@ static int ProcessSrvRqst(SLPMessage * message, SLPBuffer * sendbuf, urlentry = db->urlarray[i]; #ifdef ENABLE_SLPv1 - if (urlentry->opaque == 0) + if (urlentry->opaque == NULL) { /* url-entry reserved */ *result->curpos++ = 0; @@ -615,8 +636,18 @@ static int ProcessSrvRqst(SLPMessage * message, SLPBuffer * sendbuf, PutUINT16(&result->curpos, urlentry->urllen); /* url-entry url */ - memcpy(result->curpos, urlentry->url, urlentry->urllen); - result->curpos += urlentry->urllen; + if (RemainingBufferSpace(result) >= urlentry->urllen) + { + memcpy(result->curpos, urlentry->url, urlentry->urllen); + result->curpos = result->curpos + urlentry->urllen; + } + else + { + SLPDLog("Url too big (ask: %d have %" PRId64 "), failing request\n", + urlentry->opaquelen, (int64_t) RemainingBufferSpace(result)); + errorcode = SLP_ERROR_PARSE_ERROR; + goto FINISHED; + } /* url-entry auths */ *result->curpos++ = 0; @@ -628,7 +659,18 @@ static int ProcessSrvRqst(SLPMessage * message, SLPBuffer * sendbuf, /* TRICKY: Fix up the lifetime. */ TO_UINT16(urlentry->opaque + 1, urlentry->lifetime); - memcpy(result->curpos, urlentry->opaque, urlentry->opaquelen); + + if (RemainingBufferSpace(result) >= urlentry->opaquelen) + { + memcpy(result->curpos, urlentry->opaque, urlentry->opaquelen); + } + else + { + SLPDLog("Opaque Url too big (ask: %d have %" PRId64 "), failing request\n", + urlentry->opaquelen, (int64_t) RemainingBufferSpace(result)); + errorcode = SLP_ERROR_PARSE_ERROR; + goto FINISHED; + } /* TRICKY: Fix up the result authblock count. */ if (urlentry->authcount) From c50ecee7244b3c38cc9e726c100f479210259b61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20MANELLI?= Date: Mon, 5 Jan 2026 10:30:11 +0100 Subject: [PATCH 2/3] chore: update with pr comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andrés MANELLI --- openslp/common/slp_buffer.c | 2 +- openslp/slpd/slpd_process.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/openslp/common/slp_buffer.c b/openslp/common/slp_buffer.c index 9abbe4fe..2d4b1e0c 100644 --- a/openslp/common/slp_buffer.c +++ b/openslp/common/slp_buffer.c @@ -165,7 +165,7 @@ void SLPBufferFree(SLPBuffer buf) * Check if buffer is allocated and if so return bytes left in a * @c SLPBuffer object. * - * @param[in] buf The SLPBuffer to be freed. + * @param[in] buf The SLPBuffer to get the free space size from. */ size_t RemainingBufferSpace(SLPBuffer buf) diff --git a/openslp/slpd/slpd_process.c b/openslp/slpd/slpd_process.c index ae5c37dc..fa8ac829 100644 --- a/openslp/slpd/slpd_process.c +++ b/openslp/slpd/slpd_process.c @@ -535,7 +535,7 @@ static int ProcessSrvRqst(SLPMessage * message, SLPBuffer * sendbuf, const int64_t newsize = size + urlentry->opaquelen; if (urlentry->opaquelen <= 0 || newsize > INT_MAX) { - SLPDLog("Invalid opaquelen %d or sizeo of opaque url is too big, size=%d\n", + SLPDLog("Invalid opaquelen %zu or size of opaque url is too big, size=%zu\n", urlentry->opaquelen, size); errorcode = SLP_ERROR_PARSE_ERROR; goto FINISHED; @@ -643,8 +643,8 @@ static int ProcessSrvRqst(SLPMessage * message, SLPBuffer * sendbuf, } else { - SLPDLog("Url too big (ask: %d have %" PRId64 "), failing request\n", - urlentry->opaquelen, (int64_t) RemainingBufferSpace(result)); + SLPDLog("Url too big (ask: %zu have %zu), failing request\n", + urlentry->opaquelen, RemainingBufferSpace(result)); errorcode = SLP_ERROR_PARSE_ERROR; goto FINISHED; } @@ -666,8 +666,8 @@ static int ProcessSrvRqst(SLPMessage * message, SLPBuffer * sendbuf, } else { - SLPDLog("Opaque Url too big (ask: %d have %" PRId64 "), failing request\n", - urlentry->opaquelen, (int64_t) RemainingBufferSpace(result)); + SLPDLog("Opaque Url too big (ask: %zu have %zu), failing request\n", + urlentry->opaquelen, RemainingBufferSpace(result)); errorcode = SLP_ERROR_PARSE_ERROR; goto FINISHED; } From 0bcac71543735e6619b2f525d44e88ce8ade15ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20MANELLI?= Date: Mon, 5 Jan 2026 13:10:03 +0100 Subject: [PATCH 3/3] fix newsize comparison MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Andrés MANELLI --- openslp/slpd/slpd_process.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openslp/slpd/slpd_process.c b/openslp/slpd/slpd_process.c index fa8ac829..3c6b4693 100644 --- a/openslp/slpd/slpd_process.c +++ b/openslp/slpd/slpd_process.c @@ -532,8 +532,7 @@ static int ProcessSrvRqst(SLPMessage * message, SLPBuffer * sendbuf, { urlentry = db->urlarray[i]; if (urlentry->opaque != NULL) { - const int64_t newsize = size + urlentry->opaquelen; - if (urlentry->opaquelen <= 0 || newsize > INT_MAX) + if (urlentry->opaquelen == 0 || (size > SIZE_MAX - urlentry->opaquelen)) { SLPDLog("Invalid opaquelen %zu or size of opaque url is too big, size=%zu\n", urlentry->opaquelen, size);