Package: libmad0

Version: latest


I found a security vulnerability in libmad, I could not contact the vendor so I 
figured I'd just send it to you guys as it's a dependency for a lot of packages 
(At Least 68).

A heap overflow or heap overrun is a type of buffer overflow that occurs in the 
heap data area. Heap overflows are exploitable in a different manner to that of 
stack-based overflows. Memory on the heap is dynamically allocated by the 
application at run-time and typically contains program data. Exploitation is 
performed by corrupting this data in specific ways to cause the application to 
overwrite internal structures such as linked list pointers. The canonical heap 
overflow technique overwrites dynamic memory allocation linkage (such as malloc 
meta data) and uses the resulting pointer exchange to overwrite a program 
function pointer.

An accidental overflow may result in data corruption or unexpected behavior by 
any process which uses the affected memory area.

A deliberate exploit may result in data at a specific location being altered in 
an arbitrary way, or in arbitrary code being executed

The vulnerability in this case takes place in the mad_bit_read() function in 
libmad. The issue was found whilst fuzzing the library. In the attachments you 
can find the reproducer and the ASAN crash log and the harness, on Ubuntu 
atleast 68 packages are dependant on libmad so I think the amount of affected 
packages will be similar on Debian.

Kind Regards,

Jordy Zomer
#include <unistd.h>
#include <stdint.h>

#include "mad.h"

struct buffer {
    unsigned char const *start;
    unsigned long length;
};

static
enum mad_flow input(void *data,
                    struct mad_stream *stream)
{
    struct buffer *buffer = (struct buffer*) data;

    if (!buffer->length)
        return MAD_FLOW_STOP;

    mad_stream_buffer(stream, buffer->start, buffer->length);

    buffer->length = 0;

    return MAD_FLOW_CONTINUE;
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
    struct buffer buffer;
    struct mad_decoder decoder;

    /* initialize our private message structure */

    buffer.start  = Data;
    buffer.length = Size;

  /* configure input, output, and error functions */

    mad_decoder_init(&decoder, &buffer,
                    input, 0 /* header */,
                    0 /* filter */,
                    0 /* output */,
                    0, 0 /* message */);

  /* start decoding */

  mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC);

    /* release the decoder */

    mad_decoder_finish(&decoder);

    return 0;
}

Attachment: libmad-heap-buffer-overflow-c53-f36-c2d.repro
Description: Binary data

INFO: Seed: 977723447
INFO: Loaded 0 modules (0 guards): 
Loading corpus dir: /samples/
Loaded 1024/1222 files from /samples/
#0      READ units: 1222
#1222   INITED cov: 1305 bits: 7362 indir: 7 corp: 614/523Kb exec/s: 611 rss: 
98Mb
=================================================================
==19511==ERROR: AddressSanitizer: heap-buffer-overflow on address 
0x61700004083c at pc 0x7f3b040c9c2e bp 0x7ffcf1a68cb0 sp 0x7ffcf1a68ca8
READ of size 1 at 0x61700004083c thread T0
    #0 0x7f3b040c9c2d in mad_bit_read (/usr/lib/libmad.so.0+0x7c2d)
    #1 0x7f3b040f2f36 in II_samples (/usr/lib/libmad.so.0+0x30f36)
    #2 0x7f3b040f1c53 in mad_layer_II (/usr/lib/libmad.so.0+0x2fc53)
    #3 0x7f3b040d86c4 in mad_frame_decode (/usr/lib/libmad.so.0+0x166c4)
    #4 0x7f3b040e6e4b in run_sync (/usr/lib/libmad.so.0+0x24e4b)
    #5 0x7f3b040e5a9e in mad_decoder_run (/usr/lib/libmad.so.0+0x23a9e)
    #6 0x50e2bd in LLVMFuzzerTestOneInput 
(/src/libmad-0.15.1b/libmad-fuzzer+0x50e2bd)
    #7 0x4f85f4 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, 
unsigned long) /src/Fuzzer/FuzzerLoop.cpp:536:13
    #8 0x4f87e4 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long) 
/src/Fuzzer/FuzzerLoop.cpp:488:3
    #9 0x4f98ce in fuzzer::Fuzzer::MutateAndTestOne() 
/src/Fuzzer/FuzzerLoop.cpp:722:30
    #10 0x4f9ae7 in fuzzer::Fuzzer::Loop() /src/Fuzzer/FuzzerLoop.cpp:755:5
    #11 0x4f1ca4 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char 
const*, unsigned long)) /src/Fuzzer/FuzzerDriver.cpp:530:3
    #12 0x4ef6f0 in main /src/Fuzzer/FuzzerMain.cpp:20:10
    #13 0x7f3b02e4f82f in __libc_start_main 
(/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #14 0x41b258 in _start (/src/libmad-0.15.1b/libmad-fuzzer+0x41b258)

0x61700004083c is located 0 bytes to the right of 700-byte region 
[0x617000040580,0x61700004083c)
allocated by thread T0 here:
    #0 0x4ecad0 in operator new[](unsigned long) 
(/src/libmad-0.15.1b/libmad-fuzzer+0x4ecad0)
    #1 0x4f8537 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, 
unsigned long) /src/Fuzzer/FuzzerLoop.cpp:527:23

SUMMARY: AddressSanitizer: heap-buffer-overflow (/usr/lib/libmad.so.0+0x7c2d) 
in mad_bit_read
Shadow bytes around the buggy address:
  0x0c2e800000b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c2e800000c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c2e800000d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c2e800000e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c2e800000f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c2e80000100: 00 00 00 00 00 00 00[04]fa fa fa fa fa fa fa fa
  0x0c2e80000110: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c2e80000120: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c2e80000130: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c2e80000140: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c2e80000150: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
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
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  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
==19511==ABORTING
MS: 2 InsertRepeatedBytes-EraseBytes-; base unit: 
234b027de6de12cc0f7e8ee194e36d17ec01412e
artifact_prefix='./'; Test unit written to /dev/shm/repro-file

Reply via email to