From: Max Reitz <mreitz@redhat.com>
To: Paolo Bonzini <pbonzini@redhat.com>, qemu-devel@nongnu.org
Cc: Daniel Henrique Barboza <danielhb413@gmail.com>
Subject: Re: [Qemu-devel] [PATCH 3/4] scsi-generic: avoid invalid access to struct when emulating block limits
Date: Tue, 6 Nov 2018 03:16:43 +0100 [thread overview]
Message-ID: <341d56df-d0f4-1730-57a9-89ebb02e5ec9@redhat.com> (raw)
In-Reply-To: <20181029173437.32559-4-pbonzini@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 4774 bytes --]
On 29.10.18 18:34, Paolo Bonzini wrote:
> Emulation of the block limits VPD page called back into scsi-disk.c,
> which however expected the request to be for a SCSIDiskState and
> accessed a scsi-generic device outside the bounds of its struct
> (namely to retrieve s->max_unmap_size and s->max_io_size).
>
> To avoid this, move the emulation code to a separate function that
> takes a new SCSIBlockLimits struct and marshals it into the VPD
> response format.
>
> Reported-by: Max Reitz <mreitz@redhat.com>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> hw/scsi/Makefile.objs | 2 +-
> hw/scsi/emulation.c | 42 +++++++++++++++++
> hw/scsi/scsi-disk.c | 92 ++++++++-----------------------------
> hw/scsi/scsi-generic.c | 22 +++++++--
> include/hw/scsi/emulation.h | 16 +++++++
> include/hw/scsi/scsi.h | 1 -
> 6 files changed, 98 insertions(+), 77 deletions(-)
> create mode 100644 hw/scsi/emulation.c
> create mode 100644 include/hw/scsi/emulation.h
>
[...]
> diff --git a/hw/scsi/emulation.c b/hw/scsi/emulation.c
> new file mode 100644
> index 0000000000..94c2254bb4
> --- /dev/null
> +++ b/hw/scsi/emulation.c
> @@ -0,0 +1,42 @@
> +#include "qemu/osdep.h"
> +#include "qemu/units.h"
> +#include "qemu/bswap.h"
> +#include "hw/scsi/emulation.h"
> +
> +int scsi_emulate_block_limits(uint8_t *outbuf, SCSIBlockLimits *bl)
I'd make @bl a const *, but it's not like qemu is the kind of code base
to complain about strict const-ness.
> +{
> + /* required VPD size with unmap support */
> + memset(outbuf, 0, 0x3C);
Upper case hex here...
> +
> + outbuf[0] = bl->wsnz; /* wsnz */
> +
> + if (bl->max_io_sectors) {
> + /* optimal transfer length granularity. This field and the optimal
> + * transfer length can't be greater than maximum transfer length.
> + */
> + stw_be_p(outbuf + 2, MIN(bl->min_io_size, bl->max_io_sectors));
> +
> + /* maximum transfer length */
> + stl_be_p(outbuf + 4, bl->max_io_sectors);
> +
> + /* optimal transfer length */
> + stl_be_p(outbuf + 8, MIN(bl->opt_io_size, bl->max_io_sectors));
> + } else {
> + stw_be_p(outbuf + 2, bl->min_io_size);
> + stl_be_p(outbuf + 8, bl->opt_io_size);
> + }
> +
> + /* max unmap LBA count */
> + stl_be_p(outbuf + 16, bl->max_unmap_sectors);
> +
> + /* max unmap descriptors */
> + stl_be_p(outbuf + 20, bl->max_unmap_descr);
> +
> + /* optimal unmap granularity; alignment is zero */
> + stl_be_p(outbuf + 24, bl->unmap_sectors);
> +
> + /* max write same size, make it the same as maximum transfer length */
> + stl_be_p(outbuf + 36, bl->max_io_sectors);
> +
> + return 0x3c;
...and lower case here? (Sorry, I couldn't just bear it.)
> +}
[...]
> diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
> index c5497bbea8..8fc74ef0bd 100644
> --- a/hw/scsi/scsi-generic.c
> +++ b/hw/scsi/scsi-generic.c
> @@ -16,6 +16,7 @@
> #include "qemu-common.h"
> #include "qemu/error-report.h"
> #include "hw/scsi/scsi.h"
> +#include "hw/scsi/emulation.h"
> #include "sysemu/block-backend.h"
>
> #ifdef __linux__
> @@ -209,9 +210,24 @@ static void scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s)
> }
> }
>
> -static int scsi_emulate_block_limits(SCSIGenericReq *r)
> +static int scsi_generic_emulate_block_limits(SCSIGenericReq *r, SCSIDevice *s)
> {
> - r->buflen = scsi_disk_emulate_vpd_page(&r->req, r->buf);
> + int len, buflen;
buflen is unused, so this does not compile for me.
> + uint8_t buf[64];
> +
> + SCSIBlockLimits bl = {
> + .max_io_sectors = blk_get_max_transfer(s->conf.blk) / s->blocksize
> + };
> +
> + memset(r->buf, 0, r->buflen);
> + stb_p(buf, s->type);
> + stb_p(buf + 1, 0xb0);
> + len = scsi_emulate_block_limits(buf + 4, &bl);
> + assert(len <= sizeof(buf) - 4);
Let's hope our stack grows downwards, otherwise we'll never get back
here if there was an overflow. Maybe it would be better to pass the
buffer length to scsi_emulate_block_limits() and then move the assertion
there.
Or if you know that qemu does not support any architecture ABIs where
the stack can grow up, that's OK, too.
With buflen dropped, and you taking full responsibility for any future
bugs on ABIs with upwards stacks when someone extended
scsi_emulate_block_limits(), forgetting to adjust the buffer size here
(:-)):
Reviewed-by: Max Reitz <mreitz@redhat.com>
> + stw_be_p(buf + 2, len);
> +
> + memcpy(r->buf, buf, MIN(r->buflen, len + 4));
> +
> r->io_header.sb_len_wr = 0;
>
> /*
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
next prev parent reply other threads:[~2018-11-06 2:26 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-10-29 17:34 [Qemu-devel] [PATCH 0/4] scsi-generic: fixes for Block Limits emulation Paolo Bonzini
2018-10-29 17:34 ` [Qemu-devel] [PATCH 1/4] scsi-generic: keep VPD page list sorted Paolo Bonzini
2018-11-06 1:45 ` Max Reitz
2018-11-06 15:39 ` Daniel Henrique Barboza
2018-10-29 17:34 ` [Qemu-devel] [PATCH 2/4] scsi-generic: avoid out-of-bounds access to VPD page list Paolo Bonzini
2018-10-30 21:26 ` Philippe Mathieu-Daudé
2018-11-06 1:52 ` Max Reitz
2018-11-06 15:40 ` Daniel Henrique Barboza
2018-10-29 17:34 ` [Qemu-devel] [PATCH 3/4] scsi-generic: avoid invalid access to struct when emulating block limits Paolo Bonzini
2018-11-06 2:16 ` Max Reitz [this message]
2018-11-06 9:44 ` Paolo Bonzini
2018-10-29 17:34 ` [Qemu-devel] [PATCH 4/4] scsi-generic: do not do VPD emulation for sense other than ILLEGAL_REQUEST Paolo Bonzini
2018-11-06 2:22 ` Max Reitz
2018-10-31 23:17 ` [Qemu-devel] [PATCH 0/4] scsi-generic: fixes for Block Limits emulation no-reply
2018-10-31 23:27 ` no-reply
2018-11-06 15:31 ` no-reply
2018-11-06 15:42 ` no-reply
2018-11-06 15:54 ` Daniel Henrique Barboza
2018-11-06 18:54 ` Paolo Bonzini
2018-11-07 11:36 ` no-reply
2018-11-07 11:46 ` no-reply
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=341d56df-d0f4-1730-57a9-89ebb02e5ec9@redhat.com \
--to=mreitz@redhat.com \
--cc=danielhb413@gmail.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.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;
as well as URLs for NNTP newsgroup(s).