Changeset c171463 for lib


Ignore:
Timestamp:
06/30/18 20:26:46 (2 years ago)
Author:
Richard Sanger <rsanger@…>
Branches:
cachetimestamps, develop, master, rc-4.0.4, ringdecrementfix, ringperformance
Children:
e17bad6
Parents:
7bb2fd4
git-author:
Richard Sanger <rsanger@…> (06/30/18 19:48:48)
git-committer:
Richard Sanger <rsanger@…> (06/30/18 20:26:46)
Message:

Fixes pcapng bug where pcapng_parse_next_option would read invalid memory

pcapng_parse_next_option was being accidentally called on the trailing
block size in many parts of the code. Which caused invalid memory reads
off the end of the buffer. This commit fixes this by hardening
pcapng_parse_next_option.

pcapng_parse_next_option now checks that it has not read off the end
of a block.
pcapng_parse_next_option will now return a 'endofopt' if the end
of the option list is not found without encountering a 'endofopt'
option type.

I've also added a check to ensure the block size will not overflow the
packet buffer, which it is read into.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • lib/format_pcapng.c

    r7bb2fd4 rc171463  
    173173};
    174174
     175typedef struct pcapng_peeker pcapng_hdr_t;
     176
    175177
    176178#define DATA(x) ((struct pcapng_format_data_t *)((x)->format_data))
     
    287289
    288290static char *pcapng_parse_next_option(libtrace_t *libtrace, char **pktbuf,
    289                 uint16_t *code, uint16_t *length) {
     291                uint16_t *code, uint16_t *length, pcapng_hdr_t *blockhdr) {
    290292
    291293        struct pcapng_optheader *opthdr = (struct pcapng_optheader *)*pktbuf;
    292294        int to_skip;
    293295        int padding = 0;
     296        char *eob; //end of block
    294297        char *optval;
     298        if (DATA(libtrace)->byteswapped) {
     299                eob = ((char *) blockhdr) + byteswap32(blockhdr->blocklen);
     300        } else {
     301                eob = ((char *) blockhdr) + blockhdr->blocklen;
     302        }
     303
     304        assert((char *)blockhdr < *pktbuf);
     305        // Check if we have reached the end of the block, +4 for trailing block-size
     306        // We cannot assume a endofopt, so we add one
     307        if (eob == (*pktbuf) + 4) {
     308                *code = 0;
     309                *length = 0;
     310                return *pktbuf;
     311        }
     312        // If there is not enough space for another header we've encountered an error
     313        if (eob < (*pktbuf) + 4 + sizeof(struct pcapng_optheader)) {
     314                return NULL;
     315        }
    295316
    296317        if (DATA(libtrace)->byteswapped) {
     
    311332
    312333        to_skip = (*length) + padding;
     334        // Check the value we return is within the block length
     335        if (eob < optval + to_skip + 4) {
     336                return NULL;
     337        }
    313338        *pktbuf = optval + to_skip;
    314339
     
    588613        do {
    589614                optval = pcapng_parse_next_option(libtrace, &bodyptr,
    590                                 &optcode, &optlen);
     615                                &optcode, &optlen, (pcapng_hdr_t *) packet->buffer);
    591616                if (optval == NULL) {
    592617                        trace_set_err(libtrace, TRACE_ERR_BAD_PACKET,
     
    799824        do {
    800825                optval = pcapng_parse_next_option(packet->trace, &bodyptr,
    801                                 &optcode, &optlen);
     826                                &optcode, &optlen, (pcapng_hdr_t *) packet->buffer);
    802827                if (optval == NULL) {
    803828                        trace_set_err(libtrace, TRACE_ERR_BAD_PACKET,
     
    9921017        do {
    9931018                optval = pcapng_parse_next_option(packet->trace, &bodyptr,
    994                                 &optcode, &optlen);
     1019                                &optcode, &optlen, (pcapng_hdr_t *) packet->buffer);
    9951020                if (optval == NULL) {
    9961021                        trace_set_err(libtrace, TRACE_ERR_BAD_PACKET,
     
    10551080                if (DATA(libtrace)->byteswapped) {
    10561081                        btype = byteswap32(peeker.blocktype);
     1082                        to_read = byteswap32(peeker.blocklen);
    10571083                } else {
    10581084                        btype = peeker.blocktype;
     1085                        to_read = peeker.blocklen;
     1086                }
     1087
     1088                // Check we won't read off the end of the packet buffer. Assuming corruption.
     1089                // Exclude the SECTION header, as this is used to identify the byteorder
     1090                if (to_read > LIBTRACE_PACKET_BUFSIZE && btype != PCAPNG_SECTION_TYPE) {
     1091                        trace_set_err(libtrace, TRACE_ERR_BAD_PACKET,
     1092                                      "Oversized pcapng block found, is the trace corrupted?");
     1093                        return -1;
    10591094                }
    10601095
     
    11061141                        /* Everything else -- don't care, skip it */
    11071142                        default:
    1108                                 if (DATA(libtrace)->byteswapped) {
    1109                                         to_read = byteswap32(peeker.blocklen);
    1110                                 } else {
    1111                                         to_read = peeker.blocklen;
    1112                                 }
    11131143                                err = skip_block(libtrace, to_read);
    11141144                                break;
Note: See TracChangeset for help on using the changeset viewer.