mackron / miniaudio

Audio playback and capture library written in C, in a single source file.
https://miniaud.io
Other
4.06k stars 361 forks source link

stack-buffer-overflow in ma_channel_map_blank #167

Closed De4dCr0w closed 4 years ago

De4dCr0w commented 4 years ago

Another stack-buffer-overflow vulnerability in ma_channel_map_blank (miniaudio.h:38973)

Asan report:

=================================================================
==3105282==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffe624789e0 at pc 0x0000005c2884 bp 0x7ffe624776b0 sp 0x7ffe624776a8
READ of size 1 at 0x7ffe624789e0 thread T0
    #0 0x5c2883 in ma_channel_map_blank /home/osboxes/fuzz/miniaudio-project/miniaudio/examples/./../miniaudio.h:38973:13
    #1 0x5c2883 in ma_decoder__init_data_converter /home/osboxes/fuzz/miniaudio-project/miniaudio/examples/./../miniaudio.h:40320:9
    #2 0x5c2883 in ma_decoder__postinit /home/osboxes/fuzz/miniaudio-project/miniaudio/examples/./../miniaudio.h:41191:14
    #3 0x5ca52a in ma_decoder_init__internal /home/osboxes/fuzz/miniaudio-project/miniaudio/examples/./../miniaudio.h:41368:12
    #4 0x5ca52a in ma_decoder_init /home/osboxes/fuzz/miniaudio-project/miniaudio/examples/./../miniaudio.h:41383:12
    #5 0x5ca52a in ma_decoder_init_file /home/osboxes/fuzz/miniaudio-project/miniaudio/examples/./../miniaudio.h:41861:12
    #6 0x5e2f86 in main /home/osboxes/fuzz/miniaudio-project/miniaudio/examples/test.c:37:14
    #7 0x7fcc3270e0b2 in __libc_start_main /build/glibc-YYA7BZ/glibc-2.31/csu/../csu/libc-start.c:308:16
    #8 0x41c4cd in _start (/home/osboxes/fuzz/miniaudio-project/miniaudio/examples/test+0x41c4cd)

Address 0x7ffe624789e0 is located in stack of thread T0 at offset 192 in frame
    #0 0x5c8bff in ma_decoder_init_file /home/osboxes/fuzz/miniaudio-project/miniaudio/examples/./../miniaudio.h:41824

  This frame has 10 object(s):
    [32, 64) 'allocationCallbacks.i.i' (line 40559)
    [96, 192) 'config.i226' (line 41373) <== Memory access at offset 192 overflows this variable
    [224, 320) 'tmp.i227' (line 41376)
    [352, 448) 'config.i173' (line 41273)
    [480, 576) 'tmp.i174' (line 41276)
    [608, 640) 'allocationCallbacks.i' (line 40559)
    [672, 768) 'config.i86' (line 41225)
    [800, 896) 'tmp.i87' (line 41228)
    [928, 1024) 'config.i' (line 41201)
    [1056, 1152) 'tmp.i' (line 41204)
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow /home/osboxes/fuzz/miniaudio-project/miniaudio/examples/./../miniaudio.h:38973:13 in ma_channel_map_blank
Shadow bytes around the buggy address:
  0x10004c4870e0: 00 00 00 00 00 00 00 00 00 00 00 00 f3 f3 f3 f3
  0x10004c4870f0: f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3
  0x10004c487100: f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 00 00 00 00
  0x10004c487110: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10004c487120: 00 00 00 00 f1 f1 f1 f1 f8 f8 f8 f8 f2 f2 f2 f2
=>0x10004c487130: 00 00 00 00 00 00 00 00 00 00 00 00[f2]f2 f2 f2
  0x10004c487140: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f2 f2 f2 f2
  0x10004c487150: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f2 f2 f2 f2
  0x10004c487160: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f2 f2 f2 f2
  0x10004c487170: f8 f8 f8 f8 f2 f2 f2 f2 f8 f8 f8 f8 f8 f8 f8 f8
  0x10004c487180: f8 f8 f8 f8 f2 f2 f2 f2 f8 f8 f8 f8 f8 f8 f8 f8
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
  Shadow gap:              cc
==3105282==ABORTING

And I used gdb to debug the poc, and find the value of 'channels' was 172, but the size of channelMap array was 32. So it exists a stack-buffer-read-overflow vulnerability truely.

  38968 MA_API ma_bool32 ma_channel_map_blank(ma_uint32 channels, const ma_channel channelMap[MA_MAX_CHANNELS])
   38969 {
   38970     ma_uint32 iChannel;
   38971 
   38972     for (iChannel = 0; iChannel < channels; ++iChannel) {
 ► 38973         if (channelMap[iChannel] != MA_CHANNEL_NONE) {
   38974             return MA_FALSE;
   38975         }
   38976     }
   38977 
   38978     return MA_TRUE;
──────────────────────────────────────────────────────────────────────
pwndbg> p channels
$1 = 172
$gcc simple_playback.c -o simple_playback -lpthread -lm -ldl -g
$ ./simple_playback ./poc-stack2 
*** stack smashing detected ***: terminated
Aborted

poc-stack2.zip

mackron commented 4 years ago

I think this is the same underlying problem as https://github.com/dr-soft/miniaudio/issues/166. Should be fixed in the dev branch. Thanks for the report!

De4dCr0w commented 4 years ago

It has fixed the stack-buffer-overflow, but i find the memory leak. I guess it maybe relates to simple_playback.c, there maybe add 'xxx_uninit' function like what? I don't know. FYI

$ valgrind --leak-check=full ./simple-playback ./poc-stack1
==4066654== Memcheck, a memory error detector
==4066654== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==4066654== Using Valgrind-3.16.0 and LibVEX; rerun with -h for copyright info
==4066654== Command: ./test-poc /mnt/hgfs/fuzz-everything/crashes/miniaudio/poc-stack1
==4066654== 
==4066654== 
==4066654== HEAP SUMMARY:
==4066654==     in use at exit: 912 bytes in 2 blocks
==4066654==   total heap usage: 3 allocs, 1 frees, 1,936 bytes allocated
==4066654== 
==4066654== 440 bytes in 1 blocks are definitely lost in loss record 1 of 2
==4066654==    at 0x483B7FB: malloc (vg_replace_malloc.c:307)
==4066654==    by 0x14F114: ma__malloc_default (miniaudio.h:8547)
==4066654==    by 0x14F1B0: ma__malloc_from_callbacks (miniaudio.h:8570)
==4066654==    by 0x17E8B7: ma_decoder_init_wav__internal (miniaudio.h:42536)
==4066654==    by 0x180261: ma_decoder_init__internal (miniaudio.h:43515)
==4066654==    by 0x181641: ma_decoder_init_vfs (miniaudio.h:44054)
==4066654==    by 0x1823B3: ma_decoder_init_file (miniaudio.h:44404)
==4066654==    by 0x187DF2: main (simple_playback.c:37)
==4066654== 
==4066654== LEAK SUMMARY:
==4066654==    definitely lost: 440 bytes in 1 blocks
==4066654==    indirectly lost: 0 bytes in 0 blocks
==4066654==      possibly lost: 0 bytes in 0 blocks
==4066654==    still reachable: 472 bytes in 1 blocks
==4066654==         suppressed: 0 bytes in 0 blocks
==4066654== Reachable blocks (those to which a pointer was found) are not shown.
==4066654== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==4066654== 
==4066654== For lists of detected and suppressed errors, rerun with: -s
==4066654== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
mackron commented 4 years ago

Thanks! I've pushed a potential fix for the memory leak to the dev branch.