parsebin: use chain after free
A use-after-free bug of parsebin occurs if playbin3 is set to NONE a few seconds after it is set to PLAYING. I'm using 1.16 on Android to play an mp4 video.
The following log shows that connect_pad
executed by thread 0x7f5a5430 (tid 3036) try to lock the chain 0x808fed90 after the chain 0x808fed90 was freed by thread 0x81a24520 (tid 2245).
06-28 04:54:37.004 2075 3036 D GStreamer+parsebin: 0:05:46.479062582 0x7f5a5430 ../gst/playback/gstparsebin.c:2855:gst_parse_chain_new:<parsebin40> Creating new chain 0x808fed90 with parent group 0x8ff272b0
06-28 04:54:37.010 2075 2245 V GStreamer+parsebin: 0:05:46.484662874 0x81a24520 ../gst/playback/gstparsebin.c:2678:gst_parse_chain_free_internal:<parsebin40> locking chain 0x808fed90 from thread 0x81a24520
06-28 04:54:37.010 2075 2245 V GStreamer+parsebin: 0:05:46.484768749 0x81a24520 ../gst/playback/gstparsebin.c:2678:gst_parse_chain_free_internal:<parsebin40> locked chain 0x808fed90 from thread 0x81a24520
06-28 04:54:37.010 2075 2245 D GStreamer+parsebin: 0:05:46.484866457 0x81a24520 ../gst/playback/gstparsebin.c:2681:gst_parse_chain_free_internal:<parsebin40> Hiding chain 0x808fed90
06-28 04:54:37.010 2075 2245 D GStreamer+parsebin: 0:05:46.484979624 0x81a24520 ../gst/playback/gstparsebin.c:2811:gst_parse_chain_free_internal:<parsebin40> Hidden chain 0x808fed90
06-28 04:54:37.010 2075 2245 V GStreamer+parsebin: 0:05:46.485093957 0x81a24520 ../gst/playback/gstparsebin.c:2812:gst_parse_chain_free_internal:<parsebin40> unlocking chain 0x808fed90 from thread 0x81a24520
06-28 04:54:37.018 2075 3036 D GStreamer+parsebin: 0:05:46.492812332 0x7f5a5430 ../gst/playback/gstparsebin.c:1751:connect_pad:<parsebin40> pad qtdemux37:video_0 , chain:0x808fed90, 2 factories, caps video/x-h264, stream-format=(string)avc, alignment=(string)au, level=(string)3, profile=(string)high, codec_data=(buffer)0164001effe1001c6764001eacd940b43dbff0020001b100000303e90000ea600f162d9601000668ebe3cb22c0, width=(int)720, height=(int)480, framerate=(fraction)30000/1001, pixel-aspect-ratio=(fraction)32/27
06-28 04:54:37.019 2075 2245 V GStreamer+parsebin: 0:05:46.494063874 0x81a24520 ../gst/playback/gstparsebin.c:2678:gst_parse_chain_free_internal:<parsebin40> locking chain 0x808fed90 from thread 0x81a24520
06-28 04:54:37.019 2075 2245 V GStreamer+parsebin: 0:05:46.494214082 0x81a24520 ../gst/playback/gstparsebin.c:2678:gst_parse_chain_free_internal:<parsebin40> locked chain 0x808fed90 from thread 0x81a24520
06-28 04:54:37.020 2075 2245 D GStreamer+parsebin: 0:05:46.494361957 0x81a24520 ../gst/playback/gstparsebin.c:2681:gst_parse_chain_free_internal:<parsebin40> Freeing chain 0x808fed90
06-28 04:54:37.020 2075 2245 D GStreamer+parsebin: 0:05:46.494531416 0x81a24520 ../gst/playback/gstparsebin.c:2811:gst_parse_chain_free_internal:<parsebin40> Freed chain 0x808fed90
06-28 04:54:37.020 2075 2245 V GStreamer+parsebin: 0:05:46.494663249 0x81a24520 ../gst/playback/gstparsebin.c:2812:gst_parse_chain_free_internal:<parsebin40> unlocking chain 0x808fed90 from thread 0x81a24520
06-28 04:54:37.023 2075 3036 V GStreamer+parsebin: 0:05:46.498147791 0x7f5a5430 ../gst/playback/gstparsebin.c:1839:connect_pad locking chain 0x808fed90 from thread 0x7f5a5430
The following are the backtraces of thread 0x7f5a5430 (tid 3036) and thread 0x81a24520 (tid 2245). Where should I put CHAIN_MUTEX_LOCK(chain)
to fix this issue? Attached file is a more complete log after function pad_added_cb
was called, which results in the connect_pad
call.use-after-free.log
Thread 0x7f5a5430
Thread 106 (Thread 2075.3036):
#0 0xb18173f4 in syscall () from target:/system/lib/libc.so
#1 0xb1847560 in __pthread_mutex_lock_with_timeout(pthread_mutex_internal_t*, bool, timespec const*) () from target:/system/lib/libc.so
#2 0x837fb26a in g_mutex_lock (mutex=0x808fed98) at ../glib/gthread-posix.c:214
#3 0x835231ba in connect_pad (parsebin=<optimized out>, src=<optimized out>, parsepad=<optimized out>, pad=<optimized out>, caps=<optimized out>, factories=<optimized out>, chain=<optimized out>, deadend_details=<optimized out>) at ../gst/playback/gstparsebin.c:1839
#4 analyze_new_pad (parsebin=<optimized out>, src=<optimized out>, pad=0x80868e40, caps=0x80830918, chain=<optimized out>) at ../gst/playback/gstparsebin.c:1498
#5 0x8352586e in pad_added_cb (element=0x8e2c5ad0, pad=<optimized out>, chain=<optimized out>) at ../gst/playback/gstparsebin.c:2459
#6 0x837b0acc in ffi_call_SYSV () from target:/data/app/com.karaokeui-2/lib/arm/libgstreamer_android.so
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
Thread 96 (Thread 2075.2245):
#0 0xb18173f4 in syscall () from target:/system/lib/libc.so
#1 0xb1847560 in __pthread_mutex_lock_with_timeout(pthread_mutex_internal_t*, bool, timespec const*) () from target:/system/lib/libc.so
#2 0x83742ae8 in gst_pad_stop_task (pad=0x80026ea8) at ../gst/gstpad.c:6306
#3 0x8373970a in activate_mode_internal (pad=0x80026ea8, parent=0x8e2c5ad0, mode=<optimized out>, active=<optimized out>) at ../gst/gstpad.c:1217
#4 0x83739250 in gst_pad_set_active (pad=0x80026ea8, active=0) at ../gst/gstpad.c:1115
#5 0x83727854 in activate_pads (vpad=<optimized out>, ret=0x8d80a148, active=0x8d80a198) at ../gst/gstelement.c:3062
#6 0x837324da in gst_iterator_fold (it=0x8b4e74a8, func=0x8372783d <activate_pads>, ret=0x8d80a148, user_data=0x8d80a198) at ../gst/gstiterator.c:617
#7 0x8372780a in iterator_activate_fold_with_resync (iter=0x8b4e74a8, func=<optimized out>, user_data=0x8d80a198) at ../gst/gstelement.c:3086
#8 0x83727652 in gst_element_pads_activate (element=0x8e2c5ad0, active=<optimized out>) at ../gst/gstelement.c:3131
#9 0x837261d2 in gst_element_change_state_func (element=0x8e2c5ad0, transition=GST_STATE_CHANGE_PAUSED_TO_READY) at ../gst/gstelement.c:3196
#10 0x8347057c in gst_qtdemux_change_state (element=0x8e2c5ad0, transition=GST_STATE_CHANGE_PAUSED_TO_READY) at ../gst/isomp4/qtdemux.c:2761
#11 0x83724d12 in gst_element_change_state (element=0x8e2c5ad0, transition=<optimized out>) at ../gst/gstelement.c:2974
#12 0x837265d4 in gst_element_set_state_func (element=0x8e2c5ad0, state=GST_STATE_NULL) at ../gst/gstelement.c:2928
#13 0x835277ac in gst_parse_chain_free_internal (chain=0x8b4e76d8, hide=<optimized out>) at ../gst/playback/gstparsebin.c:2817
#14 0x8352915c in gst_parse_chain_free (chain=0x8b4e76d8) at ../gst/playback/gstparsebin.c:2838
#15 gst_parse_bin_change_state (element=0x7fa75e10, transition=<optimized out>) at ../gst/playback/gstparsebin.c:4342
#16 0x83724d12 in gst_element_change_state (element=0x7fa75e10, transition=<optimized out>) at ../gst/gstelement.c:2974
#17 0x837265d4 in gst_element_set_state_func (element=0x7fa75e10, state=GST_STATE_READY) at ../gst/gstelement.c:2928
#18 0x837049f6 in gst_bin_element_set_state (bin=<optimized out>, element=<optimized out>, base_time=<optimized out>, current=<optimized out>, next=<optimized out>, start_time=<optimized out>) at ../gst/gstbin.c:2627
#19 gst_bin_change_state_func (element=<optimized out>, transition=GST_STATE_CHANGE_PAUSED_TO_READY) at ../gst/gstbin.c:2969
#20 0x8350fa2a in gst_decodebin3_change_state (element=0x8e53f338, transition=<optimized out>) at ../gst/playback/gstdecodebin3.c:2876
#21 0x83724d12 in gst_element_change_state (element=0x8e53f338, transition=<optimized out>) at ../gst/gstelement.c:2974
#22 0x837265d4 in gst_element_set_state_func (element=0x8e53f338, state=GST_STATE_READY) at ../gst/gstelement.c:2928
#23 0x837049f6 in gst_bin_element_set_state (bin=<optimized out>, element=<optimized out>, base_time=<optimized out>, current=<optimized out>, next=<optimized out>, start_time=<optimized out>) at ../gst/gstbin.c:2627
#24 gst_bin_change_state_func (element=<optimized out>, transition=GST_STATE_CHANGE_PAUSED_TO_READY) at ../gst/gstbin.c:2969
#25 0x8351beb6 in gst_uri_decode_bin3_change_state (element=0x8e53f1a0, transition=GST_STATE_CHANGE_PAUSED_TO_READY) at ../gst/playback/gsturidecodebin3.c:1054
#26 0x83724d12 in gst_element_change_state (element=0x8e53f1a0, transition=<optimized out>) at ../gst/gstelement.c:2974
#27 0x837265d4 in gst_element_set_state_func (element=0x8e53f1a0, state=GST_STATE_READY) at ../gst/gstelement.c:2928
#28 0x837049f6 in gst_bin_element_set_state (bin=<optimized out>, element=<optimized out>, base_time=<optimized out>, current=<optimized out>, next=<optimized out>, start_time=<optimized out>) at ../gst/gstbin.c:2627
#29 gst_bin_change_state_func (element=<optimized out>, transition=GST_STATE_CHANGE_PAUSED_TO_READY) at ../gst/gstbin.c:2969
#30 0x834e9740 in gst_play_bin3_change_state (element=0x8b4e2040, transition=GST_STATE_CHANGE_PAUSED_TO_READY) at ../gst/playback/gstplaybin3.c:4944
#31 0x83724d12 in gst_element_change_state (element=0x8b4e2040, transition=<optimized out>) at ../gst/gstelement.c:2974
#32 0x837265d4 in gst_element_set_state_func (element=0x8b4e2040, state=GST_STATE_NULL) at ../gst/gstelement.c:2928
#33 0x88125e30 in set_uri (player=0x81a0c800, uri=0x7cbca960 "file:///data/user/0/com.karaokeui/files/broadcast/20201030_3.mp4") at jni/inul.c:780
#34 0x8812a550 in dispatch (action=0x7cb83380, player=0x81a0c800) at jni/actions.c:11
#35 0x837e51a8 in g_thread_pool_thread_proxy (data=0x82461a68) at ../glib/gthreadpool.c:307
#36 0x837e4600 in g_thread_proxy (data=0x81a24520) at ../glib/gthread.c:784
#37 0xb1846d34 in __pthread_start(void*) () from target:/system/lib/libc.so
#38 0xb1819aae in __start_thread () from target:/system/lib/libc.so
#39 0x00000000 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)