[Bug 238801] usbdump -r <file> bad read

bugzilla-noreply at freebsd.org bugzilla-noreply at freebsd.org
Tue Jun 25 12:04:18 UTC 2019


https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=238801

            Bug ID: 238801
           Summary: usbdump -r <file> bad read
           Product: Base System
           Version: CURRENT
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Many People
          Priority: ---
         Component: usb
          Assignee: usb at FreeBSD.org
          Reporter: areiter at veracode.com

Created attachment 205325
  --> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=205325&action=edit
crash sample

Background: With some spare time, I randomly decided to apply AFL to `usbdump
-r <file>`. To get it going, I used a seed file of 10240 bytes from /dev/random
and additionally augmented the source to avoid the magic value check and the
major/minor checks that one sees in usbdump.c:init_rfile(struct usbcap *). With
those changes, AFL under VMWare will find this crash in seconds. From the quick
diagnosis, it seems to be a bad memory access and the following is based on
June 24 2019 usbdump.c from CURRENT copied into a 12.O-RELEASE tree and built
(so one is aware) and print_packets() looking to be the culprit:

[arr at gunther ~]$ gdb /usr/obj/usr/src/amd64.amd64/usr.sbin/usbdump/usbdump.full
GNU gdb (GDB) 8.2.1 [GDB v8.2.1 for FreeBSD]
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-portbld-freebsd12.0".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from
/usr/obj/usr/src/amd64.amd64/usr.sbin/usbdump/usbdump.full...done.
(gdb) r -r usbdump_read_sample
Starting program: /usr/obj/usr/src/amd64.amd64/usr.sbin/usbdump/usbdump.full -r
usbdump_read_sample

Program received signal SIGBUS, Bus error.
strlen (str=0x180011000000e2 <error: Cannot access memory at address
0x180011000000e2>) at /usr/src/lib/libc/string/strlen.c:101
101             va = (*lp - mask01);
(gdb) bt
#0  strlen (str=0x180011000000e2 <error: Cannot access memory at address
0x180011000000e2>) at /usr/src/lib/libc/string/strlen.c:101
#1  0x0000000800397539 in __vfprintf (fp=<optimized out>, locale=0x8004084e8
<__xlocale_global_locale>, fmt0=<optimized out>,
    ap=<optimized out>) at /usr/src/lib/libc/stdio/vfprintf.c:854
#2  0x0000000800395144 in vfprintf_l (fp=0x8004098e8, locale=0x8004084e8
<__xlocale_global_locale>,
    fmt0=0x200b12 "%.*s.%06ld usbus%d.%d
%s-%s-EP=%08x,SPD=%s,NFR=%d,SLEN=%d,IVAL=%d%s%s\n", ap=0x7fffffffe720)
    at /usr/src/lib/libc/stdio/vfprintf.c:285
#3  0x00000008003e21c4 in printf (fmt=0x1 <error: Cannot access memory at
address 0x1>) at /usr/src/lib/libc/stdio/printf.c:57
#4  0x0000000000203432 in print_apacket (ptr=<optimized out>,
ptr_len=<optimized out>, hdr=<optimized out>)
    at /usr/src/usr.sbin/usbdump/usbdump.c:495
#5  print_packets (data=0x800644000
"\f;2\331\366\067\335\233\225\377\262!\226\237\066d\001\245SSSS",
datalen=<optimized out>)
    at /usr/src/usr.sbin/usbdump/usbdump.c:631
#6  0x0000000000203104 in read_file (p=<optimized out>) at
/usr/src/usr.sbin/usbdump/usbdump.c:676
#7  0x0000000000202e1d in main (argc=3, argv=0x7fffffffeab8) at
/usr/src/usr.sbin/usbdump/usbdump.c:888
(gdb) up 5
#5  print_packets (data=0x800644000
"\f;2\331\366\067\335\233\225\377\262!\226\237\066d\001\245SSSS",
datalen=<optimized out>)
    at /usr/src/usr.sbin/usbdump/usbdump.c:631
631                             print_apacket(&temp, ptr +
(gdb)  list 605
600                     if (next <= ptr)
601                             err(EXIT_FAILURE, "Invalid length");
602             }
603     }
604
605     static void
606     print_packets(uint8_t *data, const int datalen)
607     {
608             struct header_32 temp;
609             uint8_t *ptr;
(gdb)
610             uint8_t *next;
611
612             for (ptr = data; ptr < (data + datalen); ptr = next) {
613
614                     const struct header_32 *hdr32;
615
616                     hdr32 = (const struct header_32 *)ptr;
617
618                     temp.ts_sec = le32toh(hdr32->ts_sec);
619                     temp.ts_usec = le32toh(hdr32->ts_usec);
(gdb)
620                     temp.caplen = le32toh(hdr32->caplen);
621                     temp.datalen = le32toh(hdr32->datalen);
622                     temp.hdrlen = hdr32->hdrlen;
623                     temp.align = hdr32->align;
624
625                     next = ptr + roundup2(temp.hdrlen + temp.caplen,
temp.align);
626
627                     if (next <= ptr)
628                             err(EXIT_FAILURE, "Invalid length");
629
(gdb)
630                     if (verbose >= 0 || r_arg != NULL || b_arg != NULL) {
631                             print_apacket(&temp, ptr +
632                                 temp.hdrlen, temp.caplen);
633                     }
634                     pkt_captured++;
635             }
636     }


To fix the crash input to be realistic, I set the magic value, major value to
0, and minor value (of 3, versus 2) for the struct usbcap_filehdr. I only
tested with minor value set to 3 and not 2, but it would seem, regardless, to
likely want to adjust how that parsing is done. Attached is the input sample.

I have not worked up a patch, but mostly because I did this in some spare
cycles and I do not really know this code so well to produce a solution. :( I
know that is not very helpful, but figured I should at least file the bug.

-- 
You are receiving this mail because:
You are the assignee for the bug.


More information about the freebsd-usb mailing list