From: "Denis V. Lunev" <den@openvz.org>
To: qemu-devel@nongnu.org
Cc: qemu-block@nongnu.org, "Denis V. Lunev" <den@openvz.org>,
Eric Blake <eblake@redhat.com>,
Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Subject: [PATCH 0/3] block/nbd: fix a race in reply processing
Date: Wed, 12 Aug 2026 12:29:03 +0200 [thread overview]
Message-ID: <20260812102906.894063-1-den@openvz.org> (raw)
s->reply is documented as protected by s->receive_mutex, but the cookie
which owns it is cleared without that mutex. A request waiting for its
own reply reads the very same field under the mutex, and reads it twice
in a row, so the owner can clear it in between. The second read returns
0, COOKIE_TO_INDEX() turns that into an index of -1, and s->requests[]
is accessed in front of the array:
Assertion `!s->requests[ind2].receiving' failed.
(gdb) p cookie
$1 = 8
(gdb) p s->reply.cookie
$2 = 0
(gdb) p &((NBDClientRequest *)s->requests)[-1].receiving
$3 = (_Bool *) 0x5555558416c0
(gdb) p &s->in_flight
$4 = (unsigned int *) 0x5555558416c0
requests[-1].receiving lands on in_flight, which is non-zero while
requests are outstanding, so the read comes back true and the assertion
fires. Without the assertion it is a plain out of bounds read.
This was hit in the field, on a virtio-blk disk whose backing chain ends
in an NBD node, with the virtqueues of that disk spread over three
iothreads. Two coroutines of one NBD node then run in different threads,
which is what the race needs: there is no yield point between the two
reads for the owner to squeeze into, so a single AioContext cannot
produce it.
Patch 3 is the fix, patches 1 and 2 are what I ran into on the way to
it. The order is dictated by patch 2: it routes every cookie to index
conversion through a helper which asserts the range, and for the cookie
of the reply in flight that assertion only holds once patch 1 stops the
error paths from leaving a value chosen by the server behind.
Reproduced with a scratch harness which drives one NBD client node from
two AioContexts against a real qemu-nbd. At -O2 gcc merges all three
reads of s->reply.cookie in nbd_receive_replies() into a single load, so
the race is not observable at all in such a build; the gdb output above
comes from an -O1 build of this branch with the two scratch commits on
top. The report itself came from a build with coverage instrumentation,
which is the kind of build that keeps the reads apart.
Signed-off-by: Denis V. Lunev <den@openvz.org>
Cc: Eric Blake <eblake@redhat.com>
Cc: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Denis V. Lunev (3):
block/nbd: clear reply.cookie when the reply is rejected
block/nbd: never index requests[] with an unchecked cookie
block/nbd: clear reply.cookie under receive_mutex
block/nbd.c | 53 +++++++++++++++++++++++++++++++++++------------------
1 file changed, 35 insertions(+), 18 deletions(-)
base-commit: e1705a25aff35635c360bbaba4c2731d019a422a
--
2.53.0
next reply other threads:[~2026-08-12 10:30 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-12 10:29 Denis V. Lunev [this message]
2026-08-12 10:29 ` [PATCH 1/3] block/nbd: clear reply.cookie when the reply is rejected Denis V. Lunev
2026-08-19 11:51 ` Vladimir Sementsov-Ogievskiy
2026-08-12 10:29 ` [PATCH 2/3] block/nbd: never index requests[] with an unchecked cookie Denis V. Lunev
2026-08-19 12:09 ` Vladimir Sementsov-Ogievskiy
2026-08-12 10:29 ` [PATCH 3/3] block/nbd: clear reply.cookie under receive_mutex Denis V. Lunev
2026-08-19 12:17 ` Vladimir Sementsov-Ogievskiy
2026-08-19 9:34 ` [PATCH 0/3] block/nbd: fix a race in reply processing Denis V. Lunev
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260812102906.894063-1-den@openvz.org \
--to=den@openvz.org \
--cc=eblake@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=vsementsov@yandex-team.ru \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.