]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
lldp: fix a buffer overflow when handling management address TLV
authorVincent Bernat <vincent@bernat.im>
Sat, 3 Oct 2015 23:50:38 +0000 (01:50 +0200)
committerVincent Bernat <vincent@bernat.im>
Sat, 3 Oct 2015 23:53:14 +0000 (01:53 +0200)
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.

src/daemon/protocols/lldp.c

index b78e3a04d17187a42c57550744dbe8960ee08320..431b22fd76dbf1fbb972e3d5ed9b50e717ad8d76 100644 (file)
@@ -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) {