Skip to content

Commit 730fc35

Browse files
guyharrisinfrastation
authored andcommitted
CVE-2017-12894/In lookup_bytestring(), take the length of the byte string 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).
1 parent 6f5ba2b commit 730fc35

File tree

4 files changed

+2803
-29
lines changed

4 files changed

+2803
-29
lines changed

Diff for: addrtoname.c

+43-29
Original file line numberDiff line numberDiff line change
@@ -151,12 +151,24 @@ struct enamemem {
151151
const char *e_name;
152152
u_char *e_nsap; /* used only for nsaptable[] */
153153
#define e_bs e_nsap /* for bytestringtable */
154+
size_t e_namelen; /* for bytestringtable */
154155
struct enamemem *e_nxt;
155156
};
156157

157158
static struct enamemem enametable[HASHNAMESIZE];
158159
static struct enamemem nsaptable[HASHNAMESIZE];
159-
static struct enamemem bytestringtable[HASHNAMESIZE];
160+
161+
struct bsnamemem {
162+
u_short bs_addr0;
163+
u_short bs_addr1;
164+
u_short bs_addr2;
165+
const char *bs_name;
166+
u_char *bs_bytes;
167+
unsigned int bs_nbytes;
168+
struct bsnamemem *bs_nxt;
169+
};
170+
171+
static struct bsnamemem bytestringtable[HASHNAMESIZE];
160172

161173
struct protoidmem {
162174
uint32_t p_oui;
@@ -380,11 +392,11 @@ lookup_emem(netdissect_options *ndo, const u_char *ep)
380392
* with length 'nlen'
381393
*/
382394

383-
static inline struct enamemem *
395+
static inline struct bsnamemem *
384396
lookup_bytestring(netdissect_options *ndo, register const u_char *bs,
385397
const unsigned int nlen)
386398
{
387-
struct enamemem *tp;
399+
struct bsnamemem *tp;
388400
register u_int i, j, k;
389401

390402
if (nlen >= 6) {
@@ -399,26 +411,28 @@ lookup_bytestring(netdissect_options *ndo, register const u_char *bs,
399411
i = j = k = 0;
400412

401413
tp = &bytestringtable[(i ^ j) & (HASHNAMESIZE-1)];
402-
while (tp->e_nxt)
403-
if (tp->e_addr0 == i &&
404-
tp->e_addr1 == j &&
405-
tp->e_addr2 == k &&
406-
memcmp((const char *)bs, (const char *)(tp->e_bs), nlen) == 0)
414+
while (tp->bs_nxt)
415+
if (nlen == tp->bs_nbytes &&
416+
tp->bs_addr0 == i &&
417+
tp->bs_addr1 == j &&
418+
tp->bs_addr2 == k &&
419+
memcmp((const char *)bs, (const char *)(tp->bs_bytes), nlen) == 0)
407420
return tp;
408421
else
409-
tp = tp->e_nxt;
422+
tp = tp->bs_nxt;
410423

411-
tp->e_addr0 = i;
412-
tp->e_addr1 = j;
413-
tp->e_addr2 = k;
424+
tp->bs_addr0 = i;
425+
tp->bs_addr1 = j;
426+
tp->bs_addr2 = k;
414427

415-
tp->e_bs = (u_char *) calloc(1, nlen + 1);
416-
if (tp->e_bs == NULL)
428+
tp->bs_bytes = (u_char *) calloc(1, nlen + 1);
429+
if (tp->bs_bytes == NULL)
417430
(*ndo->ndo_error)(ndo, "lookup_bytestring: calloc");
418431

419-
memcpy(tp->e_bs, bs, nlen);
420-
tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp));
421-
if (tp->e_nxt == NULL)
432+
memcpy(tp->bs_bytes, bs, nlen);
433+
tp->bs_nbytes = nlen;
434+
tp->bs_nxt = (struct bsnamemem *)calloc(1, sizeof(*tp));
435+
if (tp->bs_nxt == NULL)
422436
(*ndo->ndo_error)(ndo, "lookup_bytestring: calloc");
423437

424438
return tp;
@@ -549,12 +563,12 @@ le64addr_string(netdissect_options *ndo, const u_char *ep)
549563
const unsigned int len = 8;
550564
register u_int i;
551565
register char *cp;
552-
register struct enamemem *tp;
566+
register struct bsnamemem *tp;
553567
char buf[BUFSIZE];
554568

555569
tp = lookup_bytestring(ndo, ep, len);
556-
if (tp->e_name)
557-
return (tp->e_name);
570+
if (tp->bs_name)
571+
return (tp->bs_name);
558572

559573
cp = buf;
560574
for (i = len; i > 0 ; --i) {
@@ -566,11 +580,11 @@ le64addr_string(netdissect_options *ndo, const u_char *ep)
566580

567581
*cp = '\0';
568582

569-
tp->e_name = strdup(buf);
570-
if (tp->e_name == NULL)
583+
tp->bs_name = strdup(buf);
584+
if (tp->bs_name == NULL)
571585
(*ndo->ndo_error)(ndo, "le64addr_string: strdup(buf)");
572586

573-
return (tp->e_name);
587+
return (tp->bs_name);
574588
}
575589

576590
const char *
@@ -579,7 +593,7 @@ linkaddr_string(netdissect_options *ndo, const u_char *ep,
579593
{
580594
register u_int i;
581595
register char *cp;
582-
register struct enamemem *tp;
596+
register struct bsnamemem *tp;
583597

584598
if (len == 0)
585599
return ("<empty>");
@@ -591,11 +605,11 @@ linkaddr_string(netdissect_options *ndo, const u_char *ep,
591605
return (q922_string(ndo, ep, len));
592606

593607
tp = lookup_bytestring(ndo, ep, len);
594-
if (tp->e_name)
595-
return (tp->e_name);
608+
if (tp->bs_name)
609+
return (tp->bs_name);
596610

597-
tp->e_name = cp = (char *)malloc(len*3);
598-
if (tp->e_name == NULL)
611+
tp->bs_name = cp = (char *)malloc(len*3);
612+
if (tp->bs_name == NULL)
599613
(*ndo->ndo_error)(ndo, "linkaddr_string: malloc");
600614
*cp++ = hex[*ep >> 4];
601615
*cp++ = hex[*ep++ & 0xf];
@@ -605,7 +619,7 @@ linkaddr_string(netdissect_options *ndo, const u_char *ep,
605619
*cp++ = hex[*ep++ & 0xf];
606620
}
607621
*cp = '\0';
608-
return (tp->e_name);
622+
return (tp->bs_name);
609623
}
610624

611625
const char *

Diff for: tests/TESTLIST

+1
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,7 @@ slip-bad-direction slip-bad-direction.pcap slip-bad-direction.out -ve
451451

452452
# bad packets from Otto Airamo and Antti Levomäki
453453
nbns-valgrind nbns-valgrind.pcap nbns-valgrind.out -vvv -e
454+
arp-oobr arp-oobr.pcap arp-oobr.out -vvv -e
454455

455456
# RTP tests
456457
# fuzzed pcap

0 commit comments

Comments
 (0)