segfault in relts_print at util-print.c:360 while reading malformed pcap #496

Open
geeknik opened this Issue Dec 21, 2015 · 5 comments

Projects

None yet

4 participants

@geeknik
geeknik commented Dec 21, 2015

This bug was found with American Fuzzy Lop. While reading a malformed pcap file, I was able to trigger a crash in relts_print at util-print.c:360:

355     if (secs < 0) {
356         ND_PRINT((ndo, "-"));
357         secs = -secs;
358     }
359     while (secs > 0) {
360         if (secs >= *s) {
361             ND_PRINT((ndo, "%d%s", secs / *s, *l));
362             secs -= (secs / *s) * *s;
363         }
364         s++;

This bug affects the following:
tcpdump version 4.8.0-PRE-GIT_2015_12_20
libpcap version 1.8.0-PRE-GIT_2015_12_20

It does not appear to affect tcpdump 4.6.2-5+deb8u1.

Starting program: /home/geeknik/tcpdump/tcpdump -tttt -r test00
reading from file test00, link-type EN10MB (Ethernet)

Program received signal SIGSEGV, Segmentation fault.
0x000000000063ce20 in relts_print (ndo=0x7fffffffd070, secs=-2147483648)
    at ./util-print.c:360
360         if (secs >= *s) {
(gdb) bt
#0  0x000000000063ce20 in relts_print (ndo=0x7fffffffd070, secs=-2147483648)
    at ./util-print.c:360
#1  0x000000000053d66f in lwres_print (ndo=0x7fffffffd070, bp=0xad3072 "0000", 
    length=12300) at ./print-lwres.c:543
#2  0x00000000004d539a in ip_print_demux (ipds=<optimized out>, 
    ndo=<optimized out>) at ./print-ip.c:381
#3  ip_print (ndo=0x7fffffffd070, bp=0xad304e "g00000@", length=17)
    at ./print-ip.c:646
#4  0x00000000004a3cc6 in ethertype_print (ndo=ndo@entry=0x7fffffffd070, 
    ether_type=ether_type@entry=2048, p=p@entry=0xad304e "g00000@", 
    length=length@entry=808464418, caplen=caplen@entry=114)
    at ./print-ether.c:323
#5  0x00000000004a4c3d in ether_print (ndo=0x7fffffffd070, 
    p=0xad3040 '0' <repeats 12 times>, "\b", length=808464432, 
    caplen=<optimized out>, print_encap_header=0x0, encap_header_arg=0x0)
    at ./print-ether.c:227
#6  0x000000000042892b in pretty_print_packet (ndo=0x7fffffffd070, 
    h=0x7fffffffcf20, sp=0xad3040 '0' <repeats 12 times>, "\b", 
    packets_captured=<optimized out>) at ./print.c:339
#7  0x00000000004115d9 in print_packet (user=<optimized out>, 
    h=<optimized out>, sp=<optimized out>) at ./tcpdump.c:2163
#8  0x00000000006b0d36 in pcap_offline_read (p=p@entry=0xad2db0, 
    cnt=cnt@entry=-1, callback=callback@entry=0x411570 <print_packet>, 
    user=user@entry=0x7fffffffd070 "") at ./savefile.c:490
---Type <return> to continue, or q <return> to quit--- 
#9  0x000000000065b064 in pcap_loop (p=0xad2db0, cnt=-1, 
    callback=0x411570 <print_packet>, user=0x7fffffffd070 "") at ./pcap.c:905
#10 0x000000000040b75e in main (argc=1, argv=0x7fffffffe358)
    at ./tcpdump.c:1705
$ valgrind -q ~/tcpdump/tcpdump -tttt -r test00 
reading from file test00, link-type EN10MB (Ethernet)
==93984== Invalid read of size 4
==93984==    at 0x63CE20: relts_print (util-print.c:360)
==93984==    by 0x53D66E: lwres_print (print-lwres.c:543)
==93984==    by 0x4D5399: ip_print_demux (print-ip.c:381)
==93984==    by 0x4D5399: ip_print (print-ip.c:646)
==93984==    by 0x4A3CC5: ethertype_print (print-ether.c:323)
==93984==    by 0x4A4C3C: ether_print (print-ether.c:227)
==93984==    by 0x42892A: pretty_print_packet (print.c:339)
==93984==    by 0x4115D8: print_packet (tcpdump.c:2163)
==93984==    by 0x6B0D35: pcap_offline_read (savefile.c:490)
==93984==    by 0x65B063: pcap_loop (pcap.c:905)
==93984==    by 0x40B75D: main (tcpdump.c:1705)
==93984==  Address 0x772000 is not stack'd, malloc'd or (recently) free'd
==93984== 
==93984== 
==93984== Process terminating with default action of signal 11 (SIGSEGV)
==93984==  Access not within mapped region at address 0x772000
==93984==    at 0x63CE20: relts_print (util-print.c:360)
==93984==    by 0x53D66E: lwres_print (print-lwres.c:543)
==93984==    by 0x4D5399: ip_print_demux (print-ip.c:381)
==93984==    by 0x4D5399: ip_print (print-ip.c:646)
==93984==    by 0x4A3CC5: ethertype_print (print-ether.c:323)
==93984==    by 0x4A4C3C: ether_print (print-ether.c:227)
==93984==    by 0x42892A: pretty_print_packet (print.c:339)
==93984==    by 0x4115D8: print_packet (tcpdump.c:2163)
==93984==    by 0x6B0D35: pcap_offline_read (savefile.c:490)
==93984==    by 0x65B063: pcap_loop (pcap.c:905)
==93984==    by 0x40B75D: main (tcpdump.c:1705)
==93984==  If you believe this happened as a result of a stack
==93984==  overflow in your program's main thread (unlikely but
==93984==  possible), you can try to increase the size of the
==93984==  main thread stack using the --main-stacksize= flag.
==93984==  The main thread stack size used in this run was 8388608.
1995-08-14 23:27:12.808464432 IP6, wrong link-layer encapsulation 921 > 12336:  lwres getrdatabyname[0x30f9] Type12336 Class12336 TTL -Segmentation fault

Due to the sometimes sensitive nature of the bugs I find, I won't attach the test case until the project maintainers have a chance to look this over.

@infrastation
Member

Could you send the test case to security@tcpdump.org ?

@geeknik
geeknik commented Dec 22, 2015

Sent.

@geeknik
geeknik commented Jul 23, 2016

#496 is still open.
Curious if a fix was ever merged to trunk? And since it was fixed in the
tcpdump-security branch, does it merit a CVE assignment? Thanks.

On Mon, Dec 21, 2015 at 11:01 PM, Guy Harris guy@alum.mit.edu wrote:

On Dec 21, 2015, at 6:43 PM, Brian Carpenter brian.carpenter@gmail.com
wrote:

Attached you'll find the test case for GHI #496.

This should be fixed in the tcpdump-security branch.

Michael, at what point should that be merged into the trunk?

@infrastation infrastation self-assigned this Nov 1, 2016
@Fusl
Fusl commented Jan 16, 2017

I was about to open a new issue for this but noticed that @geeknik opened one already before.

Just copy-pasting that in here in case some "more" info is needed?

1484537392536060552

The corrupted pcap file can be downloaded from here. It seems that either some versions are unaffected by this or the pcap file doesn't cause a segfault on other operating systems than Debian/Ubuntu. Here's how I tested the corrupted pcap file against tcpdump:

Affected: Debian 8.6 amd64, tcpdump and libpcap from deb repositories:
(tcpdump_4.6.2-5+deb8u1_amd64.deb/libpcap0.8_1.6.2-2_amd64.deb)

> tcpdump --version
tcpdump version 4.6.2
libpcap version 1.6.2
OpenSSL 1.0.1t  3 May 2016
> tcpdump -nn -r corrupted.pcap
reading from file corrupted.pcap, link-type EN10MB (Ethernet)
Segmentation fault
> 

Affected: Debian 8.6 amd64, tcpdump and libpcap from git repository:
(b28755b/f80a4cb)

> ../bin/tcpdump --version
bin version 4.9.0-PRE-GIT_2017_01_15
libpcap version 1.9.0-PRE-GIT_2017_01_15
> ../bin/tcpdump -nn -r corrupted.pcap
reading from file corrupted.pcap, link-type EN10MB (Ethernet)
Segmentation fault
> 

Affected: Ubuntu 16.04 amd64, tcpdump and libpcap from deb repositories:
(tcpdump_4.7.4-1ubuntu1_amd64.deb/libpcap0.8_1.7.4-2_amd64.deb)

> tcpdump --version
tcpdump version 4.7.4
libpcap version 1.7.4
OpenSSL 1.0.2g  1 Mar 2016
> tcpdump -nn -r corrupted.pcap
reading from file corrupted.pcap, link-type EN10MB (Ethernet)
Segmentation fault (core dumped)
> 

Unaffected: openSUSE Tumbleweed 20161014 amd64, tcpdump and libpcap from yum/zypper repositories:
(tcpdump-4.7.4-42.1.x86_64/libpcap1-1.7.3-61.1.x86_64)

> tcpdump --version
tcpdump version 4.7.4
libpcap version 1.7.3
OpenSSL 1.0.2j-fips  26 Sep 2016
SMI-library: 0.4.8
> tcpdump -nn -r corrupted.pcap
reading from file corrupted.pcap, link-type EN10MB (Ethernet)
06:27:12.808464432 IP 48.48.48.48.921 > 48.48.48.48.12336:  lwres getrdatabyname[0x30f9] Type12336 Class12336 TTL - 12336/12336[|lwres]
> 

Unaffected: FreeBSD 10.3-RELEASE amd64, tcpdump and libpcap shipped with OS:

> tcpdump --version
tcpdump: illegal option -- -
tcpdump version 4.4.0
libpcap version 1.4.0
Usage: tcpdump [-aAbdDefhHIJKlLnNOpqRStuUvxX] [ -B size ] [ -c count ]
                [ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]
                [ -i interface ] [ -j tstamptype ] [ -M secret ]
                [ -r file ] [ -s snaplen ] [ -T type ] [ -V file ] [ -w file ]
                [ -W filecount ] [ -y datalinktype ] [ -z command ]
                [ -Z user ] [ expression ]
> tcpdump -nn -r corrupted.pcap
reading from file corrupted.pcap, link-type EN10MB (Ethernet)
05:27:12.808464 IP 48.48.48.48.921 > 48.48.48.48.12336:  lwres getrdatabyname[0x30f9] Type12336 Class12336 TTL - 12336/12336[|lwres]
> 

GDB:

Starting program: /afl/testcases/tcpdump/bin/tcpdump -nn -r corrupted.pcap
reading from file corrupted.pcap, link-type EN10MB (Ethernet)

Program received signal SIGSEGV, Segmentation fault.
0x000000000063b98c in relts_print (ndo=0x7fffffffd880, secs=-2147483648) at ./util-print.c:362
362                     if (secs >= *s) {
(gdb) bt
#0  0x000000000063b98c in relts_print (ndo=0x7fffffffd880, secs=-2147483648) at ./util-print.c:362
#1  0x0000000000535dcf in lwres_print (ndo=0x7fffffffd880, bp=0x7ffff7fad03a "0000", length=12308) at ./print-lwres.c:545
#2  0x00000000004d0c3a in ip_print_demux (ipds=<optimized out>, ndo=<optimized out>) at ./print-ip.c:383
#3  ip_print (ndo=0x7fffffffd880, bp=0x7ffff7fad01e "E00000@", length=17) at ./print-ip.c:653
#4  0x000000000049acd6 in ethertype_print (ndo=ndo@entry=0x7fffffffd880, ether_type=ether_type@entry=2048, p=p@entry=0x7ffff7fad01e "E00000@", length=length@entry=808464418, caplen=caplen@entry=128) at ./print-ether.c:325
#5  0x000000000049bbad in ether_print (ndo=0x7fffffffd880, p=0x7ffff7fad010 '0' <repeats 12 times>, "\b", length=808464432, caplen=<optimized out>, print_encap_header=0x0, encap_header_arg=0x0) at ./print-ether.c:229
#6  0x0000000000424157 in pretty_print_packet (ndo=0x7fffffffd880, h=0x7fffffffd6e0, sp=0x7ffff7fad010 '0' <repeats 12 times>, "\b", packets_captured=<optimized out>) at ./print.c:339
#7  0x0000000000410319 in print_packet (user=<optimized out>, h=<optimized out>, sp=<optimized out>) at ./tcpdump.c:2492
#8  0x00007ffff7b9fe76 in pcap_offline_read (p=p@entry=0xa134e0, cnt=cnt@entry=-1, callback=callback@entry=0x4102c0 <print_packet>, user=user@entry=0x7fffffffd880 "") at ./savefile.c:527
#9  0x00007ffff7b46154 in pcap_loop (p=0xa134e0, cnt=cnt@entry=-1, callback=callback@entry=0x4102c0 <print_packet>, user=user@entry=0x7fffffffd880 "") at ./pcap.c:890
#10 0x0000000000409b06 in main (argc=<optimized out>, argv=<optimized out>) at ./tcpdump.c:1996

valgrind:

reading from file corrupted.pcap, link-type EN10MB (Ethernet)
==134496== Invalid read of size 4
==134496==    at 0x63B98C: relts_print (util-print.c:362)
==134496==    by 0x535DCE: lwres_print (print-lwres.c:545)
==134496==    by 0x4D0C39: ip_print_demux (print-ip.c:383)
==134496==    by 0x4D0C39: ip_print (print-ip.c:653)
==134496==    by 0x49ACD5: ethertype_print (print-ether.c:325)
==134496==    by 0x49BBAC: ether_print (print-ether.c:229)
==134496==    by 0x424156: pretty_print_packet (print.c:339)
==134496==    by 0x410318: print_packet (tcpdump.c:2492)
==134496==    by 0x4EBAE75: pcap_offline_read (savefile.c:527)
==134496==    by 0x4E61153: pcap_loop (pcap.c:890)
==134496==    by 0x409B05: main (tcpdump.c:1996)
==134496==  Address 0x6b7000 is not stack'd, malloc'd or (recently) free'd
==134496==
==134496==
==134496== Process terminating with default action of signal 11 (SIGSEGV)
==134496==  Access not within mapped region at address 0x6B7000
==134496==    at 0x63B98C: relts_print (util-print.c:362)
==134496==    by 0x535DCE: lwres_print (print-lwres.c:545)
==134496==    by 0x4D0C39: ip_print_demux (print-ip.c:383)
==134496==    by 0x4D0C39: ip_print (print-ip.c:653)
==134496==    by 0x49ACD5: ethertype_print (print-ether.c:325)
==134496==    by 0x49BBAC: ether_print (print-ether.c:229)
==134496==    by 0x424156: pretty_print_packet (print.c:339)
==134496==    by 0x410318: print_packet (tcpdump.c:2492)
==134496==    by 0x4EBAE75: pcap_offline_read (savefile.c:527)
==134496==    by 0x4E61153: pcap_loop (pcap.c:890)
==134496==    by 0x409B05: main (tcpdump.c:1996)
==134496==  If you believe this happened as a result of a stack
==134496==  overflow in your program's main thread (unlikely but
==134496==  possible), you can try to increase the size of the
==134496==  main thread stack using the --main-stacksize= flag.
==134496==  The main thread stack size used in this run was 8388608.
05:27:12.808464432 IP 48.48.48.48.921 > 48.48.48.48.12336:  lwres getrdatabyname[0x30f9] Type12336 Class12336 TTL -Segmentation fault
@infrastation
Member

Thank you for the detailed comment, I have verified that this is the same issue as reported above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment