After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 737412 - h264: playing a certain broken stream causes a crash (stack corruption caused by codec parser)
h264: playing a certain broken stream causes a crash (stack corruption caused...
Status: RESOLVED FIXED
Product: GStreamer
Classification: Platform
Component: gst-plugins-bad
1.4.3
Other Linux
: Normal critical
: 1.5.1
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on:
Blocks:
 
 
Reported: 2014-09-26 09:37 UTC by André Draszik
Modified: 2015-01-14 11:46 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
codecparser: h264: smash stack corruption bug (1.95 KB, patch)
2014-09-26 09:37 UTC, André Draszik
none Details | Review
fix stack smashing (2.96 KB, patch)
2015-01-12 17:32 UTC, Vincent Penquerc'h
committed Details | Review

Description André Draszik 2014-09-26 09:37:05 UTC
Created attachment 287135 [details] [review]
codecparser: h264: smash stack corruption bug

Playing back a certain broken stream, causes the following crash on x86_64:

  • #0 __GI_raise
    at ../nptl/sysdeps/unix/sysv/linux/raise.c line 56
  • #1 __GI_abort
    at abort.c line 89
  • #2 __libc_message
    at ../sysdeps/posix/libc_fatal.c line 175
  • #3 __GI___fortify_fail
    at fortify_fail.c line 37
  • #4 __stack_chk_fail
    at stack_chk_fail.c line 28
  • #5 gst_h264_parse_process_nal
    at /home/ad/devel/4646/gst-plugins-bad/gst/videoparsers/gsth264parse.c line 715
  • #6 ??
  • #0 slice_parse_ref_pic_list_modification_1
    at /usr/src/debug/gst-plugins-bad/1.4+gitAUTOINC+ae7db18a0b-r0/git/gst-libs/gst/codecparsers/gsth264parser.c line 539
  • #1 slice_parse_ref_pic_list_modification
    at /usr/src/debug/gst-plugins-bad/1.4+gitAUTOINC+ae7db18a0b-r0/git/gst-libs/gst/codecparsers/gsth264parser.c line 546
  • #2 gst_h264_parser_parse_slice_hdr
    at /usr/src/debug/gst-plugins-bad/1.4+gitAUTOINC+ae7db18a0b-r0/git/gst-libs/gst/codecparsers/gsth264parser.c line 1771
  • #3 gst_h264_parse_process_nal
    at /usr/src/debug/gst-plugins-bad/1.4+gitAUTOINC+ae7db18a0b-r0/git/gst/videoparsers/gsth264parse.c line 657
  • #4 ??

It's OK in frame 2, but not OK in the caller frame 3. This means, that gst_h264_parse_process_nal() (or functions it calls itself) must have corrupted it.
One obvious culprit would e.g. be somebody who is overwriting the stack object 'GstH264SliceHdr slice' (from gsth264parse.c gst_h264_parse_process_nal() around line 655).

Further investigation shows that GstH264SliceHdr::ref_pic_list_modification_l0 and GstH264SliceHdr::ref_pic_list_modification_l1 are arrays with 32 entries each. The array is written to by slice_parse_ref_pic_list_modification_1() and indeed, it happens a lot that the while(1) in that function can end up writing beyond one of the two above arrays, causing stack corruption, and thus the crash. I have seen it writing into entries > 200, whereas there is space for 32 entries only.

I am not sure if this means there is a bug in the h264 parser, where it doesn't behave as the spec mandates, or we have a corrupt stream, but attached is a fix to prevent it from writing into memory that it doesn't own.
Comment 1 André Draszik 2014-09-26 09:38:52 UTC
The stack traces got a bit garbled - for x68_64, we get:
  • #0 __GI_raise
    at ../nptl/sysdeps/unix/sysv/linux/raise.c line 56
  • #1 __GI_abort
    at abort.c line 89
  • #2 __libc_message
    at ../sysdeps/posix/libc_fatal.c line 175
  • #3 __GI___fortify_fail
    at fortify_fail.c line 37
  • #4 __stack_chk_fail
    at stack_chk_fail.c line 28
  • #5 gst_h264_parse_process_nal
    at /home/adraszik/devel/4646/gst-plugins-bad/gst/videoparsers/gsth264parse.c line 715
  • #6 ??

Comment 2 André Draszik 2014-09-26 09:39:31 UTC
Using a well placed breakpoint, we can also see that the pointer to nalu becomes corrupted in the calling function:

  • #0 slice_parse_ref_pic_list_modification_1
    at /usr/src/debug/gst-plugins-bad/1.4+gitAUTOINC+ae7db18a0b-r0/git/gst-libs/gst/codecparsers/gsth264parser.c line 539
  • #1 slice_parse_ref_pic_list_modification
    at /usr/src/debug/gst-plugins-bad/1.4+gitAUTOINC+ae7db18a0b-r0/git/gst-libs/gst/codecparsers/gsth264parser.c line 546
  • #2 gst_h264_parser_parse_slice_hdr
    at /usr/src/debug/gst-plugins-bad/1.4+gitAUTOINC+ae7db18a0b-r0/git/gst-libs/gst/codecparsers/gsth264parser.c line 1771
  • #3 gst_h264_parse_process_nal
    at /usr/src/debug/gst-plugins-bad/1.4+gitAUTOINC+ae7db18a0b-r0/git/gst/videoparsers/gsth264parse.c line 657
  • #4 ??

Comment 3 Tim-Philipp Müller 2014-09-26 09:49:53 UTC
Could you make a sample available that reproduces this?
Comment 4 André Draszik 2014-09-29 10:57:41 UTC
Sorry, it took so long. I've put it there: https://drive.google.com/file/d/0BwcM3sY1O09ASXUyeTBnNW9Ddk0/edit?usp=sharing
Comment 5 André Draszik 2014-09-29 10:58:32 UTC
It happens in several positions in this file, the first is at around 44 seconds.
Comment 6 Felix Schwarz 2014-09-29 11:16:03 UTC
seems like the bug is a bit older. I can reproduce the problem with a stock gstreamer 1.2.4 from Fedora 20 with Totem (crashes around 1:44, "stack smashing detected")
Comment 7 André Draszik 2014-09-29 16:14:12 UTC
Ah, yes, I forgot to mention that 1.2 can't play it properly either. And the stack smashing detection does not detect all the cases of stack corruption, some cases are missed (of course). Using e.g. a more verbose version of my patch you should be able to see that corruption can happen silently.
Comment 8 Vincent Penquerc'h 2015-01-12 17:32:51 UTC
Created attachment 294366 [details] [review]
fix stack smashing

This patch extends yours to fix the extra accesses you pointed to, and fixes an apparent discrepancy with the spec, which I found out when I tracked it down to see what was the expected way to deal with too many entries (turns out it doesn't say).
Comment 9 Sebastian Dröge (slomo) 2015-01-13 10:09:46 UTC
Review of attachment 294366 [details] [review]:

Looks good except for one thing, please push after fixing that :)

::: gst-libs/gst/codecparsers/gsth264parser.c
@@ +659,3 @@
   } else {
     entries = slice->ref_pic_list_modification_l1;
+    max_entries = G_N_ELEMENTS (slice->ref_pic_list_modification_l0);

This should be _l1
Comment 10 Vincent Penquerc'h 2015-01-14 11:45:26 UTC
Doh. I'll have to think hard to top that one :D

commit c73a5e0c545babe50130e7042be8cf92828afa18
Author: Vincent Penquerc'h <vincent.penquerch@collabora.co.uk>
Date:   Mon Jan 12 17:24:52 2015 +0000

    h264parser: fix stack smashing
    
    Ensure that we do not trust the bitstream when filling a table
    with a fixed max size.
    Additionally, the code was not quite matching what the spec says:
    - a value of 3 broke from the loop before adding an entry
    - an unhandled value did not add an entry
    The reference algorithm does these things differently (7.3.3.1
    in ITU-T Rec. H.264 (05/2003)).
    
    This plays (apparently correctly) the original repro file, with
    no stack smashing.
    
    Based on a patch and bug report by André Draszik <git@andred.net>