avformat: Add format_whitelist

This allows restricting demuxers to a list of needed ones for improved security
Note, some demuxers themselfs open other demuxers, these are only restricted if
AVOptions are forwarded to them. Please check that your code does that.

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
Michael Niedermayer 2014-09-30 23:25:39 +02:00
parent 5c8eb16769
commit 057ea2a982
3 changed files with 35 additions and 0 deletions

View File

@ -1584,6 +1584,22 @@ typedef struct AVFormatContext {
*/ */
int format_probesize; int format_probesize;
/**
* ',' seperated list of allowed decoders.
* If NULL then all are allowed
* - encoding: unused
* - decoding: set by user through AVOptions (NO direct access)
*/
char *codec_whitelist;
/**
* ',' seperated list of allowed demuxers.
* If NULL then all are allowed
* - encoding: unused
* - decoding: set by user through AVOptions (NO direct access)
*/
char *format_whitelist;
/***************************************************************** /*****************************************************************
* All fields below this line are not part of the public API. They * All fields below this line are not part of the public API. They
* may not be used outside of libavformat and can be changed and * may not be used outside of libavformat and can be changed and

View File

@ -97,6 +97,8 @@ static const AVOption avformat_options[] = {
{"experimental", "allow non-standardized experimental variants", 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_EXPERIMENTAL }, INT_MIN, INT_MAX, D|E, "strict"}, {"experimental", "allow non-standardized experimental variants", 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_EXPERIMENTAL }, INT_MIN, INT_MAX, D|E, "strict"},
{"max_ts_probe", "maximum number of packets to read while waiting for the first timestamp", OFFSET(max_ts_probe), AV_OPT_TYPE_INT, { .i64 = 50 }, 0, INT_MAX, D }, {"max_ts_probe", "maximum number of packets to read while waiting for the first timestamp", OFFSET(max_ts_probe), AV_OPT_TYPE_INT, { .i64 = 50 }, 0, INT_MAX, D },
{"dump_separator", "set information dump field separator", OFFSET(dump_separator), AV_OPT_TYPE_STRING, {.str = ", "}, CHAR_MIN, CHAR_MAX, D|E}, {"dump_separator", "set information dump field separator", OFFSET(dump_separator), AV_OPT_TYPE_STRING, {.str = ", "}, CHAR_MIN, CHAR_MAX, D|E},
{"codec_whitelist", "List of decoders that are allowed to be used", OFFSET(codec_whitelist), AV_OPT_TYPE_STRING, { .str = NULL }, CHAR_MIN, CHAR_MAX, D },
{"format_whitelist", "List of demuxers that are allowed to be used", OFFSET(format_whitelist), AV_OPT_TYPE_STRING, { .str = NULL }, CHAR_MIN, CHAR_MAX, D },
{NULL}, {NULL},
}; };

View File

@ -291,6 +291,11 @@ static int set_codec_from_probe_data(AVFormatContext *s, AVStream *st,
int av_demuxer_open(AVFormatContext *ic) { int av_demuxer_open(AVFormatContext *ic) {
int err; int err;
if (ic->format_whitelist && av_match_list(ic->iformat->name, ic->format_whitelist, ',') <= 0) {
av_log(ic, AV_LOG_ERROR, "Format not on whitelist\n");
return AVERROR(EINVAL);
}
if (ic->iformat->read_header) { if (ic->iformat->read_header) {
err = ic->iformat->read_header(ic); err = ic->iformat->read_header(ic);
if (err < 0) if (err < 0)
@ -402,6 +407,13 @@ int avformat_open_input(AVFormatContext **ps, const char *filename,
if ((ret = init_input(s, filename, &tmp)) < 0) if ((ret = init_input(s, filename, &tmp)) < 0)
goto fail; goto fail;
s->probe_score = ret; s->probe_score = ret;
if (s->format_whitelist && av_match_list(s->iformat->name, s->format_whitelist, ',') <= 0) {
av_log(s, AV_LOG_ERROR, "Format not on whitelist\n");
ret = AVERROR(EINVAL);
goto fail;
}
avio_skip(s->pb, s->skip_initial_bytes); avio_skip(s->pb, s->skip_initial_bytes);
/* Check filename in case an image number is expected. */ /* Check filename in case an image number is expected. */
@ -2576,6 +2588,8 @@ static int try_decode_frame(AVFormatContext *s, AVStream *st, AVPacket *avpkt,
/* Force thread count to 1 since the H.264 decoder will not extract /* Force thread count to 1 since the H.264 decoder will not extract
* SPS and PPS to extradata during multi-threaded decoding. */ * SPS and PPS to extradata during multi-threaded decoding. */
av_dict_set(options ? options : &thread_opt, "threads", "1", 0); av_dict_set(options ? options : &thread_opt, "threads", "1", 0);
if (s->codec_whitelist)
av_dict_set(options ? options : &thread_opt, "codec_whitelist", s->codec_whitelist, 0);
ret = avcodec_open2(st->codec, codec, options ? options : &thread_opt); ret = avcodec_open2(st->codec, codec, options ? options : &thread_opt);
if (!options) if (!options)
av_dict_free(&thread_opt); av_dict_free(&thread_opt);
@ -3009,6 +3023,9 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
* SPS and PPS to extradata during multi-threaded decoding. */ * SPS and PPS to extradata during multi-threaded decoding. */
av_dict_set(options ? &options[i] : &thread_opt, "threads", "1", 0); av_dict_set(options ? &options[i] : &thread_opt, "threads", "1", 0);
if (ic->codec_whitelist)
av_dict_set(options ? &options[i] : &thread_opt, "codec_whitelist", ic->codec_whitelist, 0);
/* Ensure that subtitle_header is properly set. */ /* Ensure that subtitle_header is properly set. */
if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE
&& codec && !st->codec->codec) { && codec && !st->codec->codec) {