FFmpeg buffer overflow vulnerability

2013.09.17
Credit: Reno Robert
Risk: High
Local: No
Remote: Yes
CWE: CWE-noinfo


CVSS Base Score: 5/10
Impact Subscore: 2.9/10
Exploitability Subscore: 10/10
Exploit range: Remote
Attack complexity: Low
Authentication: No required
Confidentiality impact: None
Integrity impact: None
Availability impact: Partial

The H.264 specification includes two types of parameter sets: sequence parameter set and picture parameter set. An active sequence parameter set remains unchanged throughout a coded video sequence, and an active picture parameter set remains unchanged within a coded picture. The sequence and picture parameter set structures contain information such as picture size, optional coding modes employed, and macroblock to slice group map. To be able to change picture parameters (such as the picture size) without having to transmit parameter set updates synchronously to the slice packet stream, the encoder and decoder can maintain a list of more than one sequence and picture parameter set. Each slice header contains a codeword that indicates the sequence and picture parameter set to be used. => 0x528da4 <put_image+68>: call QWORD PTR [rax+0x18] RAX: 0x4444444444444444 ('DDDDDDDD') if(video_out->control(VOCTRL_DRAW_IMAGE,mpi)==VO_TRUE) return 1; gdb-peda$ bt #0 0x0000000000528da4 in put_image (vf=0x17e82b0, mpi=0x1dc4af0, pts=604.16666666666663) at libmpcodecs/vf_vo.c:168 #1 0x00000000004f97eb in filter_video (sh_video=<optimized out>, frame=0x1dc4af0, pts=<optimized out>) at libmpcodecs/dec_video.c:479 #2 0x000000000048ba80 in update_video (blit_frame=0x7fffffffe0e8) at mplayer.c:2487 #3 0x000000000048ff78 in main (argc=<optimized out>, argv=) at mplayer.c:3765 #4 0x00000038b7a1ec5d in __libc_start_main () from /lib64/libc.so.6 #5 0x0000000000482185 in _start () libavcodec/h264.c libavcodec/h264.h libavcodec/h264_ps.c diff --git a/libavcodec/h264.c b/libavcodec/h264.c index 6e62c0d..059d65b 100644 (file) --- a/libavcodec/h264.c +++ b/libavcodec/h264.c @@ -2847,6 +2847,53 @@ int ff_h264_get_profile(SPS *sps) return profile; } +static int h264_set_parameter_from_sps(H264Context *h) +{ + MpegEncContext *s = &h->s; + + if (s->flags & CODEC_FLAG_LOW_DELAY || + (h->sps.bitstream_restriction_flag && + !h->sps.num_reorder_frames)) { + if (s->avctx->has_b_frames > 1 || h->delayed_pic[0]) + av_log(h->s.avctx, AV_LOG_WARNING, "Delayed frames seen. " + "Reenabling low delay requires a codec flush.\n"); + else + s->low_delay = 1; + } + + if (s->avctx->has_b_frames < 2) + s->avctx->has_b_frames = !s->low_delay; + + if (s->avctx->bits_per_raw_sample != h->sps.bit_depth_luma || + h->cur_chroma_format_idc != h->sps.chroma_format_idc) { + if (s->avctx->codec && + s->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU && + (h->sps.bit_depth_luma != 8 || h->sps.chroma_format_idc > 1)) { + av_log(s->avctx, AV_LOG_ERROR, + "VDPAU decoding does not support video colorspace.\n"); + return AVERROR_INVALIDDATA; + } + if (h->sps.bit_depth_luma >= 8 && h->sps.bit_depth_luma <= 10 && + (h->sps.bit_depth_luma != 9 || !CHROMA422)) { + s->avctx->bits_per_raw_sample = h->sps.bit_depth_luma; + h->cur_chroma_format_idc = h->sps.chroma_format_idc; + h->pixel_shift = h->sps.bit_depth_luma > 8; + + ff_h264dsp_init(&h->h264dsp, h->sps.bit_depth_luma, + h->sps.chroma_format_idc); + ff_h264_pred_init(&h->hpc, s->codec_id, h->sps.bit_depth_luma, + h->sps.chroma_format_idc); + s->dsp.dct_bits = h->sps.bit_depth_luma > 8 ? 32 : 16; + ff_dsputil_init(&s->dsp, s->avctx); + } else { + av_log(s->avctx, AV_LOG_ERROR, "Unsupported bit depth: %d\n", + h->sps.bit_depth_luma); + return AVERROR_INVALIDDATA; + } + } + return 0; +} + /** * Decode a slice header. * This will also call ff_MPV_common_init() and frame_start() as needed. @@ -2863,7 +2910,7 @@ static int decode_slice_header(H264Context *h, H264Context *h0) MpegEncContext *const s0 = &h0->s; unsigned int first_mb_in_slice; unsigned int pps_id; - int num_ref_idx_active_override_flag; + int num_ref_idx_active_override_flag, ret; unsigned int slice_type, tmp, i, j; int default_ref_list_done = 0; int last_pic_structure, last_pic_dropable; @@ -2940,7 +2987,14 @@ static int decode_slice_header(H264Context *h, H264Context *h0) h->pps.sps_id); return -1; } - h->sps = *h0->sps_buffers[h->pps.sps_id]; + + if (h->pps.sps_id != h->current_sps_id || + h0->sps_buffers[h->pps.sps_id]->new) { + h0->sps_buffers[h->pps.sps_id]->new = 0; + + h->current_sps_id = h->pps.sps_id; + h->sps = *h0->sps_buffers[h->pps.sps_id]; + } s->avctx->profile = ff_h264_get_profile(&h->sps); s->avctx->level = h->sps.level_idc; @@ -2989,24 +3043,8 @@ static int decode_slice_header(H264Context *h, H264Context *h0) s->avctx->sample_aspect_ratio = h->sps.sar; av_assert0(s->avctx->sample_aspect_ratio.den); - if (s->avctx->bits_per_raw_sample != h->sps.bit_depth_luma || - h->cur_chroma_format_idc != h->sps.chroma_format_idc) { - if (h->sps.bit_depth_luma >= 8 && h->sps.bit_depth_luma <= 10 && - (h->sps.bit_depth_luma != 9 || !CHROMA422)) { - s->avctx->bits_per_raw_sample = h->sps.bit_depth_luma; - h->cur_chroma_format_idc = h->sps.chroma_format_idc; - h->pixel_shift = h->sps.bit_depth_luma > 8; - - ff_h264dsp_init(&h->h264dsp, h->sps.bit_depth_luma, h->sps.chroma_format_idc); - ff_h264_pred_init(&h->hpc, s->codec_id, h->sps.bit_depth_luma, h->sps.chroma_format_idc); - s->dsp.dct_bits = h->sps.bit_depth_luma > 8 ? 32 : 16; - ff_dsputil_init(&s->dsp, s->avctx); - } else { - av_log(s->avctx, AV_LOG_ERROR, "Unsupported bit depth: %d chroma_idc: %d\n", - h->sps.bit_depth_luma, h->sps.chroma_format_idc); - return -1; - } - } + if ((ret = h264_set_parameter_from_sps(h)) < 0) + return ret; if (h->sps.video_signal_type_present_flag) { s->avctx->color_range = h->sps.full_range>0 ? AVCOL_RANGE_JPEG @@ -4435,6 +4473,7 @@ again: ff_h264_decode_seq_parameter_set(h); } + if (s->flags & CODEC_FLAG_LOW_DELAY || (h->sps.bitstream_restriction_flag && !h->sps.num_reorder_frames)) diff --git a/libavcodec/h264.h b/libavcodec/h264.h index a27f82f..22f8100 100644 (file) --- a/libavcodec/h264.h +++ b/libavcodec/h264.h @@ -206,6 +206,7 @@ typedef struct SPS { int bit_depth_chroma; ///< bit_depth_chroma_minus8 + 8 int residual_color_transform_flag; ///< residual_colour_transform_flag int constraint_set_flags; ///< constraint_set[0-3]_flag + int new; ///< flag to keep track if the decoder context needs re-init due to changed SPS } SPS; /** @@ -332,6 +333,7 @@ typedef struct H264Context { int emu_edge_width; int emu_edge_height; + unsigned current_sps_id; ///< id of the current SPS SPS sps; ///< current sps /** diff --git a/libavcodec/h264_ps.c b/libavcodec/h264_ps.c index 261e2d2..bf07cbb 100644 (file) --- a/libavcodec/h264_ps.c +++ b/libavcodec/h264_ps.c @@ -478,10 +478,13 @@ int ff_h264_decode_seq_parameter_set(H264Context *h){ sps->bit_depth_luma ); } + sps->new = 1; av_free(h->sps_buffers[sps_id]); - h->sps_buffers[sps_id]= sps; - h->sps = *sps; + h->sps_buffers[sps_id] = sps; + h->sps = *sps; + h->current_sps_id = sps_id; + return 0; fail: av_free(sps);

References:

http://seclists.org/oss-sec/2013/q3/615
http://v0ids3curity.blogspot.in/2013/09/a-ffmpeg-0113-memory-corruption-bug.html


Vote for this issue:
50%
50%


 

Thanks for you vote!


 

Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.


(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2024, cxsecurity.com

 

Back to Top