Skip to content

Commit

Permalink
CVE-2017-12894/In lookup_bytestring(), take the length of the byte st…
Browse files Browse the repository at this point in the history
…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 Sep 13, 2017
1 parent 6f5ba2b commit 730fc35
Show file tree
Hide file tree
Showing 4 changed files with 2,803 additions and 29 deletions.
72 changes: 43 additions & 29 deletions addrtoname.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand All @@ -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;
Expand Down Expand Up @@ -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) {
Expand All @@ -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 *
Expand All @@ -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>");
Expand All @@ -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];
Expand All @@ -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 *
Expand Down
1 change: 1 addition & 0 deletions tests/TESTLIST
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading

0 comments on commit 730fc35

Please sign in to comment.