CVE-2015-8012: Reachable Assertion (CWE-617)
value: lldpd before 0.8.0 allows remote attackers to cause a denial of service (assertion failure and daemon crash) via a malformed packet.
CWE description: The product contains an assert() or similar statement that can be triggered by an attacker, which leads to an application exit or other behavior that is more severe than necessary.
CVSS v3 base score: 7.5
Published: 2020-01-28T19:15Z
Repository: https://github.com/vincentbernat/lldpd
Language: C
Files changed: src/daemon/lldpd.c, src/daemon/protocols/cdp.c, src/daemon/protocols/edp.c, src/daemon/protocols/lldp.c, src/daemon/protocols/sonmp.c
Commit date: 2015-10-04 02:24:29 +0200
Commit message: protocols: don't use assert on paths that can be reached

Malformed packets should not make lldpd crash. Ensure we can handle them
by not using assert() in this part.

Diff: diff --git a/src/daemon/lldpd.c b/src/daemon/lldpd.c
index 5fb3f204..be94f4f0 100644
--- a/src/daemon/lldpd.c
+++ b/src/daemon/lldpd.c
@@ -250,11 +250,10 @@ lldpd_alloc_mgmt(int family, void *addrptr, size_t addrsize, u_int32_t iface)
 	if (mgmt == NULL) {
 		errno = ENOMEM;
 		return NULL;
 	}
 	mgmt->m_family = family;
-	assert(addrsize <= LLDPD_MGMT_MAXADDRSIZE);
 	memcpy(&mgmt->m_addr, addrptr, addrsize);
 	mgmt->m_addrsize = addrsize;
 	mgmt->m_iface = iface;
 	return mgmt;
 }
diff --git a/src/daemon/protocols/cdp.c b/src/daemon/protocols/cdp.c
index 8567679f..83745c8c 100644
--- a/src/daemon/protocols/cdp.c
+++ b/src/daemon/protocols/cdp.c
@@ -23,11 +23,10 @@
 
 #include <stdio.h>
 #include <unistd.h>
 #include <errno.h>
 #include <arpa/inet.h>
-#include <assert.h>
 
 static int
 cdp_send(struct lldpd *global,
 	 struct lldpd_hardware *hardware, int version)
 {
@@ -436,12 +435,17 @@ cdp_decode(struct lldpd *cfg, char *frame, int s,
 				    (PEEK_UINT16 == sizeof(struct in_addr))) {
 						PEEK_BYTES(&addr, sizeof(struct in_addr));
 						mgmt = lldpd_alloc_mgmt(LLDPD_AF_IPV4, &addr, 
 									sizeof(struct in_addr), 0);
 						if (mgmt == NULL) {
-							assert(errno == ENOMEM);
-							log_warn("cdp", "unable to allocate memory for management address");
+							if (errno == ENOMEM)
+								log_warn("cdp",
+								    "unable to allocate memory for management address");
+							else
+								log_warn("cdp",
+								    "too large management address received on %s",
+								    hardware->h_ifname);
 							goto malformed;
 						}
 						TAILQ_INSERT_TAIL(&chassis->c_mgmt, mgmt, m_entries);
 				}
 				/* Go to the end of the address */
diff --git a/src/daemon/protocols/edp.c b/src/daemon/protocols/edp.c
index 8eec547f..818dce92 100644
--- a/src/daemon/protocols/edp.c
+++ b/src/daemon/protocols/edp.c
@@ -23,11 +23,10 @@
 #include <stdio.h>
 #include <unistd.h>
 #include <errno.h>
 #include <arpa/inet.h>
 #include <fnmatch.h>
-#include <assert.h>
 
 static int seq = 0;
 
 int
 edp_send(struct lldpd *global,
diff --git a/src/daemon/protocols/lldp.c b/src/daemon/protocols/lldp.c
index 5a5018bf..deddc3e7 100644
--- a/src/daemon/protocols/lldp.c
+++ b/src/daemon/protocols/lldp.c
@@ -18,11 +18,10 @@
 #include "lldpd.h"
 #include "frame.h"
 
 #include <unistd.h>
 #include <errno.h>
-#include <assert.h>
 #include <time.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 
@@ -159,11 +158,11 @@ static int _lldp_send(struct lldpd *global,
 	}
 
 	/* Management addresses */
 	TAILQ_FOREACH(mgmt, &chassis->c_mgmt, m_entries) {
 		proto = lldpd_af_to_lldp_proto(mgmt->m_family);
-		assert(proto != LLDP_MGMT_ADDR_NONE);
+		if (proto == LLDP_MGMT_ADDR_NONE) continue;
 		if (!(
 			  POKE_START_LLDP_TLV(LLDP_TLV_MGMT_ADDR) &&
 			  /* Size of the address, including its type */
 			  POKE_UINT8(mgmt->m_addrsize + 1) &&
 			  POKE_UINT8(proto) &&
@@ -747,13 +746,16 @@ lldp_decode(struct lldpd *cfg, char *frame, int s,
 				iface = iface_number;
 			else
 				iface = 0;
 			mgmt = lldpd_alloc_mgmt(af, addr_ptr, addr_length, iface);
 			if (mgmt == NULL) {
-				assert(errno == ENOMEM);
-				log_warn("lldp", "unable to allocate memory "
-				    "for management address");
+				if (errno == ENOMEM)
+					log_warn("lldp", "unable to allocate memory "
+					    "for management address");
+				else
+					log_warn("lldp", "too large management address "
+					    "received on %s", hardware->h_ifname);
 				goto malformed;
 			}
 			TAILQ_INSERT_TAIL(&chassis->c_mgmt, mgmt, m_entries);
 			break;
 		case LLDP_TLV_ORG:
diff --git a/src/daemon/protocols/sonmp.c b/src/daemon/protocols/sonmp.c
index 30930cb3..b55d73b7 100644
--- a/src/daemon/protocols/sonmp.c
+++ b/src/daemon/protocols/sonmp.c
@@ -22,11 +22,10 @@
 
 #include <stdio.h>
 #include <unistd.h>
 #include <errno.h>
 #include <arpa/inet.h>
-#include <assert.h>
 
 static struct sonmp_chassis sonmp_chassis_types[] = {
 	{1, "unknown (via SONMP)"},
 	{2, "Nortel 3000"},
 	{3, "Nortel 3030"},
@@ -356,12 +355,15 @@ sonmp_decode(struct lldpd *cfg, char *frame, int s,
 		    hardware->h_ifname);
 		goto malformed;
 	}
 	mgmt = lldpd_alloc_mgmt(LLDPD_AF_IPV4, &address, sizeof(struct in_addr), 0);
 	if (mgmt == NULL) {
-		assert(errno == ENOMEM);
-		log_warn("sonmp", "unable to allocate memory for management address");
+		if (errno == ENOMEM)
+			log_warn("sonmp", "unable to allocate memory for management address");
+		else
+			log_warn("sonmp", "too large management address received on %s",
+			    hardware->h_ifname);
 		goto malformed;
 	}
 	TAILQ_INSERT_TAIL(&chassis->c_mgmt, mgmt, m_entries);
 	chassis->c_ttl = cfg?(cfg->g_config.c_tx_interval * cfg->g_config.c_tx_hold):
 	    LLDPD_TTL;

Vulnerable code: 	assert(addrsize <= LLDPD_MGMT_MAXADDRSIZE);
#include <assert.h>
							assert(errno == ENOMEM);
							log_warn("cdp", "unable to allocate memory for management address");
#include <assert.h>
#include <assert.h>
		assert(proto != LLDP_MGMT_ADDR_NONE);
				assert(errno == ENOMEM);
				log_warn("lldp", "unable to allocate memory "
				    "for management address");
#include <assert.h>
		assert(errno == ENOMEM);
		log_warn("sonmp", "unable to allocate memory for management address");
Fixed code: 							if (errno == ENOMEM)
								log_warn("cdp",
								    "unable to allocate memory for management address");
							else
								log_warn("cdp",
								    "too large management address received on %s",
								    hardware->h_ifname);
		if (proto == LLDP_MGMT_ADDR_NONE) continue;
				if (errno == ENOMEM)
					log_warn("lldp", "unable to allocate memory "
					    "for management address");
				else
					log_warn("lldp", "too large management address "
					    "received on %s", hardware->h_ifname);
		if (errno == ENOMEM)
			log_warn("sonmp", "unable to allocate memory for management address");
		else
			log_warn("sonmp", "too large management address received on %s",
			    hardware->h_ifname);