SIGILL triggerred by usbredirparser_serialize with nullptr in usbredirparser.c:1766
I have found SIGILL crashes with usbredir-0.13.0 when running some fuzzing tests.
Repordocing Steps:
-
Trigger the SIGILL crashes with PoC attached.
./usbredirparserfuzz < out2/default/crashes/id\:000033\,sig\:04\,src\:000083\,time\:5394\,execs\:37324\,op\:havoc\,rep\:3
[AFL++ 0cc14d0bc3c5] /data/openeuler/usbredir/fuzzing # date Mon Dec 18 02:50:16 AM UTC 2023 [AFL++ 0cc14d0bc3c5] /data/openeuler/usbredir/fuzzing # ./usbredirparserfuzz < out2/default/crashes/id:000033,sig:04,src:000083,time:5394,execs:37324,op:havoc,rep:3 Illegal instruction
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./usbredirparserfuzz...
(gdb) run < out2/default/crashes/id\:000033\,sig\:04\,src\:000083\,time\:5394\,execs\:37324\,op\:havoc\,rep\:3
Starting program: /data/openeuler/usbredir/fuzzing/usbredirparserfuzz < out2/default/crashes/id\:000033\,sig\:04\,src\:000083\,time\:5394\,execs\:37324\,op\:havoc\,rep\:3
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Program received signal SIGILL, Illegal instruction.
0x000055555568cd92 in serialize_data (parser=<optimized out>, state=<optimized out>, pos=0x7fffffffdc00, remain=0x7fffffffdc20, data=0x0, len=<optimized out>, desc=0x55555558cd00 <str.20> "packet-data") at ../usbredirparser/usbredirparser.c:1661
1661 memcpy(*pos, data, len);
(gdb) p data
$1 = (uint8_t *) 0x0
(gdb) p len
$2 = <optimized out>
(gdb) bt
#0 0x000055555568cd92 in serialize_data (parser=<optimized out>, state=<optimized out>, pos=0x7fffffffdc00, remain=0x7fffffffdc20,
data=0x0, len=<optimized out>, desc=0x55555558cd00 <str.20> "packet-data") at ../usbredirparser/usbredirparser.c:1661
#1 0x000055555568b237 in usbredirparser_serialize (parser_pub=<optimized out>, state_dest=<optimized out>, state_len=<optimized out>)
at ../usbredirparser/usbredirparser.c:1766
#2 0x000055555567735b in (anonymous namespace)::try_serialize (parser=0x631000014824) at usbredirparserfuzz.cc:330
#3 LLVMFuzzerTestOneInput (data=<optimized out>, size=<optimized out>) at usbredirparserfuzz.cc:424
#4 0x000055555567e8d3 in main (argc=<optimized out>, argv=<optimized out>) at usbredirparserfuzz.cc:458
(gdb)
A more details debug info:
(gdb)bu usbredirparser.c:1661
Breakpoint 1 at 0x55555568c9ac: file ../usbredirparser/usbredirparser.c, line 1661.
(gdb) b usbredirparser.c:1766
Breakpoint 2 at 0x55555568b21a: file ../usbredirparser/usbredirparser.c, line 1766.
(gdb) usbredirparserfuzz.cc:330
Undefined command: "usbredirparserfuzz.cc". Try "help".
(gdb) b usbredirparserfuzz.cc:330
Breakpoint 3 at 0x55555567705f: usbredirparserfuzz.cc:330. (2 locations)
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /data/openeuler/usbredir/fuzzing/usbredirparserfuzz < out2/default/crashes/id\:000033\,sig\:04\,src\:000083\,time\:5394\,execs\:37324\,op\:havoc\,rep\:3
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Breakpoint 3, (anonymous namespace)::try_serialize (parser=0x617000000080) at usbredirparserfuzz.cc:330
330 ret = usbredirparser_serialize(parser, &state, &len);
(gdb) p state
$1 = (uint8_t *) 0x0
(gdb) p len
$2 = 0
(gdb) c
Continuing.
Breakpoint 2, usbredirparser_serialize (parser_pub=<optimized out>, state_dest=<optimized out>, state_len=<optimized out>) at ../usbredirparser/usbredirparser.c:1766
1766 if (serialize_data(parser, &state, &pos, &remain,
(gdb) p state
$3 = (uint8_t *) 0x631000014800 "1PRU"
(gdb) p len
$4 = <optimized out>
(gdb) c
Continuing.
Program received signal SIGILL, Illegal instruction.
0x000055555568cd92 in serialize_data (parser=<optimized out>, state=<optimized out>, pos=0x7fffffffdc00, remain=0x7fffffffdc20, data=0x0, len=<optimized out>, desc=0x55555558cd00 <str.20> "packet-data") at ../usbredirparser/usbredirparser.c:1661
1661 memcpy(*pos, data, len);
(gdb) p data
$5 = (uint8_t *) 0x0
(gdb) p len
$6 = <optimized out>
(gdb) p pos
$7 = (uint8_t **) 0x7fffffffdc00
The fuzzing code I use is also attached above!