diff options
author | Narpat Mali <narpat.mali@windriver.com> | 2023-04-28 16:58:32 +0000 |
---|---|---|
committer | Steve Sakoman <steve@sakoman.com> | 2023-05-10 04:19:56 -1000 |
commit | 813d4715e4d37ef22a8e8f1275e248bed23b4779 (patch) | |
tree | a82ad7c21fd066480474cc971ee7b8e313013ce3 | |
parent | 75239ddd8d67c00139c6e88c1c2a790b471b12c5 (diff) | |
download | poky-813d4715e4d37ef22a8e8f1275e248bed23b4779.tar.gz |
ffmpeg: fix for CVE-2022-48434
libavcodec/pthread_frame.c in FFmpeg before 5.1.2, as used in VLC and
other products, leaves stale hwaccel state in worker threads, which
allows attackers to trigger a use-after-free and execute arbitrary
code in some circumstances (e.g., hardware re-initialization upon a
mid-video SPS change when Direct3D11 is used).
(From OE-Core rev: 392f984ffd95bcd3ce4c364b40425e7808ca7719)
Signed-off-by: Narpat Mali <narpat.mali@windriver.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
-rw-r--r-- | meta/recipes-multimedia/ffmpeg/ffmpeg/CVE-2022-48434.patch | 130 | ||||
-rw-r--r-- | meta/recipes-multimedia/ffmpeg/ffmpeg_5.0.1.bb | 3 |
2 files changed, 132 insertions, 1 deletions
diff --git a/meta/recipes-multimedia/ffmpeg/ffmpeg/CVE-2022-48434.patch b/meta/recipes-multimedia/ffmpeg/ffmpeg/CVE-2022-48434.patch new file mode 100644 index 0000000000..3cd374dc39 --- /dev/null +++ b/meta/recipes-multimedia/ffmpeg/ffmpeg/CVE-2022-48434.patch | |||
@@ -0,0 +1,130 @@ | |||
1 | From e40c964a0678908e2c756741343ed50d6a99ee12 Mon Sep 17 00:00:00 2001 | ||
2 | From: Anton Khirnov <anton@khirnov.net> | ||
3 | Date: Fri, 28 Apr 2023 11:45:30 +0000 | ||
4 | Subject: [PATCH] lavc/pthread_frame: avoid leaving stale hwaccel state in | ||
5 | worker threads | ||
6 | |||
7 | This state is not refcounted, so make sure it always has a well-defined | ||
8 | owner. | ||
9 | |||
10 | Remove the block added in 091341f, as | ||
11 | this commit also solves that issue in a more general way. | ||
12 | |||
13 | CVE:CVE-2022-48434 | ||
14 | |||
15 | Upstream-Status: Backport [https://github.com/FFmpeg/FFmpeg/commit/cc867f2c09d2b69cee8a0eccd62aff002cbbfe11] | ||
16 | |||
17 | Signed-off-by: Narpat Mali <narpat.mali@windriver.com> | ||
18 | --- | ||
19 | libavcodec/pthread_frame.c | 46 +++++++++++++++++++++++++++++--------- | ||
20 | 1 file changed, 35 insertions(+), 11 deletions(-) | ||
21 | |||
22 | diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c | ||
23 | index 85a6bc9..e40dced 100644 | ||
24 | --- a/libavcodec/pthread_frame.c | ||
25 | +++ b/libavcodec/pthread_frame.c | ||
26 | @@ -145,6 +145,12 @@ typedef struct FrameThreadContext { | ||
27 | * Set for the first N packets, where N is the number of threads. | ||
28 | * While it is set, ff_thread_en/decode_frame won't return any results. | ||
29 | */ | ||
30 | + | ||
31 | + /* hwaccel state is temporarily stored here in order to transfer its ownership | ||
32 | + * to the next decoding thread without the need for extra synchronization */ | ||
33 | + const AVHWAccel *stash_hwaccel; | ||
34 | + void *stash_hwaccel_context; | ||
35 | + void *stash_hwaccel_priv; | ||
36 | } FrameThreadContext; | ||
37 | |||
38 | #if FF_API_THREAD_SAFE_CALLBACKS | ||
39 | @@ -229,9 +235,17 @@ FF_ENABLE_DEPRECATION_WARNINGS | ||
40 | ff_thread_finish_setup(avctx); | ||
41 | |||
42 | if (p->hwaccel_serializing) { | ||
43 | + /* wipe hwaccel state to avoid stale pointers lying around; | ||
44 | + * the state was transferred to FrameThreadContext in | ||
45 | + * ff_thread_finish_setup(), so nothing is leaked */ | ||
46 | + avctx->hwaccel = NULL; | ||
47 | + avctx->hwaccel_context = NULL; | ||
48 | + avctx->internal->hwaccel_priv_data = NULL; | ||
49 | + | ||
50 | p->hwaccel_serializing = 0; | ||
51 | pthread_mutex_unlock(&p->parent->hwaccel_mutex); | ||
52 | } | ||
53 | + av_assert0(!avctx->hwaccel); | ||
54 | |||
55 | if (p->async_serializing) { | ||
56 | p->async_serializing = 0; | ||
57 | @@ -294,14 +308,10 @@ static int update_context_from_thread(AVCodecContext *dst, AVCodecContext *src, | ||
58 | dst->color_range = src->color_range; | ||
59 | dst->chroma_sample_location = src->chroma_sample_location; | ||
60 | |||
61 | - dst->hwaccel = src->hwaccel; | ||
62 | - dst->hwaccel_context = src->hwaccel_context; | ||
63 | - | ||
64 | dst->channels = src->channels; | ||
65 | dst->sample_rate = src->sample_rate; | ||
66 | dst->sample_fmt = src->sample_fmt; | ||
67 | dst->channel_layout = src->channel_layout; | ||
68 | - dst->internal->hwaccel_priv_data = src->internal->hwaccel_priv_data; | ||
69 | |||
70 | if (!!dst->hw_frames_ctx != !!src->hw_frames_ctx || | ||
71 | (dst->hw_frames_ctx && dst->hw_frames_ctx->data != src->hw_frames_ctx->data)) { | ||
72 | @@ -442,6 +452,12 @@ static int submit_packet(PerThreadContext *p, AVCodecContext *user_avctx, | ||
73 | pthread_mutex_unlock(&p->mutex); | ||
74 | return err; | ||
75 | } | ||
76 | + | ||
77 | + /* transfer hwaccel state stashed from previous thread, if any */ | ||
78 | + av_assert0(!p->avctx->hwaccel); | ||
79 | + FFSWAP(const AVHWAccel*, p->avctx->hwaccel, fctx->stash_hwaccel); | ||
80 | + FFSWAP(void*, p->avctx->hwaccel_context, fctx->stash_hwaccel_context); | ||
81 | + FFSWAP(void*, p->avctx->internal->hwaccel_priv_data, fctx->stash_hwaccel_priv); | ||
82 | } | ||
83 | |||
84 | av_packet_unref(p->avpkt); | ||
85 | @@ -647,6 +663,14 @@ void ff_thread_finish_setup(AVCodecContext *avctx) { | ||
86 | async_lock(p->parent); | ||
87 | } | ||
88 | |||
89 | + /* save hwaccel state for passing to the next thread; | ||
90 | + * this is done here so that this worker thread can wipe its own hwaccel | ||
91 | + * state after decoding, without requiring synchronization */ | ||
92 | + av_assert0(!p->parent->stash_hwaccel); | ||
93 | + p->parent->stash_hwaccel = avctx->hwaccel; | ||
94 | + p->parent->stash_hwaccel_context = avctx->hwaccel_context; | ||
95 | + p->parent->stash_hwaccel_priv = avctx->internal->hwaccel_priv_data; | ||
96 | + | ||
97 | pthread_mutex_lock(&p->progress_mutex); | ||
98 | if(atomic_load(&p->state) == STATE_SETUP_FINISHED){ | ||
99 | av_log(avctx, AV_LOG_WARNING, "Multiple ff_thread_finish_setup() calls\n"); | ||
100 | @@ -700,13 +724,6 @@ void ff_frame_thread_free(AVCodecContext *avctx, int thread_count) | ||
101 | |||
102 | park_frame_worker_threads(fctx, thread_count); | ||
103 | |||
104 | - if (fctx->prev_thread && avctx->internal->hwaccel_priv_data != | ||
105 | - fctx->prev_thread->avctx->internal->hwaccel_priv_data) { | ||
106 | - if (update_context_from_thread(avctx, fctx->prev_thread->avctx, 1) < 0) { | ||
107 | - av_log(avctx, AV_LOG_ERROR, "Failed to update user thread.\n"); | ||
108 | - } | ||
109 | - } | ||
110 | - | ||
111 | if (fctx->prev_thread && fctx->prev_thread != fctx->threads) | ||
112 | if (update_context_from_thread(fctx->threads->avctx, fctx->prev_thread->avctx, 0) < 0) { | ||
113 | av_log(avctx, AV_LOG_ERROR, "Final thread update failed\n"); | ||
114 | @@ -760,6 +777,13 @@ void ff_frame_thread_free(AVCodecContext *avctx, int thread_count) | ||
115 | av_freep(&fctx->threads); | ||
116 | ff_pthread_free(fctx, thread_ctx_offsets); | ||
117 | |||
118 | + /* if we have stashed hwaccel state, move it to the user-facing context, | ||
119 | + * so it will be freed in avcodec_close() */ | ||
120 | + av_assert0(!avctx->hwaccel); | ||
121 | + FFSWAP(const AVHWAccel*, avctx->hwaccel, fctx->stash_hwaccel); | ||
122 | + FFSWAP(void*, avctx->hwaccel_context, fctx->stash_hwaccel_context); | ||
123 | + FFSWAP(void*, avctx->internal->hwaccel_priv_data, fctx->stash_hwaccel_priv); | ||
124 | + | ||
125 | av_freep(&avctx->internal->thread_ctx); | ||
126 | } | ||
127 | |||
128 | -- | ||
129 | 2.40.0 | ||
130 | |||
diff --git a/meta/recipes-multimedia/ffmpeg/ffmpeg_5.0.1.bb b/meta/recipes-multimedia/ffmpeg/ffmpeg_5.0.1.bb index 4bcbda9976..6ece34fcfd 100644 --- a/meta/recipes-multimedia/ffmpeg/ffmpeg_5.0.1.bb +++ b/meta/recipes-multimedia/ffmpeg/ffmpeg_5.0.1.bb | |||
@@ -28,7 +28,8 @@ SRC_URI = "https://www.ffmpeg.org/releases/${BP}.tar.xz \ | |||
28 | file://0001-avcodec-smcenc-stop-accessing-out-of-bounds-frame.patch \ | 28 | file://0001-avcodec-smcenc-stop-accessing-out-of-bounds-frame.patch \ |
29 | file://0001-avcodec-vp3-Add-missing-check-for-av_malloc.patch \ | 29 | file://0001-avcodec-vp3-Add-missing-check-for-av_malloc.patch \ |
30 | file://0001-avformat-nutdec-Add-check-for-avformat_new_stream.patch \ | 30 | file://0001-avformat-nutdec-Add-check-for-avformat_new_stream.patch \ |
31 | " | 31 | file://CVE-2022-48434.patch \ |
32 | " | ||
32 | 33 | ||
33 | SRC_URI[sha256sum] = "ef2efae259ce80a240de48ec85ecb062cecca26e4352ffb3fda562c21a93007b" | 34 | SRC_URI[sha256sum] = "ef2efae259ce80a240de48ec85ecb062cecca26e4352ffb3fda562c21a93007b" |
34 | 35 | ||