Gentoo Archives: gentoo-commits

From: Sam James <sam@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] repo/gentoo:master commit in: media-video/pipewire/, media-video/pipewire/files/
Date: Mon, 21 Feb 2022 03:30:38
Message-Id: 1645414219.3f09ddaa0cb5529f43f290d663ab2267d67b2a6c.sam@gentoo
1 commit: 3f09ddaa0cb5529f43f290d663ab2267d67b2a6c
2 Author: Sam James <sam <AT> gentoo <DOT> org>
3 AuthorDate: Mon Feb 21 03:27:05 2022 +0000
4 Commit: Sam James <sam <AT> gentoo <DOT> org>
5 CommitDate: Mon Feb 21 03:30:19 2022 +0000
6 URL: https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=3f09ddaa
7
8 media-video/pipewire: backport 2 crash fixes
9
10 - backport mpd crash fix
11 - backport "fast volume change" fix
12
13 Signed-off-by: Sam James <sam <AT> gentoo.org>
14
15 ...7-pulse-server-pending-sample-reply-crash.patch | 101 +++++++++++
16 ....3.47-revert-loop-remove-destroy-list-mpd.patch | 187 +++++++++++++++++++++
17 ...ire-0.3.47.ebuild => pipewire-0.3.47-r1.ebuild} | 3 +
18 3 files changed, 291 insertions(+)
19
20 diff --git a/media-video/pipewire/files/pipewire-0.3.47-pulse-server-pending-sample-reply-crash.patch b/media-video/pipewire/files/pipewire-0.3.47-pulse-server-pending-sample-reply-crash.patch
21 new file mode 100644
22 index 000000000000..d4f74a5abcc5
23 --- /dev/null
24 +++ b/media-video/pipewire/files/pipewire-0.3.47-pulse-server-pending-sample-reply-crash.patch
25 @@ -0,0 +1,101 @@
26 +https://gitlab.freedesktop.org/pipewire/pipewire/-/commit/d7793501fd012de37fcc8bf09003c60bc4624341.patch
27 +
28 +From d7793501fd012de37fcc8bf09003c60bc4624341 Mon Sep 17 00:00:00 2001
29 +From: Wim Taymans <wtaymans@××××××.com>
30 +Date: Sun, 20 Feb 2022 21:34:53 +0100
31 +Subject: [PATCH] pulse-server: free pending sample reply
32 +
33 +If the sample finished playing before we finished the roundtrip to
34 +get the sink_index, it will be destroyed. When the roundtrip completes,
35 +it will try to use invalid memoryy and crash.
36 +
37 +Make sure we destroy all pending replies before destroying the sample
38 +to avoid this problem.
39 +
40 +Fixes #2151
41 +---
42 + src/modules/module-protocol-pulse/operation.c | 10 ++++++++++
43 + src/modules/module-protocol-pulse/operation.h | 1 +
44 + src/modules/module-protocol-pulse/pending-sample.c | 5 +++++
45 + src/modules/module-protocol-pulse/pulse-server.c | 4 ++++
46 + 4 files changed, 20 insertions(+)
47 +
48 +diff --git a/src/modules/module-protocol-pulse/operation.c b/src/modules/module-protocol-pulse/operation.c
49 +index e0e67b374..b1e0eb08d 100644
50 +--- a/src/modules/module-protocol-pulse/operation.c
51 ++++ b/src/modules/module-protocol-pulse/operation.c
52 +@@ -66,6 +66,16 @@ void operation_free(struct operation *o)
53 + free(o);
54 + }
55 +
56 ++struct operation *operation_find(struct client *client, uint32_t tag)
57 ++{
58 ++ struct operation *o;
59 ++ spa_list_for_each(o, &client->operations, link) {
60 ++ if (o->tag == tag)
61 ++ return o;
62 ++ }
63 ++ return NULL;
64 ++}
65 ++
66 + void operation_complete(struct operation *o)
67 + {
68 + struct client *client = o->client;
69 +diff --git a/src/modules/module-protocol-pulse/operation.h b/src/modules/module-protocol-pulse/operation.h
70 +index d282ee5e5..1fa07cc7b 100644
71 +--- a/src/modules/module-protocol-pulse/operation.h
72 ++++ b/src/modules/module-protocol-pulse/operation.h
73 +@@ -43,6 +43,7 @@ int operation_new(struct client *client, uint32_t tag);
74 + int operation_new_cb(struct client *client, uint32_t tag,
75 + void (*callback) (void *data, struct client *client, uint32_t tag),
76 + void *data);
77 ++struct operation *operation_find(struct client *client, uint32_t tag);
78 + void operation_free(struct operation *o);
79 + void operation_complete(struct operation *o);
80 +
81 +diff --git a/src/modules/module-protocol-pulse/pending-sample.c b/src/modules/module-protocol-pulse/pending-sample.c
82 +index 6e5d04fbb..399fc3b54 100644
83 +--- a/src/modules/module-protocol-pulse/pending-sample.c
84 ++++ b/src/modules/module-protocol-pulse/pending-sample.c
85 +@@ -29,6 +29,7 @@
86 + #include "client.h"
87 + #include "internal.h"
88 + #include "log.h"
89 ++#include "operation.h"
90 + #include "pending-sample.h"
91 + #include "sample-play.h"
92 +
93 +@@ -36,10 +37,14 @@ void pending_sample_free(struct pending_sample *ps)
94 + {
95 + struct client * const client = ps->client;
96 + struct impl * const impl = client->impl;
97 ++ struct operation *o;
98 +
99 + spa_list_remove(&ps->link);
100 + spa_hook_remove(&ps->listener);
101 + pw_work_queue_cancel(impl->work_queue, ps, SPA_ID_INVALID);
102 +
103 ++ if ((o = operation_find(client, ps->tag)) != NULL)
104 ++ operation_free(o);
105 ++
106 + sample_play_destroy(ps->play);
107 + }
108 +diff --git a/src/modules/module-protocol-pulse/pulse-server.c b/src/modules/module-protocol-pulse/pulse-server.c
109 +index 182c3db99..c035840d1 100644
110 +--- a/src/modules/module-protocol-pulse/pulse-server.c
111 ++++ b/src/modules/module-protocol-pulse/pulse-server.c
112 +@@ -2353,6 +2353,10 @@ static void on_sample_done(void *obj, void *data, int res, uint32_t id)
113 + {
114 + struct pending_sample *ps = obj;
115 + struct client *client = ps->client;
116 ++ struct operation *o;
117 ++
118 ++ if ((o = operation_find(client, ps->tag)) != NULL)
119 ++ operation_complete(o);
120 +
121 + pending_sample_free(ps);
122 + client_unref(client);
123 +--
124 +GitLab
125 +
126 +
127
128 diff --git a/media-video/pipewire/files/pipewire-0.3.47-revert-loop-remove-destroy-list-mpd.patch b/media-video/pipewire/files/pipewire-0.3.47-revert-loop-remove-destroy-list-mpd.patch
129 new file mode 100644
130 index 000000000000..0e27d65fdb3a
131 --- /dev/null
132 +++ b/media-video/pipewire/files/pipewire-0.3.47-revert-loop-remove-destroy-list-mpd.patch
133 @@ -0,0 +1,187 @@
134 +Fixes mpd crash.
135 +
136 +https://gitlab.freedesktop.org/pipewire/pipewire/-/commit/16f63a3c8fa227625bade5a9edea22354b347d18.patch
137 +https://gitlab.freedesktop.org/pipewire/pipewire/-/commit/d1f7e96f821089224ddcacf8e8f506f99c54eb5c.patch
138 +
139 +From 16f63a3c8fa227625bade5a9edea22354b347d18 Mon Sep 17 00:00:00 2001
140 +From: =?UTF-8?q?Barnab=C3=A1s=20P=C5=91cze?= <pobrn@××××××××××.com>
141 +Date: Fri, 18 Feb 2022 18:36:36 +0100
142 +Subject: [PATCH] Revert "loop: remove destroy list"
143 +
144 +This reverts commit c474846c42967c44db069a23b76a29da6f496f33.
145 +In addition, `s->loop` is also checked before dispatching a source.
146 +
147 +The destroy list is needed in the presence of threads. The
148 +issue is that a source may be destroyed between `epoll_wait()`
149 +returning and thread loop lock being acquired. If this
150 +source is active, then a use-after-free will be triggered
151 +when the thread loop acquires the lock and starts dispatching
152 +the sources.
153 +
154 + thread 1 thread 2
155 + ---------- ----------
156 + loop_iterate
157 + spa_loop_control_hook_before
158 + // release lock
159 +
160 + pw_thread_loop_lock
161 +
162 + spa_system_pollfd_wait
163 + // assume it returns with source A
164 +
165 + pw_loop_destroy_source(..., A)
166 + // frees storage of A
167 +
168 + pw_thread_loop_unlock
169 + spa_loop_control_hook_after
170 + // acquire the lock
171 +
172 + for (...) {
173 + struct spa_source *s = ep[i].data;
174 + s->rmask = ep[i].events;
175 + // use-after-free if `s` refers to
176 + // the previously freed `A`
177 +
178 +Fixes #2147
179 +---
180 + spa/plugins/support/loop.c | 19 +++++++++++++++++--
181 + 1 file changed, 17 insertions(+), 2 deletions(-)
182 +
183 +diff --git a/spa/plugins/support/loop.c b/spa/plugins/support/loop.c
184 +index 0588ce770..04739eb2a 100644
185 +--- a/spa/plugins/support/loop.c
186 ++++ b/spa/plugins/support/loop.c
187 +@@ -75,6 +75,7 @@ struct impl {
188 + struct spa_system *system;
189 +
190 + struct spa_list source_list;
191 ++ struct spa_list destroy_list;
192 + struct spa_hook_list hooks_list;
193 +
194 + int poll_fd;
195 +@@ -325,6 +326,14 @@ static void loop_leave(void *object)
196 + impl->thread = 0;
197 + }
198 +
199 ++static inline void process_destroy(struct impl *impl)
200 ++{
201 ++ struct source_impl *source, *tmp;
202 ++ spa_list_for_each_safe(source, tmp, &impl->destroy_list, link)
203 ++ free(source);
204 ++ spa_list_init(&impl->destroy_list);
205 ++}
206 ++
207 + static int loop_iterate(void *object, int timeout)
208 + {
209 + struct impl *impl = object;
210 +@@ -354,11 +363,14 @@ static int loop_iterate(void *object, int timeout)
211 + }
212 + for (i = 0; i < nfds; i++) {
213 + struct spa_source *s = ep[i].data;
214 +- if (SPA_LIKELY(s && s->rmask)) {
215 ++ if (SPA_LIKELY(s && s->rmask && s->loop)) {
216 + s->priv = NULL;
217 + s->func(s);
218 + }
219 + }
220 ++ if (SPA_UNLIKELY(!spa_list_is_empty(&impl->destroy_list)))
221 ++ process_destroy(impl);
222 ++
223 + return nfds;
224 + }
225 +
226 +@@ -712,7 +724,7 @@ static void loop_destroy_source(void *object, struct spa_source *source)
227 + spa_system_close(impl->impl->system, source->fd);
228 + source->fd = -1;
229 + }
230 +- free(source);
231 ++ spa_list_insert(&impl->impl->destroy_list, &impl->link);
232 + }
233 +
234 + static const struct spa_loop_methods impl_loop = {
235 +@@ -783,6 +795,8 @@ static int impl_clear(struct spa_handle *handle)
236 + spa_list_consume(source, &impl->source_list, link)
237 + loop_destroy_source(impl, &source->source);
238 +
239 ++ process_destroy(impl);
240 ++
241 + spa_system_close(impl->system, impl->ack_fd);
242 + spa_system_close(impl->system, impl->poll_fd);
243 +
244 +@@ -844,6 +858,7 @@ impl_init(const struct spa_handle_factory *factory,
245 + impl->poll_fd = res;
246 +
247 + spa_list_init(&impl->source_list);
248 ++ spa_list_init(&impl->destroy_list);
249 + spa_hook_list_init(&impl->hooks_list);
250 +
251 + impl->buffer_data = SPA_PTR_ALIGN(impl->buffer_mem, MAX_ALIGN, uint8_t);
252 +--
253 +GitLab
254 +
255 +
256 +From d1f7e96f821089224ddcacf8e8f506f99c54eb5c Mon Sep 17 00:00:00 2001
257 +From: =?UTF-8?q?Barnab=C3=A1s=20P=C5=91cze?= <pobrn@××××××××××.com>
258 +Date: Fri, 18 Feb 2022 19:27:13 +0100
259 +Subject: [PATCH] test: loop: add test for destroying source of thread loop
260 +
261 +Add test which tries to destroy an active source precisely
262 +after the loop has returned from polling but has not yet
263 +acquired the thread loop lock.
264 +---
265 + test/test-loop.c | 34 ++++++++++++++++++++++++++++++++++
266 + 1 file changed, 34 insertions(+)
267 +
268 +diff --git a/test/test-loop.c b/test/test-loop.c
269 +index 98b2add09..81f7a117c 100644
270 +--- a/test/test-loop.c
271 ++++ b/test/test-loop.c
272 +@@ -227,11 +227,45 @@ PWTEST(pwtest_loop_recurse2)
273 + return PWTEST_PASS;
274 + }
275 +
276 ++PWTEST(thread_loop_destroy_between_poll_and_lock)
277 ++{
278 ++ pw_init(NULL, NULL);
279 ++
280 ++ struct pw_thread_loop *thread_loop = pw_thread_loop_new("uaf", NULL);
281 ++ pwtest_ptr_notnull(thread_loop);
282 ++
283 ++ struct pw_loop *loop = pw_thread_loop_get_loop(thread_loop);
284 ++ pwtest_ptr_notnull(loop);
285 ++
286 ++ int evfd = eventfd(0, 0);
287 ++ pwtest_errno_ok(evfd);
288 ++
289 ++ struct spa_source *source = pw_loop_add_io(loop, evfd, SPA_IO_IN, true, NULL, NULL);
290 ++ pwtest_ptr_notnull(source);
291 ++
292 ++ pw_thread_loop_start(thread_loop);
293 ++
294 ++ pw_thread_loop_lock(thread_loop);
295 ++ {
296 ++ write(evfd, &(uint64_t){1}, sizeof(uint64_t));
297 ++ sleep(1);
298 ++ pw_loop_destroy_source(loop, source);
299 ++ }
300 ++ pw_thread_loop_unlock(thread_loop);
301 ++
302 ++ pw_thread_loop_destroy(thread_loop);
303 ++
304 ++ pw_deinit();
305 ++
306 ++ return PWTEST_PASS;
307 ++}
308 ++
309 + PWTEST_SUITE(support)
310 + {
311 + pwtest_add(pwtest_loop_destroy2, PWTEST_NOARG);
312 + pwtest_add(pwtest_loop_recurse1, PWTEST_NOARG);
313 + pwtest_add(pwtest_loop_recurse2, PWTEST_NOARG);
314 ++ pwtest_add(thread_loop_destroy_between_poll_and_lock, PWTEST_NOARG);
315 +
316 + return PWTEST_PASS;
317 + }
318 +--
319 +GitLab
320 +
321
322 diff --git a/media-video/pipewire/pipewire-0.3.47.ebuild b/media-video/pipewire/pipewire-0.3.47-r1.ebuild
323 similarity index 98%
324 rename from media-video/pipewire/pipewire-0.3.47.ebuild
325 rename to media-video/pipewire/pipewire-0.3.47-r1.ebuild
326 index 1539b089dfa2..25c024b05e01 100644
327 --- a/media-video/pipewire/pipewire-0.3.47.ebuild
328 +++ b/media-video/pipewire/pipewire-0.3.47-r1.ebuild
329 @@ -123,6 +123,9 @@ DOCS=( {README,INSTALL}.md NEWS )
330
331 PATCHES=(
332 "${FILESDIR}"/${PN}-0.3.25-enable-failed-mlock-warning.patch
333 +
334 + "${FILESDIR}"/${P}-revert-loop-remove-destroy-list-mpd.patch
335 + "${FILESDIR}"/${P}-pulse-server-pending-sample-reply-crash.patch
336 )
337
338 # limitsdfile related code taken from =sys-auth/realtime-base-0.1