Opened 4 years ago

Closed 4 years ago

Last modified 4 years ago

#8718 closed defect (fixed)

Heap buffer overflow in crash_dnn_execute_layer_pad due to integer overflow in memcpy

Reported by: Assaf Sion Owned by: Guo Yejun
Priority: important Component: avfilter
Version: git-master Keywords: dnn crash SIGSEGV
Cc: assafsion@gmaiil.com, yejun.guo@intel.com Blocked By:
Blocking: Reproduced by developer: yes
Analyzed by developer: no

Description

This bug apply to all the 4 *different* memcpy calls exist in the function dnn_execute_layer_pad. Calling to calculate_operand_data_length to calculate the destination buffer size an integer overflow occurs. This could allow an attacker to control the address of the source and destination buffer inside the memcpy and to cause a read/write overflow. This is highly critical and could allow an attacker to execute code.

I compiled ffmpeg on Ubuntu 18.04 with the following configuration:
configuration: --cc=clang --extra-cflags='-O0 -g3 -fsanitize=address -Wno-error -fPIC' --extra-ldflags='-O0 -g3 -fsanitize=address -Wno-error -fPIC' --enable-debug --disable-asm --disable-optimizations --disable-shared --enable-libopenjpeg --enable-gpl --enable-libass --enable-libfdk-aac --enable-libmp3lame --enable-libopus --enable-libtheora --enable-libvorbis --enable-libvpx --enable-libx264 --enable-nonfree
the bug could be reproduced while running the following command line:
ffmpeg -v debug -i 10.jpg -vf format=rgb24,sr=dnn_backend=native:model=crash_dnn_execute_layer_pad_3 derain.jpg
the output after running the command:

ffmpeg version N-97806-gf603d10b1e Copyright (c) 2000-2020 the FFmpeg developers

built with clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)
configuration: --cc=clang --extra-cflags='-O0 -g3 -fsanitize=address -Wno-error -fPIC' --extra-ldflags='-O0 -g3 -fsanitize=address -Wno-error -fPIC' --enable-debug --disable-asm --disable-optimizations --disable-shared --enable-libopenjpeg --enable-gpl --enable-libass --enable-libfdk-aac --enable-libmp3lame --enable-libopus --enable-libtheora --enable-libvorbis --enable-libvpx --enable-libx264 --enable-nonfree
libavutil 56. 45.100 / 56. 45.100
libavcodec 58. 84.100 / 58. 84.100
libavformat 58. 43.100 / 58. 43.100
libavdevice 58. 9.103 / 58. 9.103
libavfilter 7. 81.100 / 7. 81.100
libswscale 5. 6.101 / 5. 6.101
libswresample 3. 6.100 / 3. 6.100
libpostproc 55. 6.100 / 55. 6.100

Splitting the commandline.
Reading option '-v' ... matched as option 'v' (set logging level) with argument 'debug'.
Reading option '-i' ... matched as input url with argument '10.jpg'.
Reading option '-vf' ... matched as option 'vf' (set video filters) with argument 'format=rgb24,sr=dnn_backend=native:model=crash_dnn_execute_layer_pad_3'.
Reading option 'derain.jpg' ... matched as output url.
Finished splitting the commandline.
Parsing a group of options: global .
Applying option v (set logging level) with argument debug.
Successfully parsed a group of options.
Parsing a group of options: input url 10.jpg.
Successfully parsed a group of options.
Opening an input file: 10.jpg.
[NULL @ 0x61b000000080] Opening '10.jpg' for reading
[file @ 0x60c000000040] Setting default whitelist 'file,crypto,data'
[image2 @ 0x61b000000080] Format image2 probed with size=2048 and score=50
[image2 @ 0x61b000000080] Before avformat_find_stream_info() pos: 0 bytes read:18522 seeks:0 nb_streams:1
[mjpeg @ 0x619000000580] marker=d8 avail_size_in_buf=18520
[mjpeg @ 0x619000000580] marker parser used 0 bytes (0 bits)
[mjpeg @ 0x619000000580] marker=e0 avail_size_in_buf=18518
[mjpeg @ 0x619000000580] marker parser used 16 bytes (128 bits)
[mjpeg @ 0x619000000580] marker=e1 avail_size_in_buf=18500
[mjpeg @ 0x619000000580] marker parser used 12833 bytes (102664 bits)
[mjpeg @ 0x619000000580] marker=db avail_size_in_buf=5664
[mjpeg @ 0x619000000580] index=0
[mjpeg @ 0x619000000580] qscale[0]: 2
[mjpeg @ 0x619000000580] marker parser used 67 bytes (536 bits)
[mjpeg @ 0x619000000580] marker=db avail_size_in_buf=5595
[mjpeg @ 0x619000000580] index=1
[mjpeg @ 0x619000000580] qscale[1]: 8
[mjpeg @ 0x619000000580] marker parser used 67 bytes (536 bits)
[mjpeg @ 0x619000000580] marker=c0 avail_size_in_buf=5526
[mjpeg @ 0x619000000580] Changing bps from 0 to 8
[mjpeg @ 0x619000000580] sof0: picture: 432x173
[mjpeg @ 0x619000000580] component 0 1:1 id: 0 quant:0
[mjpeg @ 0x619000000580] component 1 1:1 id: 1 quant:1
[mjpeg @ 0x619000000580] component 2 1:1 id: 2 quant:1
[mjpeg @ 0x619000000580] pix fmt id 11111100
[mjpeg @ 0x619000000580] Format yuvj444p chosen by get_format().
[mjpeg @ 0x619000000580] marker parser used 17 bytes (136 bits)
[mjpeg @ 0x619000000580] marker=c4 avail_size_in_buf=5507
[mjpeg @ 0x619000000580] marker parser used 0 bytes (0 bits)
[mjpeg @ 0x619000000580] marker=c4 avail_size_in_buf=5478
[mjpeg @ 0x619000000580] marker parser used 0 bytes (0 bits)
[mjpeg @ 0x619000000580] marker=c4 avail_size_in_buf=5420
[mjpeg @ 0x619000000580] marker parser used 0 bytes (0 bits)
[mjpeg @ 0x619000000580] marker=c4 avail_size_in_buf=5393
[mjpeg @ 0x619000000580] marker parser used 0 bytes (0 bits)
[mjpeg @ 0x619000000580] escaping removed 16 bytes
[mjpeg @ 0x619000000580] marker=da avail_size_in_buf=5360
[mjpeg @ 0x619000000580] marker parser used 5344 bytes (42752 bits)
[mjpeg @ 0x619000000580] marker=d9 avail_size_in_buf=0
[mjpeg @ 0x619000000580] decode frame unused 0 bytes
[image2 @ 0x61b000000080] After avformat_find_stream_info() pos: 18522 bytes read:18522 seeks:0 frames:1
Input #0, image2, from '10.jpg':

Duration: 00:00:00.04, start: 0.000000, bitrate: 3704 kb/s

Stream #0:0, 1, 1/25: Video: mjpeg (Baseline), 1 reference frame, yuvj444p(pc, bt470bg/unknown/unknown, center), 432x173 [SAR 96:96 DAR 432:173], 0/1, 25 tbr, 25 tbn, 25 tbc

Successfully opened the file.
Parsing a group of options: output url derain.jpg.
Applying option vf (set video filters) with argument format=rgb24,sr=dnn_backend=native:model=crash_dnn_execute_layer_pad_3.
Successfully parsed a group of options.
Opening an output file: derain.jpg.
Successfully opened the file.
Stream mapping:

Stream #0:0 -> #0:0 (mjpeg (native) -> mjpeg (native))

Press [q] to stop, ? for help
cur_dts is invalid st:0 (0) [init:0 i_done:0 finish:0] (this is harmless if it occurs once at the start per stream)
[mjpeg @ 0x619000000a80] marker=d8 avail_size_in_buf=18520
[mjpeg @ 0x619000000a80] marker parser used 0 bytes (0 bits)
[mjpeg @ 0x619000000a80] marker=e0 avail_size_in_buf=18518
[mjpeg @ 0x619000000a80] marker parser used 16 bytes (128 bits)
[mjpeg @ 0x619000000a80] marker=e1 avail_size_in_buf=18500
[mjpeg @ 0x619000000a80] marker parser used 12833 bytes (102664 bits)
[mjpeg @ 0x619000000a80] marker=db avail_size_in_buf=5664
[mjpeg @ 0x619000000a80] index=0
[mjpeg @ 0x619000000a80] qscale[0]: 2
[mjpeg @ 0x619000000a80] marker parser used 67 bytes (536 bits)
[mjpeg @ 0x619000000a80] marker=db avail_size_in_buf=5595
[mjpeg @ 0x619000000a80] index=1
[mjpeg @ 0x619000000a80] qscale[1]: 8
[mjpeg @ 0x619000000a80] marker parser used 67 bytes (536 bits)
[mjpeg @ 0x619000000a80] marker=c0 avail_size_in_buf=5526
[mjpeg @ 0x619000000a80] sof0: picture: 432x173
[mjpeg @ 0x619000000a80] component 0 1:1 id: 0 quant:0
[mjpeg @ 0x619000000a80] component 1 1:1 id: 1 quant:1
[mjpeg @ 0x619000000a80] component 2 1:1 id: 2 quant:1
[mjpeg @ 0x619000000a80] pix fmt id 11111100
[mjpeg @ 0x619000000a80] Format yuvj444p chosen by get_format().
[mjpeg @ 0x619000000a80] marker parser used 17 bytes (136 bits)
[mjpeg @ 0x619000000a80] marker=c4 avail_size_in_buf=5507
[mjpeg @ 0x619000000a80] class=0 index=0 nb_codes=8
[mjpeg @ 0x619000000a80] marker parser used 27 bytes (216 bits)
[mjpeg @ 0x619000000a80] marker=c4 avail_size_in_buf=5478
[mjpeg @ 0x619000000a80] class=1 index=0 nb_codes=226
[mjpeg @ 0x619000000a80] marker parser used 56 bytes (448 bits)
[mjpeg @ 0x619000000a80] marker=c4 avail_size_in_buf=5420
[mjpeg @ 0x619000000a80] class=0 index=1 nb_codes=6
[mjpeg @ 0x619000000a80] marker parser used 25 bytes (200 bits)
[mjpeg @ 0x619000000a80] marker=c4 avail_size_in_buf=5393
[mjpeg @ 0x619000000a80] class=1 index=1 nb_codes=82
[mjpeg @ 0x619000000a80] marker parser used 31 bytes (248 bits)
[mjpeg @ 0x619000000a80] escaping removed 16 bytes
[mjpeg @ 0x619000000a80] marker=da avail_size_in_buf=5360
[mjpeg @ 0x619000000a80] component: 0
[mjpeg @ 0x619000000a80] component: 1
[mjpeg @ 0x619000000a80] component: 2
[mjpeg @ 0x619000000a80] marker parser used 5343 bytes (42742 bits)
[mjpeg @ 0x619000000a80] marker=d9 avail_size_in_buf=0
[mjpeg @ 0x619000000a80] decode frame unused 0 bytes
detected 32 logical cores
[Parsed_format_0 @ 0x610000000040] Setting 'pix_fmts' to value 'rgb24'
[Parsed_sr_1 @ 0x610000000140] Setting 'dnn_backend' to value 'native'
[Parsed_sr_1 @ 0x610000000140] Setting 'model' to value 'crash_dnn_execute_layer_pad_3'
[file @ 0x60d000000040] Setting default whitelist 'file,crypto,data'
[AVIOContext @ 0x6120000001c0] Statistics: 145 bytes read, 0 seeks
[graph 0 input from stream 0:0 @ 0x610000000240] Setting 'video_size' to value '432x173'
[graph 0 input from stream 0:0 @ 0x610000000240] Setting 'pix_fmt' to value '14'
[graph 0 input from stream 0:0 @ 0x610000000240] Setting 'time_base' to value '1/25'
[graph 0 input from stream 0:0 @ 0x610000000240] Setting 'pixel_aspect' to value '96/96'
[graph 0 input from stream 0:0 @ 0x610000000240] Setting 'frame_rate' to value '25/1'
[graph 0 input from stream 0:0 @ 0x610000000240] w:432 h:173 pixfmt:yuvj444p tb:1/25 fr:25/1 sar:96/96
[format @ 0x610000000440] Setting 'pix_fmts' to value 'yuvj420p|yuvj422p|yuvj444p'
[auto_scaler_0 @ 0x610000001d40] Setting 'flags' to value 'bicubic'
[auto_scaler_0 @ 0x610000001d40] w:iw h:ih flags:'bicubic' interl:0
[Parsed_format_0 @ 0x610000000040] auto-inserting filter 'auto_scaler_0' between the filter 'graph 0 input from stream 0:0' and the filter 'Parsed_format_0'
[auto_scaler_1 @ 0x610000002a40] Setting 'flags' to value 'bicubic'
[auto_scaler_1 @ 0x610000002a40] w:iw h:ih flags:'bicubic' interl:0
[Parsed_sr_1 @ 0x610000000140] auto-inserting filter 'auto_scaler_1' between the filter 'Parsed_format_0' and the filter 'Parsed_sr_1'
[auto_scaler_2 @ 0x610000003740] Setting 'flags' to value 'bicubic'
[auto_scaler_2 @ 0x610000003740] w:iw h:ih flags:'bicubic' interl:0
[format @ 0x610000000440] auto-inserting filter 'auto_scaler_2' between the filter 'Parsed_sr_1' and the filter 'format'
[AVFilterGraph @ 0x6090000006e0] query_formats: 5 queried, 1 merged, 3 already done, 0 delayed
[auto_scaler_1 @ 0x610000002a40] picking yuv444p out of 6 ref:rgb24 alpha:0
[auto_scaler_2 @ 0x610000003740] picking yuvj444p out of 3 ref:yuv444p alpha:0
[swscaler @ 0x62f000000400] deprecated pixel format used, make sure you did set range correctly
[swscaler @ 0x62f000000400] Forcing full internal H chroma due to input having non subsampled chroma
[auto_scaler_0 @ 0x610000001d40] w:432 h:173 fmt:yuvj444p sar:96/96 -> w:432 h:173 fmt:rgb24 sar:1/1 flags:0x4
[auto_scaler_1 @ 0x610000002a40] w:432 h:173 fmt:rgb24 sar:1/1 -> w:432 h:173 fmt:yuv444p sar:1/1 flags:0x4
AddressSanitizer:DEADLYSIGNAL
=================================================================
==95910==ERROR: AddressSanitizer: SEGV on unknown address 0x7fff2cda1a7c (pc 0x7ffff2d53595 bp 0x7fffffff6b00 sp 0x7fffffff6288 T0)
==95910==The signal is caused by a WRITE memory access.

#0 0x7ffff2d53594 /build/glibc-OTsEL5/glibc-2.27/string/../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:307
#1 0x4e215d in asan_memcpy (/home/cyber/VulnResearch/ffmpeg/clean/13_5_ffmpeg/FFmpeg/ffmpeg_g+0x4e215d)
#2 0x1318940 in dnn_execute_layer_pad /home/cyber/VulnResearch/ffmpeg/clean/13_5_ffmpeg/FFmpeg/libavfilter/dnn/dnn_backend_native_layer_pad.c:124:17
#3 0x130f6ee in ff_dnn_execute_model_native /home/cyber/VulnResearch/ffmpeg/clean/13_5_ffmpeg/FFmpeg/libavfilter/dnn/dnn_backend_native.c:276:9
#4 0xe5a10f in config_props /home/cyber/VulnResearch/ffmpeg/clean/13_5_ffmpeg/FFmpeg/libavfilter/vf_sr.c:133:14
#5 0x6c1d38 in avfilter_config_links /home/cyber/VulnResearch/ffmpeg/clean/13_5_ffmpeg/FFmpeg/libavfilter/avfilter.c:369:28
#6 0x6c08bd in avfilter_config_links /home/cyber/VulnResearch/ffmpeg/clean/13_5_ffmpeg/FFmpeg/libavfilter/avfilter.c:307:24
#7 0x6c08bd in avfilter_config_links /home/cyber/VulnResearch/ffmpeg/clean/13_5_ffmpeg/FFmpeg/libavfilter/avfilter.c:307:24
#8 0x6c08bd in avfilter_config_links /home/cyber/VulnResearch/ffmpeg/clean/13_5_ffmpeg/FFmpeg/libavfilter/avfilter.c:307:24
#9 0x6d1dbc in graph_config_links /home/cyber/VulnResearch/ffmpeg/clean/13_5_ffmpeg/FFmpeg/libavfilter/avfiltergraph.c:261:24
#10 0x6d0bb6 in avfilter_graph_config /home/cyber/VulnResearch/ffmpeg/clean/13_5_ffmpeg/FFmpeg/libavfilter/avfiltergraph.c:1279:16
#11 0x568e88 in configure_filtergraph /home/cyber/VulnResearch/ffmpeg/clean/13_5_ffmpeg/FFmpeg/fftools/ffmpeg_filter.c:1106:16
#12 0x5d66a3 in ifilter_send_frame /home/cyber/VulnResearch/ffmpeg/clean/13_5_ffmpeg/FFmpeg/fftools/ffmpeg.c:2166:15
#13 0x5d5669 in send_frame_to_filters /home/cyber/VulnResearch/ffmpeg/clean/13_5_ffmpeg/FFmpeg/fftools/ffmpeg.c:2247:15
#14 0x5d0f2b in decode_video /home/cyber/VulnResearch/ffmpeg/clean/13_5_ffmpeg/FFmpeg/fftools/ffmpeg.c:2446:11
#15 0x59ba41 in process_input_packet /home/cyber/VulnResearch/ffmpeg/clean/13_5_ffmpeg/FFmpeg/fftools/ffmpeg.c:2600:19
#16 0x5be936 in process_input /home/cyber/VulnResearch/ffmpeg/clean/13_5_ffmpeg/FFmpeg/fftools/ffmpeg.c:4491:5
#17 0x597af6 in transcode_step /home/cyber/VulnResearch/ffmpeg/clean/13_5_ffmpeg/FFmpeg/fftools/ffmpeg.c:4611:11
#18 0x590da5 in transcode /home/cyber/VulnResearch/ffmpeg/clean/13_5_ffmpeg/FFmpeg/fftools/ffmpeg.c:4665:15
#19 0x58efda in main /home/cyber/VulnResearch/ffmpeg/clean/13_5_ffmpeg/FFmpeg/fftools/ffmpeg.c:4866:9
#20 0x7ffff2cb9b96 in
libc_start_main /build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310
#21 0x423839 in _start (/home/cyber/VulnResearch/ffmpeg/clean/13_5_ffmpeg/FFmpeg/ffmpeg_g+0x423839)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /build/glibc-OTsEL5/glibc-2.27/string/../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:307
==95910==ABORTING
[1] + Done "/usr/bin/gdb" --interpreter=mi --tty=${DbgTerm} 0<"/tmp/Microsoft-MIEngine-In-l1la0r3g.zlb" 1>"/tmp/Microsoft-MIEngine-Out-kftego55.fig"

Attachments (2)

10.jpg (18.1 KB ) - added by Assaf Sion 4 years ago.
crash_dnn_execute_layer_pad_3 (145 bytes ) - added by Assaf Sion 4 years ago.

Download all attachments as: .zip

Change History (11)

by Assaf Sion, 4 years ago

Attachment: 10.jpg added

comment:1 by Assaf Sion, 4 years ago

Component: undeterminedavfilter

by Assaf Sion, 4 years ago

comment:2 by Carl Eugen Hoyos, 4 years ago

Keywords: dnn crash SIGSEGV added
Priority: criticalimportant
Reproduced by developer: set
Status: newopen

comment:3 by Assaf Sion, 4 years ago

Any updates regarding the bug?
We at CyberArk wait for the patch so we could report this bug and assign a CVE for this.

comment:4 by Assaf Sion, 4 years ago

Owner: set to Guo Yejun

comment:5 by Assaf Sion, 4 years ago

This bug could lead to code execution and fixing this bug is highly important.

in reply to:  4 comment:6 by Guo Yejun, 4 years ago

Cc: yejun.guo@intel.com added

Replying to assafsion: sorry, i do not receive an email for this, and i missed this issue, will look at it now.

in reply to:  4 comment:7 by Guo Yejun, 4 years ago

Cc: yejun.guo@intel.com added

Replying to assafsion: sorry, i do not receive an email for this, and i missed this issue, will look at it now.

comment:8 by Carl Eugen Hoyos, 4 years ago

Resolution: fixed
Status: openclosed

in reply to:  5 comment:9 by Carl Eugen Hoyos, 4 years ago

Replying to assafsion:

This bug could lead to code execution and fixing this bug is highly important.

Since other people may read this:
This bug can lead to code execution if the attacker already has full control over the ffmpeg command line. If an attacker has full control over the ffmpeg command line, the system is already compromised independently of this bug.

Last edited 4 years ago by Carl Eugen Hoyos (previous) (diff)
Note: See TracTickets for help on using tickets.