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

heap-buffer-overflow in put_epel_hv_fallback when decoding file #233

Closed
leonzhao7 opened this issue Dec 24, 2019 · 4 comments
Closed

heap-buffer-overflow in put_epel_hv_fallback when decoding file #233

leonzhao7 opened this issue Dec 24, 2019 · 4 comments

Comments

@leonzhao7
Copy link

heap-buffer-overflow in put_epel_hv_fallback when decoding file

I found some problems during fuzzing

Test Version

dev version, git clone https://github.com/strukturag/libde265

Test Environment

root@ubuntu:~# lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 16.04.6 LTS
Release: 16.04
Codename: xenial

Test Configure

./configure
configure: ---------------------------------------
configure: Building dec265 example: yes
configure: Building sherlock265 example: no
configure: Building encoder: yes
configure: ---------------------------------------

Test Program

dec265 [infile]

Asan Output

root@ubuntu:~# /opt/asan/bin/dec265 libde265-put_epel_hv_fallback-heap_overflow.crash
WARNING: pps header invalid
=================================================================
==51241==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x62f00001c3b8 at pc 0x0000004354cc bp 0x7fffea7fb3d0 sp 0x7fffea7fb3c0
READ of size 2 at 0x62f00001c3b8 thread T0
    #0 0x4354cb in void put_epel_hv_fallback<unsigned short>(short*, long, unsigned short const*, long, int, int, int, int, short*, int) /root/src/libde265/libde265/fallback-motion.cc:348
    #1 0x52c1cc in acceleration_functions::put_hevc_epel_v(short*, long, void const*, long, int, int, int, int, short*, int) const ../libde265/acceleration.h:318
    #2 0x52ebed in void mc_chroma<unsigned char>(base_context const*, seq_parameter_set const*, int, int, int, int, short*, int, unsigned char const*, int, int, int, int) /root/src/libde265/libde265/motion.cc:264
    #3 0x51fb8b in generate_inter_prediction_samples(base_context*, slice_segment_header const*, de265_image*, int, int, int, int, int, int, int, PBMotion const*) /root/src/libde265/libde265/motion.cc:390
    #4 0x52b8f9 in decode_prediction_unit(base_context*, slice_segment_header const*, de265_image*, PBMotionCoding const&, int, int, int, int, int, int, int, int) /root/src/libde265/libde265/motion.cc:2107
    #5 0x478f4a in read_prediction_unit(thread_context*, int, int, int, int, int, int, int, int, int) /root/src/libde265/libde265/slice.cc:4137
    #6 0x47a7d3 in read_coding_unit(thread_context*, int, int, int, int) /root/src/libde265/libde265/slice.cc:4496
    #7 0x47b6fe in read_coding_quadtree(thread_context*, int, int, int, int) /root/src/libde265/libde265/slice.cc:4647
    #8 0x47b53f in read_coding_quadtree(thread_context*, int, int, int, int) /root/src/libde265/libde265/slice.cc:4630
    #9 0x47b5ac in read_coding_quadtree(thread_context*, int, int, int, int) /root/src/libde265/libde265/slice.cc:4633
    #10 0x47338a in read_coding_tree_unit(thread_context*) /root/src/libde265/libde265/slice.cc:2861
    #11 0x47beb1 in decode_substream(thread_context*, bool, bool) /root/src/libde265/libde265/slice.cc:4736
    #12 0x47db9f in read_slice_segment_data(thread_context*) /root/src/libde265/libde265/slice.cc:5049
    #13 0x40bf17 in decoder_context::decode_slice_unit_sequential(image_unit*, slice_unit*) /root/src/libde265/libde265/decctx.cc:843
    #14 0x40c6d7 in decoder_context::decode_slice_unit_parallel(image_unit*, slice_unit*) /root/src/libde265/libde265/decctx.cc:945
    #15 0x40b589 in decoder_context::decode_some(bool*) /root/src/libde265/libde265/decctx.cc:730
    #16 0x40b2f2 in decoder_context::read_slice_NAL(bitreader&, NAL_unit*, nal_header&) /root/src/libde265/libde265/decctx.cc:688
    #17 0x40dbb3 in decoder_context::decode_NAL(NAL_unit*) /root/src/libde265/libde265/decctx.cc:1230
    #18 0x40e17b in decoder_context::decode(int*) /root/src/libde265/libde265/decctx.cc:1318
    #19 0x405a61 in de265_decode /root/src/libde265/libde265/de265.cc:346
    #20 0x404972 in main /root/src/libde265/dec265/dec265.cc:764
    #21 0x7f5bb73aa82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #22 0x402b28 in _start (/opt/asan/bin/dec265+0x402b28)

0x62f00001c3b8 is located 72 bytes to the left of 50704-byte region [0x62f00001c400,0x62f000028a10)
allocated by thread T0 here:
    #0 0x7f5bb82ab076 in __interceptor_posix_memalign (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x99076)
    #1 0x43e00d in ALLOC_ALIGNED /root/src/libde265/libde265/image.cc:54
    #2 0x43e725 in de265_image_get_buffer /root/src/libde265/libde265/image.cc:132
    #3 0x440639 in de265_image::alloc_image(int, int, de265_chroma, std::shared_ptr<seq_parameter_set const>, bool, decoder_context*, long, void*, bool) /root/src/libde265/libde265/image.cc:384
    #4 0x43afa4 in decoded_picture_buffer::new_image(std::shared_ptr<seq_parameter_set const>, decoder_context*, long, void*, bool) /root/src/libde265/libde265/dpb.cc:262
    #5 0x40ee8b in decoder_context::generate_unavailable_reference_picture(seq_parameter_set const*, int, bool) /root/src/libde265/libde265/decctx.cc:1418
    #6 0x411722 in decoder_context::process_reference_picture_set(slice_segment_header*) /root/src/libde265/libde265/decctx.cc:1648
    #7 0x414cc9 in decoder_context::process_slice_segment_header(slice_segment_header*, de265_error*, long, nal_header*, void*) /root/src/libde265/libde265/decctx.cc:2066
    #8 0x40acad in decoder_context::read_slice_NAL(bitreader&, NAL_unit*, nal_header&) /root/src/libde265/libde265/decctx.cc:639
    #9 0x40dbb3 in decoder_context::decode_NAL(NAL_unit*) /root/src/libde265/libde265/decctx.cc:1230
    #10 0x40e17b in decoder_context::decode(int*) /root/src/libde265/libde265/decctx.cc:1318
    #11 0x405a61 in de265_decode /root/src/libde265/libde265/de265.cc:346
    #12 0x404972 in main /root/src/libde265/dec265/dec265.cc:764
    #13 0x7f5bb73aa82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

SUMMARY: AddressSanitizer: heap-buffer-overflow /root/src/libde265/libde265/fallback-motion.cc:348 void put_epel_hv_fallback<unsigned short>(short*, long, unsigned short const*, long, int, int, int, int, short*, int)
Shadow bytes around the buggy address:
  0x0c5e7fffb820: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c5e7fffb830: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c5e7fffb840: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c5e7fffb850: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c5e7fffb860: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c5e7fffb870: fa fa fa fa fa fa fa[fa]fa fa fa fa fa fa fa fa
  0x0c5e7fffb880: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c5e7fffb890: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c5e7fffb8a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c5e7fffb8b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c5e7fffb8c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
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
==51241==ABORTING

POC file

libde265-put_epel_hv_fallback-heap_overflow.zip
libde265-put_epel_hv_fallback-heap_overflow2.zip
password: leon.zhao.7

CREDIT

Zhao Liang, Huawei Weiran Labs

@coldtobi
Copy link

According to Debian this is CVE-2020-21594

@coldtobi
Copy link

coldtobi commented Jan 22, 2023

The poc is no longer triggering with the state in the master branch, as of today at
commit c96962c, I was bisecting to find when the poc
started to no longer trigger.

The test were commited on Debian unstable, gcc (Debian 12.2.0-14) 12.2.

Methology:

Starting point for all bisects were commit c43f2f8 (selected, as this is around the time where the CVEs were reported)

(FOR THIS ISSUE I THEN HAD TO GO BACKWARD, and used tags to narrow the search range.)

commit c43f2f8cd674bc7c78951b279ca0b1f883e1f276 (HEAD)
Author: Dirk Farin <dirk.farin@gmail.com>
Date:   Thu Dec 19 11:04:40 2019 +0100

    increase version number to v1.0.4

Bisecting is done using, so that git will report the first "good" commit.
# git bisect start --term-new=fixed --term-old=unfixed

Bisecting is done using the CMake build system, using
# cmake ../libde265 -DCMAKE_CXX_FLAGS="-fsanitize=address" -DCMAKE_BUILD_TYPE=Debug

The pocs -- taken from the upstream issues (renamed for convience, so that the link to the CVE/issue is in the filename)
The test was done with:
./dec265/dec265 -q $POC

CVE-2020-21594-issue233-libde265-put_epel_hv_fallback-heap_overflow.crash CVE-2020-21594-issue233-libde265-put_epel_hv_fallback-heap_overflow.crash2

Unfortunatly the code did not compile at the final bisect step, so the candidates for the first fixed commits are:

There are only 'skip'ped commits left to test.
The first fixed commit could be any of:
39879b749bbad5b2abc2d56ddcb6488891e3a9a0
1df1dfe3180074724e8c7dedc789910a605934ad
We cannot bisect more!

(to help github making nice links: this is 39879b7 and 1df1dfe)

git describe --contains 1df1dfe3180074724e8c7dedc789910a605934ad
v1.0.3~15
git describe --contains 39879b749bbad5b2abc2d56ddcb6488891e3a9a0
v1.0.3~16

So this seems to be fixed in v1.0.3.
This result is strange, the commit 39879b7 is dated Mon Dec 4 16:22:57 2017 +0100 and the other is just ~30 minutes younger.

Of course, there could be versions that have reintroduced a similar regression…

FWIIW, this is the asan repot I get, e.g exactly at tag v1.0.2:

=================================================================
==517523==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x62f000038379 at pc 0x7ff8661ba4cb bp 0x7ffdb6a90520 sp 0x7ffdb6a90518
READ of size 2 at 0x62f000038379 thread T0
    #0 0x7ff8661ba4ca in void put_epel_hv_fallback<unsigned short>(short*, long, unsigned short const*, long, int, int, int, int, short*, int) /home/tobi/workspace/deb/Xlts/Repositories/libde265/upstreamhacking/4eclipse/libde265/libde265/fallback-motion.cc:353
    #1 0x7ff8661acd5c in acceleration_functions::put_hevc_epel_hv(short*, long, void const*, long, int, int, int, int, short*, int) const /home/tobi/workspace/deb/Xlts/Repositories/libde265/upstreamhacking/4eclipse/libde265/libde265/acceleration.h:328
    #2 0x7ff8661af79d in void mc_chroma<unsigned char>(base_context const*, seq_parameter_set const*, int, int, int, int, short*, int, unsigned char const*, int, int, int, int) /home/tobi/workspace/deb/Xlts/Repositories/libde265/upstreamhacking/4eclipse/libde265/libde265/motion.cc:253
    #3 0x7ff8661a006d in generate_inter_prediction_samples(base_context*, slice_segment_header const*, de265_image*, int, int, int, int, int, int, int, MotionVectorSpec const*) /home/tobi/workspace/deb/Xlts/Repositories/libde265/upstreamhacking/4eclipse/libde265/libde265/motion.cc:384
    #4 0x7ff8661ac39b in decode_prediction_unit(base_context*, slice_segment_header const*, de265_image*, motion_spec const&, int, int, int, int, int, int, int, int) /home/tobi/workspace/deb/Xlts/Repositories/libde265/upstreamhacking/4eclipse/libde265/libde265/motion.cc:2080
    #5 0x7ff866176df3 in read_prediction_unit(thread_context*, int, int, int, int, int, int, int, int, int) /home/tobi/workspace/deb/Xlts/Repositories/libde265/upstreamhacking/4eclipse/libde265/libde265/slice.cc:4122
    #6 0x7ff866178823 in read_coding_unit(thread_context*, int, int, int, int) /home/tobi/workspace/deb/Xlts/Repositories/libde265/upstreamhacking/4eclipse/libde265/libde265/slice.cc:4482
    #7 0x7ff8661796e1 in read_coding_quadtree(thread_context*, int, int, int, int) /home/tobi/workspace/deb/Xlts/Repositories/libde265/upstreamhacking/4eclipse/libde265/libde265/slice.cc:4632
    #8 0x7ff86617958f in read_coding_quadtree(thread_context*, int, int, int, int) /home/tobi/workspace/deb/Xlts/Repositories/libde265/upstreamhacking/4eclipse/libde265/libde265/slice.cc:4618
    #9 0x7ff86617958f in read_coding_quadtree(thread_context*, int, int, int, int) /home/tobi/workspace/deb/Xlts/Repositories/libde265/upstreamhacking/4eclipse/libde265/libde265/slice.cc:4618
    #10 0x7ff866170ee3 in read_coding_tree_unit(thread_context*) /home/tobi/workspace/deb/Xlts/Repositories/libde265/upstreamhacking/4eclipse/libde265/libde265/slice.cc:2856
    #11 0x7ff866179ed5 in decode_substream(thread_context*, bool, bool) /home/tobi/workspace/deb/Xlts/Repositories/libde265/upstreamhacking/4eclipse/libde265/libde265/slice.cc:4721
    #12 0x7ff86617bb9b in read_slice_segment_data(thread_context*) /home/tobi/workspace/deb/Xlts/Repositories/libde265/upstreamhacking/4eclipse/libde265/libde265/slice.cc:5034
    #13 0x7ff8660f0a8d in decoder_context::decode_slice_unit_sequential(image_unit*, slice_unit*) /home/tobi/workspace/deb/Xlts/Repositories/libde265/upstreamhacking/4eclipse/libde265/libde265/decctx.cc:840
    #14 0x7ff8660f1235 in decoder_context::decode_slice_unit_parallel(image_unit*, slice_unit*) /home/tobi/workspace/deb/Xlts/Repositories/libde265/upstreamhacking/4eclipse/libde265/libde265/decctx.cc:942
    #15 0x7ff8660effb5 in decoder_context::decode_some(bool*) /home/tobi/workspace/deb/Xlts/Repositories/libde265/upstreamhacking/4eclipse/libde265/libde265/decctx.cc:727
    #16 0x7ff8660f2e54 in decoder_context::decode(int*) /home/tobi/workspace/deb/Xlts/Repositories/libde265/upstreamhacking/4eclipse/libde265/libde265/decctx.cc:1326
    #17 0x7ff8660da6b0 in de265_decode /home/tobi/workspace/deb/Xlts/Repositories/libde265/upstreamhacking/4eclipse/libde265/libde265/de265.cc:337
    #18 0x56375f3d198e in main /home/tobi/workspace/deb/Xlts/Repositories/libde265/upstreamhacking/4eclipse/libde265/dec265/dec265.cc:737
    #19 0x7ff865e46189 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #20 0x7ff865e46244 in __libc_start_main_impl ../csu/libc-start.c:381
    #21 0x56375f3cf500 in _start (/home/tobi/workspace/deb/Xlts/Repositories/libde265/upstreamhacking/4eclipse/build/dec265/dec265+0x5500)

0x62f000038379 is located 135 bytes to the left of 50696-byte region [0x62f000038400,0x62f000044a08)
allocated by thread T0 here:
    #0 0x7ff8664b7bf8 in __interceptor_memalign ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:99
    #1 0x7ff86612eca0 in de265_image_get_buffer /home/tobi/workspace/deb/Xlts/Repositories/libde265/upstreamhacking/4eclipse/libde265/libde265/image.cc:131
    #2 0x7ff866130d79 in de265_image::alloc_image(int, int, de265_chroma, seq_parameter_set const*, bool, decoder_context*, encoder_context*, long, void*, bool) /home/tobi/workspace/deb/Xlts/Repositories/libde265/upstreamhacking/4eclipse/libde265/libde265/image.cc:366
    #3 0x7ff86612a52f in decoded_picture_buffer::new_image(seq_parameter_set const*, decoder_context*, long, void*, bool) /home/tobi/workspace/deb/Xlts/Repositories/libde265/upstreamhacking/4eclipse/libde265/libde265/dpb.cc:262
    #4 0x7ff8660f3b76 in decoder_context::generate_unavailable_reference_picture(decoder_context*, seq_parameter_set const*, int, bool) /home/tobi/workspace/deb/Xlts/Repositories/libde265/upstreamhacking/4eclipse/libde265/libde265/decctx.cc:1435
    #5 0x7ff8660f660c in decoder_context::process_reference_picture_set(decoder_context*, slice_segment_header*) /home/tobi/workspace/deb/Xlts/Repositories/libde265/upstreamhacking/4eclipse/libde265/libde265/decctx.cc:1660
    #6 0x7ff8660f9db8 in decoder_context::process_slice_segment_header(decoder_context*, slice_segment_header*, de265_error*, long, nal_header*, void*) /home/tobi/workspace/deb/Xlts/Repositories/libde265/upstreamhacking/4eclipse/libde265/libde265/decctx.cc:2069
    #7 0x7ff8660ef639 in decoder_context::read_slice_NAL(bitreader&, NAL_unit*, nal_header&) /home/tobi/workspace/deb/Xlts/Repositories/libde265/upstreamhacking/4eclipse/libde265/libde265/decctx.cc:636
    #8 0x7ff8660f2775 in decoder_context::decode_NAL(NAL_unit*) /home/tobi/workspace/deb/Xlts/Repositories/libde265/upstreamhacking/4eclipse/libde265/libde265/decctx.cc:1227
    #9 0x7ff8660f2d64 in decoder_context::decode(int*) /home/tobi/workspace/deb/Xlts/Repositories/libde265/upstreamhacking/4eclipse/libde265/libde265/decctx.cc:1315
    #10 0x7ff8660da6b0 in de265_decode /home/tobi/workspace/deb/Xlts/Repositories/libde265/upstreamhacking/4eclipse/libde265/libde265/de265.cc:337
    #11 0x56375f3d198e in main /home/tobi/workspace/deb/Xlts/Repositories/libde265/upstreamhacking/4eclipse/libde265/dec265/dec265.cc:737
    #12 0x7ff865e46189 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/tobi/workspace/deb/Xlts/Repositories/libde265/upstreamhacking/4eclipse/libde265/libde265/fallback-motion.cc:353 in void put_epel_hv_fallback<unsigned short>(short*, long, unsigned short const*, long, int, int, int, int, short*, int)
Shadow bytes around the buggy address:
  0x0c5e7ffff010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c5e7ffff020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c5e7ffff030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c5e7ffff040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c5e7ffff050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c5e7ffff060: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa[fa]
  0x0c5e7ffff070: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c5e7ffff080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c5e7ffff090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c5e7ffff0a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c5e7ffff0b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
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
==517523==ABORTING

@attritionorg
Copy link

@coldtobi Thank you for that analysis, very helpful!

@farindk
Copy link
Contributor

farindk commented Jan 24, 2023

Thank you @leonzhao7 and @coldtobi

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