Shaleen Jain

(Updated: ) · 6 min read

Fuzzing libVLC - De-multiplexer

So, I have been working on writing a fuzz target for the demux API for the past two weeks and I have reached a point where it has a good code coverage and has already found some few shallow bugs.

Here are some of the stacktraces libfuzzer spit out and all of them were fixed rather promptly.

A Segfault on a null pointer, fixed by adding a null check

==25241==ERROR: AddressSanitizer: SEGV on unknown address 0xffffffffffffff68 (pc 0x7f56c19e8ab0 bp 0xffffffffffffff58 sp 0x7ffcdfe59e58 T0)
==25241==The signal is caused by a READ memory access.
    #0 0x7f56c19e8aaf  (/usr/lib/libpthread.so.0+0x9aaf)
    #1 0x7f56c275c5e1 in Lookup misc/variables.c:158
    #2 0x7f56c275c5e1 in AddCallback misc/variables.c:839
    #3 0x7f56c275c5e1 in var_AddCallback misc/variables.c:884
    #4 0x7f56b336a55e in blurayOpen access/bluray.c:674
    #5 0x7f56c26df59d in module_load modules/modules.c:183
    #6 0x7f56c26dfb43 in vlc_module_load modules/modules.c:275
    #7 0x7f56c2704dec in demux_NewAdvanced input/demux.c:259
    #8 0x7f56c2705236 in demux_New input/demux.c:151
    #9 0x40575b in LLVMFuzzerTestOneInput /home/shalzz/builds/vlc/test/fuzz/libvlc_demux_fuzzer.cpp:73
    #10 0x416714 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) FuzzerLoop.cpp:458
    #11 0x416983 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long) FuzzerLoop.cpp:397
    #12 0x41714d in fuzzer::Fuzzer::MutateAndTestOne() FuzzerLoop.cpp:596
    #13 0x417397 in fuzzer::Fuzzer::Loop() FuzzerLoop.cpp:624
    #14 0x410438 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) FuzzerDriver.cpp:744
    #15 0x405c40 in main FuzzerMain.cpp:20
    #16 0x7f56c0089439 in __libc_start_main (/usr/lib/libc.so.6+0x20439)
    #17 0x404ee9 in _start (/home/shalzz/builds/vlc/test/fuzz/.libs/lt-libvlc_demux_fuzzer+0x404ee9)

Abort due to character conversion without a conversion descriptor, fixed.

==32703== ERROR: libFuzzer: deadly signal
    #0 0x7f46cd57fb68 in __sanitizer_print_stack_trace /build/gcc-multilib/src/gcc/libsanitizer/asan/asan_stack.cc:36
    #1 0x468961 in fuzzer::Fuzzer::CrashCallback() FuzzerLoop.cpp:195
    #2 0x46892d in fuzzer::Fuzzer::StaticCrashSignalCallback() FuzzerLoop.cpp:179
    #3 0x7f46cc83993f  (/usr/lib/libpthread.so.0+0x1193f)
    #4 0x7f46cbf8d66f in raise (/usr/lib/libc.so.6+0x3366f)
    #5 0x7f46cbf8ecff in __GI_abort (/usr/lib/libc.so.6+0x34cff)
    #6 0x7f46cce9996f in vlc_iconv extras/libc.c:391
    #7 0x7f46ccf3e083 in vlc_stream_ReadLine input/stream.c:321
    #8 0x7f4690b96342 in peek_Readline demux/subtitle_helper.h:38
    #9 0x7f4690b96b02 in Open demux/vobsub.c:128
    #10 0x7f46cce9b2dc in generic_start modules/modules.c:356
    #11 0x7f46cce9a508 in module_load modules/modules.c:183
    #12 0x7f46cce9abd6 in vlc_module_load modules/modules.c:279
    #13 0x7f46cce9b42d in module_need modules/modules.c:371
    #14 0x7f46cceef2bd in demux_NewAdvanced input/demux.c:259
    #15 0x7f46cceeeadd in demux_New input/demux.c:151
    #16 0x458a46 in LLVMFuzzerTestOneInput (/home/shalzz/builds/vlc-clean/test/fuzz/libvlc_demux_fuzzer+0x458a46)
    #17 0x469754 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) FuzzerLoop.cpp:458
    #18 0x4699c3 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long) FuzzerLoop.cpp:397
    #19 0x45f421 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) FuzzerDriver.cpp:268
    #20 0x463034 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) FuzzerDriver.cpp:683
    #21 0x458c80 in main FuzzerMain.cpp:20
    #22 0x7f46cbf7a439 in __libc_start_main (/usr/lib/libc.so.6+0x20439)
    #23 0x458239 in _start (/home/shalzz/builds/vlc-clean/test/fuzz/libvlc_demux_fuzzer+0x458239)

A heap-use-after-free, fixed by this and this.

==26135==ERROR: AddressSanitizer: heap-use-after-free on address 0x613000005a00 at pc 0x7f4549af4c64 bp 0x7ffcb951f110 sp 0x7ffcb951e8b8
    READ of size 4 at 0x613000005a00 thread T0
        #0 0x7f4549af4c63 in __interceptor_memcmp /build/gcc-multilib/src/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:626
        #1 0x7f453871981c in Open demux/image.c:640
        #2 0x7f4548ffdb26 in generic_start modules/modules.c:356
        #3 0x7f4548ffca56 in module_load modules/modules.c:183
        #4 0x7f4548ffd2e5 in vlc_module_load modules/modules.c:279
        #5 0x7f4548ffdc77 in module_need modules/modules.c:371
        #6 0x7f4549076c84 in demux_NewAdvanced input/demux.c:259
        #7 0x7f4549075fc2 in demux_New input/demux.c:151
        #8 0x405ce5 in LLVMFuzzerTestOneInput /home/shalzz/builds/vlc/test/fuzz/libvlc_demux_fuzzer.cpp:68
        #9 0x4169d4 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) FuzzerLoop.cpp:458
        #10 0x416c43 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long) FuzzerLoop.cpp:397
        #11 0x41740d in fuzzer::Fuzzer::MutateAndTestOne() FuzzerLoop.cpp:596
        #12 0x417657 in fuzzer::Fuzzer::Loop() FuzzerLoop.cpp:624
        #13 0x4106f8 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) FuzzerDriver.cpp:744
        #14 0x405f00 in main FuzzerMain.cpp:20
        #15 0x7f45464b0439 in __libc_start_main (/usr/lib/libc.so.6+0x20439)
        #16 0x404e49 in _start (/home/shalzz/builds/vlc/test/fuzz/.libs/lt-libvlc_demux_fuzzer+0x404e49)
     
    0x613000005a00 is located 128 bytes inside of 380-byte region [0x613000005980,0x613000005afc)
    freed by thread T0 here:
        #0 0x7f4549b234c8 in __interceptor_free /build/gcc-multilib/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:45
        #1 0x7f4549193fc7 in block_generic_Release misc/block.c:99
        #2 0x7f4549193a3c in block_Release ../include/vlc_block.h:184
        #3 0x7f4549194de2 in block_TryRealloc misc/block.c:212
        #4 0x7f45490e89bb in vlc_stream_Peek input/stream.c:506
        #5 0x7f4538717037 in IsPnm demux/image.c:354
        #6 0x7f45387195bd in Open demux/image.c:634
        #7 0x7f4548ffdb26 in generic_start modules/modules.c:356
        #8 0x7f4548ffca56 in module_load modules/modules.c:183
        #9 0x7f4548ffd2e5 in vlc_module_load modules/modules.c:279
        #10 0x7f4548ffdc77 in module_need modules/modules.c:371
        #11 0x7f4549076c84 in demux_NewAdvanced input/demux.c:259
        #12 0x7f4549075fc2 in demux_New input/demux.c:151
        #13 0x405ce5 in LLVMFuzzerTestOneInput /home/shalzz/builds/vlc/test/fuzz/libvlc_demux_fuzzer.cpp:68
        #14 0x4169d4 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) FuzzerLoop.cpp:458
        #15 0x416c43 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long) FuzzerLoop.cpp:397
        #16 0x41740d in fuzzer::Fuzzer::MutateAndTestOne() FuzzerLoop.cpp:596
        #17 0x417657 in fuzzer::Fuzzer::Loop() FuzzerLoop.cpp:624
        #18 0x4106f8 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) FuzzerDriver.cpp:744
        #19 0x405f00 in main FuzzerMain.cpp:20
        #20 0x7f45464b0439 in __libc_start_main (/usr/lib/libc.so.6+0x20439)
     
    previously allocated by thread T0 here:
        #0 0x7f4549b23860 in __interceptor_malloc /build/gcc-multilib/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:62
        #1 0x7f4549194434 in block_Alloc misc/block.c:128
        #2 0x7f4549194c77 in block_TryRealloc misc/block.c:205
        #3 0x7f45490e89bb in vlc_stream_Peek input/stream.c:506
        #4 0x7f4539fc5e24 in DetectPVRHeadersAndHeaderSize demux/mpeg/ts.c:256
        #5 0x7f4539fc6272 in Open demux/mpeg/ts.c:357
        #6 0x7f4548ffdb26 in generic_start modules/modules.c:356
        #7 0x7f4548ffca56 in module_load modules/modules.c:183
        #8 0x7f4548ffd2e5 in vlc_module_load modules/modules.c:279
        #9 0x7f4548ffdc77 in module_need modules/modules.c:371
        #10 0x7f4549076c84 in demux_NewAdvanced input/demux.c:259
        #11 0x7f4549075fc2 in demux_New input/demux.c:151
        #12 0x405ce5 in LLVMFuzzerTestOneInput /home/shalzz/builds/vlc/test/fuzz/libvlc_demux_fuzzer.cpp:68
        #13 0x4169d4 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) FuzzerLoop.cpp:458
        #14 0x416c43 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long) FuzzerLoop.cpp:397
        #15 0x41740d in fuzzer::Fuzzer::MutateAndTestOne() FuzzerLoop.cpp:596
        #16 0x417657 in fuzzer::Fuzzer::Loop() FuzzerLoop.cpp:624
        #17 0x4106f8 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) FuzzerDriver.cpp:744
        #18 0x405f00 in main FuzzerMain.cpp:20
        #19 0x7f45464b0439 in __libc_start_main (/usr/lib/libc.so.6+0x20439)
     
    SUMMARY: AddressSanitizer: heap-use-after-free /build/gcc-multilib/src/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:626 in __interceptor_memcmp
    Shadow bytes around the buggy address:
      0x0c267fff8af0: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
      0x0c267fff8b00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x0c267fff8b10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x0c267fff8b20: 00 00 00 00 00 fa fa fa fa fa fa fa fa fa fa fa
      0x0c267fff8b30: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
    =>0x0c267fff8b40:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
      0x0c267fff8b50: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
      0x0c267fff8b60: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c267fff8b70: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c267fff8b80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c267fff8b90: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
    Shadow byte legend (one shadow byte represents 8 application bytes):
      Addressable:           00
      Partially addressable: 01 02 03 04 05 06 07
      Heap left redzone:       fa
      Freed heap region:       fd
      Stack left redzone:      f1
      Stack mid redzone:       f2
      Stack right redzone:     f3
      Stack after return:      f5
      Stack use after scope:   f8
      Global redzone:          f9
      Global init order:       f6
      Poisoned by user:        f7
      Container overflow:      fc
      Array cookie:            ac
      Intra object redzone:    bb
      ASan internal:           fe
      Left alloca redzone:     ca
      Right alloca redzone:    cb
    ==26135==ABORTING

Unfortunately I cannot publish my source code yet or start integrating with oss-fuzz and cluster fuzz by Google as VideoLAN/Labs is still undecided and would rather do this privately, mostly because they don't want to be bound by Google's bug disclosure policy.

I think they are just confused that they have to do a software release within the specified deadline when it's just a bug disclosure, but whatever. (There's no longer any confusion.)

Update: You can find all my bug fixes and patches here

Liked this article? Buy me a beer on the Bitcoin Lightning Network

Got any questions or comments? Drop me a message on Twitter @shalzzj or comment below.