OpenVZ / Virtuozzo kernel development (devel@openvz.org)
 help / color / mirror / Atom feed
From: Konstantin Khorenko <khorenko@virtuozzo.com>
To: Alexander Ivanov <alexander.ivanov@virtuozzo.com>,
	andrey.zhadchenko@virtuozzo.com
Cc: devel@openvz.org
Subject: Re: [Devel] [PATCH hci-8.1 0/3] drivers/vhost/blk: fix virtio-blk request header and payload parsing
Date: Thu, 29 Oct 2026 12:26:49 +0100	[thread overview]
Message-ID: <2f39ce07-cf48-4ebe-af40-58f3ff78587a@virtuozzo.com> (raw)
In-Reply-To: <20261021084610.1476738-1-alexander.ivanov@virtuozzo.com>

Hi Alexander,

The code in all three patches is fine, I have nothing to change there.
Two commit messages describe the old behaviour inaccurately, please fix
them in place for v2.

Patch 2, "take virtio_blk_outhdr only from the readable part":

> The request header was moved from the whole descriptor chain, so a
> chain with no readable part, or one shorter than the header, had header
> bytes read from buffers the guest marked device-writable.

The "shorter than the header" case was already rejected before the
patch: VHOST_MAX_METADATA_IOV is 1, so move_iovec() fills one target
segment and returns -1 when the header does not fit into the first
readable iovec, and the kick handler drops the chain as "too split".
Only a chain with no readable part at all had the header taken from a
writable buffer.

> Those bytes
> were also trimmed in place from the writable segments, shifting the
> status byte and the READ/GET_ID payload taken from them.

The status byte did not move: it was taken as the last byte of the
chain after req->len was computed. What shifted was the start of the
READ/GET_ID payload, by sizeof(hdr).

Suggested paragraph:

  The request header was moved from the whole descriptor chain, so a
  chain with no readable part had header bytes read from buffers the
  guest marked device-writable. Those bytes were also trimmed in place
  from the writable segments, shifting the start of the READ/GET_ID
  payload taken from them.

Patch 3, "take req->len from one side of the descriptor chain":

> Complete a read or write with VIRTIO_BLK_S_IOERR if its payload is
> empty, above ALIGN_DOWN(INT_MAX, SECTOR_SIZE) or, for a write, not a
> multiple of SECTOR_SIZE. Such requests used to fail in bio setup or
> hit a WARN_ONCE() and leave the guest request hanging. Drop the now
> unreachable WARN_ONCE().

Three things here.

"Such requests used to fail" is true only for the empty payload and the
unaligned write. A write above ALIGN_DOWN(INT_MAX, SECTOR_SIZE) was
never rejected before: req->len is size_t, the bios are split per
BIO_MAX_VECS and used_len for a write is one byte, so it was submitted
as is. The bound is a new restriction for writes and the message should
say so. For reads, the in_len > INT_MAX check still runs first, so a
read above INT_MAX keeps getting -EINVAL; the new bound only covers the
range below it.

"Leave the guest request hanging" understates it. On -EINVAL the kick
handler breaks out of the loop with the descriptor consumed and
notifications still disabled, so with EVENT_IDX the guest never kicks
again and the whole virtqueue stalls until QEMU resets it through
error_ctx.

The WARN_ONCE() was reachable from the guest: any write with an
unaligned length triggered it, and with panic_on_warn that panics the
host. That is the reason for the Fixes: 02ce37f62707 trailer and worth
one sentence, "now unreachable" is a side effect.

Suggested paragraphs:

  Complete a read or write with VIRTIO_BLK_S_IOERR if its payload is
  empty, above ALIGN_DOWN(INT_MAX, SECTOR_SIZE) or, for a write, not a
  multiple of SECTOR_SIZE. An empty payload used to fail in bio setup
  and an unaligned write hit a WARN_ONCE() reachable from the guest.
  In both cases the kick handler broke out with the descriptor consumed
  and notifications disabled, so the virtqueue stalled. Drop the
  WARN_ONCE().

  The size bound is new for writes: the readable side had no limit and
  a write of any size was submitted. Reads above INT_MAX still get
  -EINVAL from the in_len check, the bound only covers the range below
  it.

With the two messages fixed the series is good to go, no code changes
needed.

--
Best regards,

Konstantin Khorenko,
Virtuozzo Linux Kernel Team


_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

      parent reply	other threads:[~2026-10-29 11:28 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-21  8:46 Alexander Ivanov
2026-10-21  8:46 ` [Devel] [PATCH hci-8.1 1/3] drivers/vhost/blk: convert virtio_blk_outhdr fields to CPU byte order Alexander Ivanov
2026-10-21  8:49   ` no-reply
2026-10-21  8:46 ` [Devel] [PATCH hci-8.1 2/3] drivers/vhost/blk: take virtio_blk_outhdr only from the readable part Alexander Ivanov
2026-10-21  8:49   ` no-reply
2026-10-21  8:46 ` [Devel] [PATCH hci-8.1 3/3] drivers/vhost/blk: take req->len from one side of the descriptor chain Alexander Ivanov
2026-10-21  8:50   ` no-reply
2026-10-25 21:54 ` [Devel] [PATCH hci-8.1 0/3] drivers/vhost/blk: fix virtio-blk request header and payload parsing Andrey Zhadchenko
2026-10-29 11:26 ` Konstantin Khorenko [this message]

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=2f39ce07-cf48-4ebe-af40-58f3ff78587a@virtuozzo.com \
    --to=khorenko@virtuozzo.com \
    --cc=alexander.ivanov@virtuozzo.com \
    --cc=andrey.zhadchenko@virtuozzo.com \
    --cc=devel@openvz.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox