Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NULL pointer dereference bug in ulaw2linear_buf, in G711.cpp #54

Open
cuanduo opened this issue Jun 29, 2019 · 5 comments
Open

NULL pointer dereference bug in ulaw2linear_buf, in G711.cpp #54

cuanduo opened this issue Jun 29, 2019 · 5 comments

Comments

@cuanduo
Copy link

cuanduo commented Jun 29, 2019

There exists one NULL pointer dereference bug in ulaw2linear_buf, in G711.cpp, which allows an attacker to cause a denial of service via a crafted file.
To reproduce with the attached poc file:
./sfconvert poc output format voc
poc.zip

gdb output

[----------------------------------registers-----------------------------------]
RAX: 0xffff8284 
RBX: 0x0 
RCX: 0x7 
RDX: 0x7e00 ('')
RSI: 0x7d7c ('|}')
RDI: 0xffffffff 
RBP: 0x7fffebce2010 --> 0x0 
RSP: 0x7fffffffe2a0 --> 0x7ffff7b20ef6 (<afGetFrameCount(AFfilehandle, int)+390>:	mov    rax,QWORD PTR [rsp+0x10])
RIP: 0x7ffff7b388bf (<G711::runPull()+3199>:	mov    WORD PTR [rbx+r12*2],ax)
R8 : 0x0 
R9 : 0x55555576b648 --> 0x0 
R10: 0x55555576af48 --> 0x3e9 
R11: 0x246 
R12: 0x0 
R13: 0x0 
R14: 0x1 
R15: 0x55555576b120 --> 0x7ffff7dd3568 --> 0x7ffff7b39440 (<G711::~G711()>:	lea    rsp,[rsp-0x98])
EFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x7ffff7b388ac <G711::runPull()+3180>:	lea    rsp,[rsp+0x98]
   0x7ffff7b388b4 <G711::runPull()+3188>:	movzx  edi,BYTE PTR [rbp+r12*1+0x0]
   0x7ffff7b388ba <G711::runPull()+3194>:	call   0x7ffff7b23370 <_af_ulaw2linear>
=> 0x7ffff7b388bf <G711::runPull()+3199>:	mov    WORD PTR [rbx+r12*2],ax
   0x7ffff7b388c4 <G711::runPull()+3204>:	add    r12,0x1
   0x7ffff7b388c8 <G711::runPull()+3208>:	cmp    QWORD PTR [rsp+0x10],r12
   0x7ffff7b388cd <G711::runPull()+3213>:	je     0x7ffff7b38348 <G711::runPull()+1800>
   0x7ffff7b388d3 <G711::runPull()+3219>:	nop
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffe2a0 --> 0x7ffff7b20ef6 (<afGetFrameCount(AFfilehandle, int)+390>:	mov    rax,QWORD PTR [rsp+0x10])
0008| 0x7fffffffe2a8 --> 0x0 
0016| 0x7fffffffe2b0 --> 0x61616161 ('aaaa')
0024| 0x7fffffffe2b8 --> 0x7ffff7b1ae32 (<afReadFrames(AFfilehandle, int, void*, int)+34>:	mov    rax,QWORD PTR [rsp+0x10])
0032| 0x7fffffffe2c0 --> 0x0 
0040| 0x7fffffffe2c8 --> 0x1 
0048| 0x7fffffffe2d0 --> 0x55555576b360 --> 0x7fff00000003 
0056| 0x7fffffffe2d8 --> 0x55555576af48 --> 0x3e9 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x00007ffff7b388bf in ulaw2linear_buf (nsamples=<optimized out>, linear=<optimized out>, ulaw=<optimized out>) at G711.cpp:42
42			linear[i] = _af_ulaw2linear(ulaw[i]);
gdb-peda$ bt
#0  0x00007ffff7b388bf in ulaw2linear_buf (nsamples=<optimized out>, linear=<optimized out>, ulaw=<optimized out>) at G711.cpp:42
#1  G711::runPull (this=0x55555576b120) at G711.cpp:206
#2  0x00007ffff7b1b4b6 in afReadFrames (file=<optimized out>, trackid=<optimized out>, samples=0x0, nvframeswanted=<optimized out>) at data.cpp:222
#3  0x0000555555555f9e in copyaudiodata (infile=0x55555576ae90, outfile=0x55555576b6c0, trackid=0x3e9) at sfconvert.c:340
#4  0x00005555555555e1 in main (argc=argc@entry=0x5, argv=argv@entry=0x7fffffffe508) at sfconvert.c:248
#5  0x00007ffff76f3b97 in __libc_start_main (main=0x555555555370 <main>, argc=0x5, argv=0x7fffffffe508, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe4f8) at ../csu/libc-start.c:310
#6  0x0000555555555c3a in _start ()
@cuanduo
Copy link
Author

cuanduo commented Jul 1, 2019

caused by allocate too large mem, and then alloc return 0

asan output

root@ubuntu:~/audiofile-santi/sfcommands/.libs# ./sfconvert /home/tim/poc output format voc
==129695==WARNING: AddressSanitizer failed to allocate 0xffffffffc2c00000 bytes
==129695==AddressSanitizer's allocator is terminating the process instead of returning 0
==129695==If you don't like this behavior set allocator_may_return_null=1
==129695==AddressSanitizer CHECK failed: ../../../../src/libsanitizer/sanitizer_common/sanitizer_allocator.cc:218 "((0)) != (0)" (0x0, 0x0)
    #0 0x7f48c8503c02  (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xe9c02)
    #1 0x7f48c8522595 in __sanitizer::CheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x108595)
    #2 0x7f48c8509342  (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xef342)
    #3 0x7f48c8441e46  (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x27e46)
    #4 0x7f48c84f8b1a in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb1a)
    #5 0x558dc209af68 in copyaudiodata /home/tim/audiofile-santi/sfcommands/sfconvert.c:327
    #6 0x558dc209a620 in main /home/tim/audiofile-santi/sfcommands/sfconvert.c:248
    #7 0x7f48c7d38b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
    #8 0x558dc209ac79 in _start (/home/tim/audiofile-santi/sfcommands/.libs/sfconvert+0x1c79)

@carnil
Copy link

carnil commented Jan 2, 2021

CVE-2019-13147 was assigned for this issue.

@asarubbo
Copy link

asarubbo commented Oct 5, 2023

For completeness, this is the stacktrace I get with the provided poc:

==6157==WARNING: AddressSanitizer failed to allocate 0xffffffff85858580 bytes
AddressSanitizer:DEADLYSIGNAL
=================================================================
==6157==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x7f68322200db bp 0x7f6824545800 sp 0x7ffd57f71660 T0)
==6157==The signal is caused by a WRITE memory access.
==6157==Hint: address points to the zero page.
    #0 0x7f68322200db in ulaw2linear_buf(unsigned char const*, short*, int) /var/tmp/portage/media-libs/audiofile-0.3.6-r5/work/audiofile-0.3.6/libaudiofile/modules/G711.cpp:42:13
    #1 0x7f68322200db in G711::runPull() /var/tmp/portage/media-libs/audiofile-0.3.6-r5/work/audiofile-0.3.6/libaudiofile/modules/G711.cpp:206:3
    #2 0x7f6832212ec1 in afReadFrames /var/tmp/portage/media-libs/audiofile-0.3.6-r5/work/audiofile-0.3.6/libaudiofile/data.cpp:222:14
    #3 0x4f42e1 in copyaudiodata /var/tmp/portage/media-libs/audiofile-0.3.6-r5/work/audiofile-0.3.6/sfcommands/sfconvert.c:370:29
    #4 0x4f3b57 in main /var/tmp/portage/media-libs/audiofile-0.3.6-r5/work/audiofile-0.3.6/sfcommands/sfconvert.c:275:17
    #5 0x7f6831f31676 in __libc_start_call_main /var/tmp/portage/sys-libs/glibc-2.37-r3/work/glibc-2.37/csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #6 0x7f6831f31734 in __libc_start_main /var/tmp/portage/sys-libs/glibc-2.37-r3/work/glibc-2.37/csu/../csu/libc-start.c:360:3
    #7 0x41e780  (/usr/bin/sfconvert+0x41e780)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /var/tmp/portage/media-libs/audiofile-0.3.6-r5/work/audiofile-0.3.6/libaudiofile/modules/G711.cpp:42:13 in ulaw2linear_buf(unsigned char const*, short*, int)
==6157==ABORTING
Aborted

While the asan output complains about " failed to allocate" I confirm that under normal condition I get a Segmentation fault.

@bastien-roucaries
Copy link

Partial fix (symptom), nevertheless a fix:

commit 2f762fa2dd93fe2c66c59150d89ed15778274690
Author: Bastien Roucariès <rouca@debian.org>
Date:   Sat Nov 11 17:42:03 2023 +0000

    Partial fix of CVE-2019-13147
    
    This fix the symptom do not allow to allocate negative memory:
    ==129695==WARNING: AddressSanitizer failed to allocate 0xffffffffc2c00000 bytes
    ==129695==AddressSanitizer's allocator is terminating the process instead of returning 0
    ==129695==If you don't like this behavior set allocator_may_return_null=1
    ==129695==AddressSanitizer CHECK failed: ../../../../src/libsanitizer/sanitizer_common/sanitizer_allocator.cc:218 "((0)) != (0)" (0x0, 0x0)
        #0 0x7f48c8503c02  (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xe9c02)
        #1 0x7f48c8522595 in __sanitizer::CheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x108595)
        #2 0x7f48c8509342  (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xef342)
        #3 0x7f48c8441e46  (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x27e46)
        #4 0x7f48c84f8b1a in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb1a)
        #5 0x558dc209af68 in copyaudiodata /home/tim/audiofile-santi/sfcommands/sfconvert.c:327
        #6 0x558dc209a620 in main /home/tim/audiofile-santi/sfcommands/sfconvert.c:248
        #7 0x7f48c7d38b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
        #8 0x558dc209ac79 in _start (/home/tim/audiofile-santi/sfcommands/.libs/sfconvert+0x1c79)
    
    If negative bail out

diff --git a/sfcommands/sfconvert.c b/sfcommands/sfconvert.c
index 367f7a5..400d485 100644
--- a/sfcommands/sfconvert.c
+++ b/sfcommands/sfconvert.c
@@ -349,7 +349,8 @@ void printversion (void)
 bool copyaudiodata (AFfilehandle infile, AFfilehandle outfile, int trackid)
 {
        int frameSize = afGetVirtualFrameSize(infile, trackid, 1);
-
+       if(frameSize <= 0)
+               return false;
        int kBufferFrameCount = 65536;
        int bufferSize;
        while (multiplyCheckOverflow(kBufferFrameCount, frameSize, &bufferSize))

@bastien-roucaries
Copy link

Real fix is too many channel:

commit 18e39112376f488bf57ca6527d42afc644f06a94 (HEAD -> patch-queue/master)
Author: Bastien Roucariès <rouca@debian.org>
Date:   Sat Nov 11 17:43:19 2023 +0000

    Partial fix of CVE-2019-13147
    
    This is the fix of the POC. Do not allow too many channel
    
    Now it fail with:
    Audio File Library: invalid file with 1633771873 channels [error 15]
    Could not open file 'poc' for reading.

diff --git a/libaudiofile/NeXT.cpp b/libaudiofile/NeXT.cpp
index c462dbe..01c967c 100644
--- a/libaudiofile/NeXT.cpp
+++ b/libaudiofile/NeXT.cpp
@@ -32,6 +32,7 @@
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
+#include <limits.h>
 
 #include "File.h"
 #include "Setup.h"
@@ -122,6 +123,12 @@ status NeXTFile::readInit(AFfilesetup setup)
                _af_error(AF_BAD_CHANNELS, "invalid file with 0 channels");
                return AF_FAIL;
        }
+       /* avoid overflow of INT for double size rate */
+       if (channelCount > (INT32_MAX / (sizeof(double))))
+       {
+               _af_error(AF_BAD_CHANNELS, "invalid file with %i channels", channelCount);
+               return AF_FAIL;
+       }
 
        Track *track = allocateTrack();
        if (!track)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants