Permalink
Browse files

CVE-2017-12894/In lookup_bytestring(), take the length of the byte st…

…ring into account.

Otherwise, if, in our search of the hash table, we come across a byte
string that's shorter than the string we're looking for, we'll search
past the end of the string in the hash table.

This fixes a buffer over-read discovered by Forcepoint's security
researchers Otto Airamo & Antti Levomäki.

Add a test using the capture file supplied by the reporter(s).
  • Loading branch information...
guyharris authored and infrastation committed Feb 4, 2017
1 parent 6f5ba2b commit 730fc35968c5433b9e2a829779057f4f9495dc51
Showing with 2,803 additions and 29 deletions.
  1. +43 −29 addrtoname.c
  2. +1 −0 tests/TESTLIST
  3. +2,759 −0 tests/arp-oobr.out
  4. BIN tests/arp-oobr.pcap
View
@@ -151,12 +151,24 @@ struct enamemem {
const char *e_name;
u_char *e_nsap; /* used only for nsaptable[] */
#define e_bs e_nsap /* for bytestringtable */
size_t e_namelen; /* for bytestringtable */
struct enamemem *e_nxt;
};
static struct enamemem enametable[HASHNAMESIZE];
static struct enamemem nsaptable[HASHNAMESIZE];
static struct enamemem bytestringtable[HASHNAMESIZE];
struct bsnamemem {
u_short bs_addr0;
u_short bs_addr1;
u_short bs_addr2;
const char *bs_name;
u_char *bs_bytes;
unsigned int bs_nbytes;
struct bsnamemem *bs_nxt;
};
static struct bsnamemem bytestringtable[HASHNAMESIZE];
struct protoidmem {
uint32_t p_oui;
@@ -380,11 +392,11 @@ lookup_emem(netdissect_options *ndo, const u_char *ep)
* with length 'nlen'
*/
static inline struct enamemem *
static inline struct bsnamemem *
lookup_bytestring(netdissect_options *ndo, register const u_char *bs,
const unsigned int nlen)
{
struct enamemem *tp;
struct bsnamemem *tp;
register u_int i, j, k;
if (nlen >= 6) {
@@ -399,26 +411,28 @@ lookup_bytestring(netdissect_options *ndo, register const u_char *bs,
i = j = k = 0;
tp = &bytestringtable[(i ^ j) & (HASHNAMESIZE-1)];
while (tp->e_nxt)
if (tp->e_addr0 == i &&
tp->e_addr1 == j &&
tp->e_addr2 == k &&
memcmp((const char *)bs, (const char *)(tp->e_bs), nlen) == 0)
while (tp->bs_nxt)
if (nlen == tp->bs_nbytes &&
tp->bs_addr0 == i &&
tp->bs_addr1 == j &&
tp->bs_addr2 == k &&
memcmp((const char *)bs, (const char *)(tp->bs_bytes), nlen) == 0)
return tp;
else
tp = tp->e_nxt;
tp = tp->bs_nxt;
tp->e_addr0 = i;
tp->e_addr1 = j;
tp->e_addr2 = k;
tp->bs_addr0 = i;
tp->bs_addr1 = j;
tp->bs_addr2 = k;
tp->e_bs = (u_char *) calloc(1, nlen + 1);
if (tp->e_bs == NULL)
tp->bs_bytes = (u_char *) calloc(1, nlen + 1);
if (tp->bs_bytes == NULL)
(*ndo->ndo_error)(ndo, "lookup_bytestring: calloc");
memcpy(tp->e_bs, bs, nlen);
tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp));
if (tp->e_nxt == NULL)
memcpy(tp->bs_bytes, bs, nlen);
tp->bs_nbytes = nlen;
tp->bs_nxt = (struct bsnamemem *)calloc(1, sizeof(*tp));
if (tp->bs_nxt == NULL)
(*ndo->ndo_error)(ndo, "lookup_bytestring: calloc");
return tp;
@@ -549,12 +563,12 @@ le64addr_string(netdissect_options *ndo, const u_char *ep)
const unsigned int len = 8;
register u_int i;
register char *cp;
register struct enamemem *tp;
register struct bsnamemem *tp;
char buf[BUFSIZE];
tp = lookup_bytestring(ndo, ep, len);
if (tp->e_name)
return (tp->e_name);
if (tp->bs_name)
return (tp->bs_name);
cp = buf;
for (i = len; i > 0 ; --i) {
@@ -566,11 +580,11 @@ le64addr_string(netdissect_options *ndo, const u_char *ep)
*cp = '\0';
tp->e_name = strdup(buf);
if (tp->e_name == NULL)
tp->bs_name = strdup(buf);
if (tp->bs_name == NULL)
(*ndo->ndo_error)(ndo, "le64addr_string: strdup(buf)");
return (tp->e_name);
return (tp->bs_name);
}
const char *
@@ -579,7 +593,7 @@ linkaddr_string(netdissect_options *ndo, const u_char *ep,
{
register u_int i;
register char *cp;
register struct enamemem *tp;
register struct bsnamemem *tp;
if (len == 0)
return ("<empty>");
@@ -591,11 +605,11 @@ linkaddr_string(netdissect_options *ndo, const u_char *ep,
return (q922_string(ndo, ep, len));
tp = lookup_bytestring(ndo, ep, len);
if (tp->e_name)
return (tp->e_name);
if (tp->bs_name)
return (tp->bs_name);
tp->e_name = cp = (char *)malloc(len*3);
if (tp->e_name == NULL)
tp->bs_name = cp = (char *)malloc(len*3);
if (tp->bs_name == NULL)
(*ndo->ndo_error)(ndo, "linkaddr_string: malloc");
*cp++ = hex[*ep >> 4];
*cp++ = hex[*ep++ & 0xf];
@@ -605,7 +619,7 @@ linkaddr_string(netdissect_options *ndo, const u_char *ep,
*cp++ = hex[*ep++ & 0xf];
}
*cp = '\0';
return (tp->e_name);
return (tp->bs_name);
}
const char *
View
@@ -451,6 +451,7 @@ slip-bad-direction slip-bad-direction.pcap slip-bad-direction.out -ve
# bad packets from Otto Airamo and Antti Levomäki
nbns-valgrind nbns-valgrind.pcap nbns-valgrind.out -vvv -e
arp-oobr arp-oobr.pcap arp-oobr.out -vvv -e
# RTP tests
# fuzzed pcap
Oops, something went wrong.

0 comments on commit 730fc35

Please sign in to comment.