Merge ~rafaeldtinoco/ubuntu/+source/qemu:lp1805256-eoan into ubuntu/+source/qemu:ubuntu/eoan-devel

Proposed by Rafael David Tinoco
Status: Merged
Approved by: Rafael David Tinoco
Approved revision: a5f79f1371f9db7b6b93733d1dc4346a222593d8
Merged at revision: a5f79f1371f9db7b6b93733d1dc4346a222593d8
Proposed branch: ~rafaeldtinoco/ubuntu/+source/qemu:lp1805256-eoan
Merge into: ubuntu/+source/qemu:ubuntu/eoan-devel
Diff against target: 307 lines (+279/-0)
4 files modified
debian/changelog (+8/-0)
debian/patches/series (+2/-0)
debian/patches/ubuntu/lp-1805256-aio-wait_delegate_poll_aioctx_bql.patch (+110/-0)
debian/patches/ubuntu/lp-1805256-async_use_explicit_mem_barriers.patch (+159/-0)
Reviewer Review Type Date Requested Status
Christian Ehrhardt  (community) Approve
Rafael David Tinoco (community) Approve
Ike Panhc (community) Approve
dann frazier (community) Approve
Canonical Server Pending
Review via email: mp+383551@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Rafael David Tinoco (rafaeldtinoco) wrote :
Revision history for this message
dann frazier (dannf) wrote :

Verified by building and testing the source package in your PPA (faster than waiting for LP builder), and verifying that it passed my test case for > 100 loops. Thanks @rafaeldtinoco!

review: Approve
Revision history for this message
Ike Panhc (ikepanhc) wrote :

Test on d06 for 1000 run and all passed

review: Approve
Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

Also needs a rebase due to CVE-2020-11869 fix in 1:4.0+dfsg-0ubuntu9.6
It otherwise looks ok to me

Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

Can you update the PPA (https://launchpad.net/~rafaeldtinoco/+archive/ubuntu/lp1805256/) after the rebase. I'll then run a regression test set and if ok sponsor it into the -unapproved queue after the groovy upload completed.

Revision history for this message
Rafael David Tinoco (rafaeldtinoco) wrote :

Done!

review: Approve
Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

Thanks for the rebase, non case specific regression testing is a few thousand tests in and still working.
Approving the MP now.
If no issue shows up late I'll sponsor this to -unapproved later on.

review: Approve
Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

Regression tests completed - sponsoring once groovy is complete

Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

Groovy is completed, SRU sponsored into -unapproved

To ssh://git.launchpad.net/~usd-import-team/ubuntu/+source/qemu
 * [new tag] upload/1%4.0+dfsg-0ubuntu9.7 -> upload/1%4.0+dfsg-0ubuntu9.7

Uploading to ubuntu (via ftp to upload.ubuntu.com):
  Uploading qemu_4.0+dfsg-0ubuntu9.7.dsc: done.
  Uploading qemu_4.0+dfsg-0ubuntu9.7.debian.tar.xz: done.
  Uploading qemu_4.0+dfsg-0ubuntu9.7_source.buildinfo: done.
  Uploading qemu_4.0+dfsg-0ubuntu9.7_source.changes: done.
Successfully uploaded packages.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/debian/changelog b/debian/changelog
2index 5cf0eef..4450378 100644
3--- a/debian/changelog
4+++ b/debian/changelog
5@@ -1,3 +1,11 @@
6+qemu (1:4.0+dfsg-0ubuntu9.7) eoan; urgency=medium
7+
8+ * d/p/ubuntu/lp-1805256*: Fixes for QEMU on aarch64 ARM hosts
9+ - async: use explicit memory barriers (LP: #1805256)
10+ - aio-wait: delegate polling of main AioContext if BQL not held
11+
12+ -- Rafael David Tinoco <rafaeldtinoco@ubuntu.com> Wed, 27 May 2020 20:07:57 +0000
13+
14 qemu (1:4.0+dfsg-0ubuntu9.6) eoan-security; urgency=medium
15
16 * SECURITY UPDATE: overflow via PCIe extended config space
17diff --git a/debian/patches/series b/debian/patches/series
18index 8edcf9d..43a5b90 100644
19--- a/debian/patches/series
20+++ b/debian/patches/series
21@@ -52,3 +52,5 @@ ubuntu/CVE-2019-15034.patch
22 ubuntu/CVE-2019-20382.patch
23 ubuntu/CVE-2020-10702.patch
24 ubuntu/CVE-2020-1983.patch
25+ubuntu/lp-1805256-async_use_explicit_mem_barriers.patch
26+ubuntu/lp-1805256-aio-wait_delegate_poll_aioctx_bql.patch
27diff --git a/debian/patches/ubuntu/lp-1805256-aio-wait_delegate_poll_aioctx_bql.patch b/debian/patches/ubuntu/lp-1805256-aio-wait_delegate_poll_aioctx_bql.patch
28new file mode 100644
29index 0000000..c304a0b
30--- /dev/null
31+++ b/debian/patches/ubuntu/lp-1805256-aio-wait_delegate_poll_aioctx_bql.patch
32@@ -0,0 +1,110 @@
33+Description: aio-wait: delegate polling of main AioContext if BQL not held
34+
35+Any thread that is not a iothread returns NULL for qemu_get_current_aio_context().
36+As a result, it would also return true for
37+in_aio_context_home_thread(qemu_get_aio_context()), causing
38+AIO_WAIT_WHILE to invoke aio_poll() directly. This is incorrect
39+if the BQL is not held, because aio_poll() does not expect to
40+run concurrently from multiple threads, and it can actually
41+happen when savevm writes to the vmstate file from the
42+migration thread.
43+
44+Therefore, restrict in_aio_context_home_thread to return true
45+for the main AioContext only if the BQL is held.
46+
47+The function is moved to aio-wait.h because it is mostly used
48+there and to avoid a circular reference between main-loop.h
49+and block/aio.h.
50+
51+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
52+Message-Id: <20200407140746.8041-5-pbonzini@redhat.com>
53+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
54+
55+Author: Paolo Bonzini <pbonzini@redhat.com>
56+Origin: upstream, https://github.com/qemu/qemu/commit/3c18a92dc
57+Bug: https://launchpad.net/bugs/1805256
58+Bug-Ubuntu: https://launchpad.net/bugs/1805256
59+Reviewed-By: Rafael David Tinoco <rafaeldtinoco@ubuntu.com>
60+Last-Update: 2020-05-06
61+
62+--- qemu-4.0+dfsg.orig/include/block/aio-wait.h
63++++ qemu-4.0+dfsg/include/block/aio-wait.h
64+@@ -26,6 +26,7 @@
65+ #define QEMU_AIO_WAIT_H
66+
67+ #include "block/aio.h"
68++#include "qemu/main-loop.h"
69+
70+ /**
71+ * AioWait:
72+@@ -124,4 +125,25 @@ void aio_wait_kick(void);
73+ */
74+ void aio_wait_bh_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque);
75+
76++/**
77++ * in_aio_context_home_thread:
78++ * @ctx: the aio context
79++ *
80++ * Return whether we are running in the thread that normally runs @ctx. Note
81++ * that acquiring/releasing ctx does not affect the outcome, each AioContext
82++ * still only has one home thread that is responsible for running it.
83++ */
84++static inline bool in_aio_context_home_thread(AioContext *ctx)
85++{
86++ if (ctx == qemu_get_current_aio_context()) {
87++ return true;
88++ }
89++
90++ if (ctx == qemu_get_aio_context()) {
91++ return qemu_mutex_iothread_locked();
92++ } else {
93++ return false;
94++ }
95++}
96++
97+ #endif /* QEMU_AIO_WAIT */
98+--- qemu-4.0+dfsg.orig/include/block/aio.h
99++++ qemu-4.0+dfsg/include/block/aio.h
100+@@ -61,12 +61,16 @@ struct AioContext {
101+ QLIST_HEAD(, AioHandler) aio_handlers;
102+
103+ /* Used to avoid unnecessary event_notifier_set calls in aio_notify;
104+- * accessed with atomic primitives. If this field is 0, everything
105+- * (file descriptors, bottom halves, timers) will be re-evaluated
106+- * before the next blocking poll(), thus the event_notifier_set call
107+- * can be skipped. If it is non-zero, you may need to wake up a
108+- * concurrent aio_poll or the glib main event loop, making
109+- * event_notifier_set necessary.
110++ * only written from the AioContext home thread, or under the BQL in
111++ * the case of the main AioContext. However, it is read from any
112++ * thread so it is still accessed with atomic primitives.
113++ *
114++ * If this field is 0, everything (file descriptors, bottom halves,
115++ * timers) will be re-evaluated before the next blocking poll() or
116++ * io_uring wait; therefore, the event_notifier_set call can be
117++ * skipped. If it is non-zero, you may need to wake up a concurrent
118++ * aio_poll or the glib main event loop, making event_notifier_set
119++ * necessary.
120+ *
121+ * Bit 0 is reserved for GSource usage of the AioContext, and is 1
122+ * between a call to aio_ctx_prepare and the next call to aio_ctx_check.
123+@@ -582,19 +586,6 @@ void aio_co_enter(AioContext *ctx, struc
124+ AioContext *qemu_get_current_aio_context(void);
125+
126+ /**
127+- * in_aio_context_home_thread:
128+- * @ctx: the aio context
129+- *
130+- * Return whether we are running in the thread that normally runs @ctx. Note
131+- * that acquiring/releasing ctx does not affect the outcome, each AioContext
132+- * still only has one home thread that is responsible for running it.
133+- */
134+-static inline bool in_aio_context_home_thread(AioContext *ctx)
135+-{
136+- return ctx == qemu_get_current_aio_context();
137+-}
138+-
139+-/**
140+ * aio_context_setup:
141+ * @ctx: the aio context
142+ *
143diff --git a/debian/patches/ubuntu/lp-1805256-async_use_explicit_mem_barriers.patch b/debian/patches/ubuntu/lp-1805256-async_use_explicit_mem_barriers.patch
144new file mode 100644
145index 0000000..3ed09e1
146--- /dev/null
147+++ b/debian/patches/ubuntu/lp-1805256-async_use_explicit_mem_barriers.patch
148@@ -0,0 +1,159 @@
149+Description: async: use explicit memory barriers
150+
151+When using C11 atomics, non-seqcst reads and writes do not participate
152+in the total order of seqcst operations. In util/async.c and util/aio-posix.c,
153+in particular, the pattern that we use
154+
155+ write ctx->notify_me write bh->scheduled
156+ read bh->scheduled read ctx->notify_me
157+ if !bh->scheduled, sleep if ctx->notify_me, notify
158+
159+needs to use seqcst operations for both the write and the read. In
160+general this is something that we do not want, because there can be
161+many sources that are polled in addition to bottom halves. The
162+alternative is to place a seqcst memory barrier between the write
163+and the read. This also comes with a disadvantage, in that the
164+memory barrier is implicit on strongly-ordered architectures and
165+it wastes a few dozen clock cycles.
166+
167+Fortunately, ctx->notify_me is never written concurrently by two
168+threads, so we can assert that and relax the writes to ctx->notify_me.
169+The resulting solution works and performs well on both aarch64 and x86.
170+
171+Note that the atomic_set/atomic_read combination is not an atomic
172+read-modify-write, and therefore it is even weaker than C11 ATOMIC_RELAXED;
173+on x86, ATOMIC_RELAXED compiles to a locked operation.
174+
175+Analyzed-by: Ying Fang <fangying1@huawei.com>
176+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
177+Tested-by: Ying Fang <fangying1@huawei.com>
178+Message-Id: <20200407140746.8041-6-pbonzini@redhat.com>
179+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
180+
181+Author: Paolo Bonzini <pbonzini@redhat.com>
182+Origin: upstream, https://github.com/qemu/qemu/commit/5710a3e09f
183+Bug: https://bugs.launchpad.net/bugs/1805256
184+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1805256
185+Reviewed-By: Rafael David Tinoco <rafaeldtinoco@ubuntu.com>
186+Last-Update: 2020-05-06
187+
188+--- qemu-4.2.orig/util/aio-posix.c
189++++ qemu-4.2/util/aio-posix.c
190+@@ -616,6 +616,11 @@ bool aio_poll(AioContext *ctx, bool bloc
191+ int64_t timeout;
192+ int64_t start = 0;
193+
194++ /*
195++ * There cannot be two concurrent aio_poll calls for the same AioContext (or
196++ * an aio_poll concurrent with a GSource prepare/check/dispatch callback).
197++ * We rely on this below to avoid slow locked accesses to ctx->notify_me.
198++ */
199+ assert(in_aio_context_home_thread(ctx));
200+
201+ /* aio_notify can avoid the expensive event_notifier_set if
202+@@ -626,7 +631,13 @@ bool aio_poll(AioContext *ctx, bool bloc
203+ * so disable the optimization now.
204+ */
205+ if (blocking) {
206+- atomic_add(&ctx->notify_me, 2);
207++ atomic_set(&ctx->notify_me, atomic_read(&ctx->notify_me) + 2);
208++ /*
209++ * Write ctx->notify_me before computing the timeout
210++ * (reading bottom half flags, etc.). Pairs with
211++ * smp_mb in aio_notify().
212++ */
213++ smp_mb();
214+ }
215+
216+ qemu_lockcnt_inc(&ctx->list_lock);
217+@@ -671,7 +682,8 @@ bool aio_poll(AioContext *ctx, bool bloc
218+ }
219+
220+ if (blocking) {
221+- atomic_sub(&ctx->notify_me, 2);
222++ /* Finish the poll before clearing the flag. */
223++ atomic_store_release(&ctx->notify_me, atomic_read(&ctx->notify_me) - 2);
224+ aio_notify_accept(ctx);
225+ }
226+
227+--- qemu-4.2.orig/util/aio-win32.c
228++++ qemu-4.2/util/aio-win32.c
229+@@ -321,6 +321,12 @@ bool aio_poll(AioContext *ctx, bool bloc
230+ int count;
231+ int timeout;
232+
233++ /*
234++ * There cannot be two concurrent aio_poll calls for the same AioContext (or
235++ * an aio_poll concurrent with a GSource prepare/check/dispatch callback).
236++ * We rely on this below to avoid slow locked accesses to ctx->notify_me.
237++ */
238++ assert(in_aio_context_home_thread(ctx));
239+ progress = false;
240+
241+ /* aio_notify can avoid the expensive event_notifier_set if
242+@@ -331,7 +337,13 @@ bool aio_poll(AioContext *ctx, bool bloc
243+ * so disable the optimization now.
244+ */
245+ if (blocking) {
246+- atomic_add(&ctx->notify_me, 2);
247++ atomic_set(&ctx->notify_me, atomic_read(&ctx->notify_me) + 2);
248++ /*
249++ * Write ctx->notify_me before computing the timeout
250++ * (reading bottom half flags, etc.). Pairs with
251++ * smp_mb in aio_notify().
252++ */
253++ smp_mb();
254+ }
255+
256+ qemu_lockcnt_inc(&ctx->list_lock);
257+@@ -364,8 +376,7 @@ bool aio_poll(AioContext *ctx, bool bloc
258+ ret = WaitForMultipleObjects(count, events, FALSE, timeout);
259+ if (blocking) {
260+ assert(first);
261+- assert(in_aio_context_home_thread(ctx));
262+- atomic_sub(&ctx->notify_me, 2);
263++ atomic_store_release(&ctx->notify_me, atomic_read(&ctx->notify_me) - 2);
264+ aio_notify_accept(ctx);
265+ }
266+
267+--- qemu-4.2.orig/util/async.c
268++++ qemu-4.2/util/async.c
269+@@ -220,7 +220,14 @@ aio_ctx_prepare(GSource *source, gint
270+ {
271+ AioContext *ctx = (AioContext *) source;
272+
273+- atomic_or(&ctx->notify_me, 1);
274++ atomic_set(&ctx->notify_me, atomic_read(&ctx->notify_me) | 1);
275++
276++ /*
277++ * Write ctx->notify_me before computing the timeout
278++ * (reading bottom half flags, etc.). Pairs with
279++ * smp_mb in aio_notify().
280++ */
281++ smp_mb();
282+
283+ /* We assume there is no timeout already supplied */
284+ *timeout = qemu_timeout_ns_to_ms(aio_compute_timeout(ctx));
285+@@ -238,7 +245,8 @@ aio_ctx_check(GSource *source)
286+ AioContext *ctx = (AioContext *) source;
287+ QEMUBH *bh;
288+
289+- atomic_and(&ctx->notify_me, ~1);
290++ /* Finish computing the timeout before clearing the flag. */
291++ atomic_store_release(&ctx->notify_me, atomic_read(&ctx->notify_me) & ~1);
292+ aio_notify_accept(ctx);
293+
294+ for (bh = ctx->first_bh; bh; bh = bh->next) {
295+@@ -343,10 +351,10 @@ LinuxAioState *aio_get_linux_aio(AioCont
296+ void aio_notify(AioContext *ctx)
297+ {
298+ /* Write e.g. bh->scheduled before reading ctx->notify_me. Pairs
299+- * with atomic_or in aio_ctx_prepare or atomic_add in aio_poll.
300++ * with smp_mb in aio_ctx_prepare or aio_poll.
301+ */
302+ smp_mb();
303+- if (ctx->notify_me) {
304++ if (atomic_read(&ctx->notify_me)) {
305+ event_notifier_set(&ctx->notifier);
306+ atomic_mb_set(&ctx->notified, true);
307+ }

Subscribers

People subscribed via source and target branches