Vulnerability: Buffer overflow in the lldp_decode function in daemon/protocols/lldp.c in lldpd before 0.8.0 allows remote attackers to cause a denial of service (daemon crash) and possibly execute arbitrary code via vectors involving large management addresses and TLV boundaries.
Vulnerability ID: CVE-2015-8011
CWE: CWE-120
Severity score: 6.4
Project: https://github.com/vincentbernat/lldpd
Published: 2020-01-28
File: src/daemon/protocols/lldp.c
Commit message: lldp: fix a buffer overflow when handling management address TLV

When a remote device was advertising a too large management address
while still respecting TLV boundaries, lldpd would crash due to a buffer
overflow. However, the buffer being a static one, this buffer overflow
is not exploitable if hardening was not disabled. This bug exists since
version 0.5.6.
Commit author: Vincent Bernat

Vulnerable version (before fix):
 lldp_decode(struct lldpd *cfg, char *frame, int s, 		case LLDP_TLV_MGMT_ADDR: 			CHECK_TLV_SIZE(1, "Management address"); 			addr_str_length = PEEK_UINT8; 			CHECK_TLV_SIZE(1 + addr_str_length, "Management address"); 			PEEK_BYTES(addr_str_buffer, addr_str_length); 			addr_length = addr_str_length - 1; lldp_decode(struct lldpd *cfg, char *frame, int s, 			CHECK_TLV_SIZE(1 + addr_str_length + 5, "Management address"); 			iface_subtype = PEEK_UINT8; 			iface_number = PEEK_UINT32; 			 			af = lldpd_af_from_lldp_proto(addr_family); 			if (af == LLDPD_AF_UNSPEC) 				break; lldp_decode(struct lldpd *cfg, char *frame, int s, 			TAILQ_INSERT_TAIL(&chassis->c_mgmt, mgmt, m_entries); 			break; 		case LLDP_TLV_ORG: 			CHECK_TLV_SIZE(4, "Organisational"); 			PEEK_BYTES(orgid, sizeof(orgid)); 			tlv_subtype = PEEK_UINT8; 			if (memcmp(dot1, orgid, sizeof(orgid)) == 0) {

Fixed version (after fix):
 lldp_decode(struct lldpd *cfg, char *frame, int s, 		case LLDP_TLV_MGMT_ADDR: 			CHECK_TLV_SIZE(1, "Management address"); 			addr_str_length = PEEK_UINT8; 			if (addr_str_length > sizeof(addr_str_buffer)) { 				log_warnx("lldp", "too large management address on %s", 				    hardware->h_ifname); 				goto malformed; 			} 			CHECK_TLV_SIZE(1 + addr_str_length, "Management address"); 			PEEK_BYTES(addr_str_buffer, addr_str_length); 			addr_length = addr_str_length - 1; lldp_decode(struct lldpd *cfg, char *frame, int s, 			CHECK_TLV_SIZE(1 + addr_str_length + 5, "Management address"); 			iface_subtype = PEEK_UINT8; 			iface_number = PEEK_UINT32;  			af = lldpd_af_from_lldp_proto(addr_family); 			if (af == LLDPD_AF_UNSPEC) 				break; lldp_decode(struct lldpd *cfg, char *frame, int s, 			TAILQ_INSERT_TAIL(&chassis->c_mgmt, mgmt, m_entries); 			break; 		case LLDP_TLV_ORG: 			CHECK_TLV_SIZE(1 + (int)sizeof(orgid), "Organisational"); 			PEEK_BYTES(orgid, sizeof(orgid)); 			tlv_subtype = PEEK_UINT8; 			if (memcmp(dot1, orgid, sizeof(orgid)) == 0) {

Patch:
patch: @@ -726,6 +726,11 @@ lldp_decode(struct lldpd *cfg, char *frame, int s,
 		case LLDP_TLV_MGMT_ADDR:
 			CHECK_TLV_SIZE(1, "Management address");
 			addr_str_length = PEEK_UINT8;
+			if (addr_str_length > sizeof(addr_str_buffer)) {
+				log_warnx("lldp", "too large management address on %s",
+				    hardware->h_ifname);
+				goto malformed;
+			}
 			CHECK_TLV_SIZE(1 + addr_str_length, "Management address");
 			PEEK_BYTES(addr_str_buffer, addr_str_length);
 			addr_length = addr_str_length - 1;
@@ -734,7 +739,7 @@ lldp_decode(struct lldpd *cfg, char *frame, int s,
 			CHECK_TLV_SIZE(1 + addr_str_length + 5, "Management address");
 			iface_subtype = PEEK_UINT8;
 			iface_number = PEEK_UINT32;
-			
+
 			af = lldpd_af_from_lldp_proto(addr_family);
 			if (af == LLDPD_AF_UNSPEC)
 				break;
@@ -752,7 +757,7 @@ lldp_decode(struct lldpd *cfg, char *frame, int s,
 			TAILQ_INSERT_TAIL(&chassis->c_mgmt, mgmt, m_entries);
 			break;
 		case LLDP_TLV_ORG:
-			CHECK_TLV_SIZE(4, "Organisational");
+			CHECK_TLV_SIZE(1 + (int)sizeof(orgid), "Organisational");
 			PEEK_BYTES(orgid, sizeof(orgid));
 			tlv_subtype = PEEK_UINT8;
 			if (memcmp(dot1, orgid, sizeof(orgid)) == 0) {
path: src/daemon/protocols/lldp.c