* [Qemu-devel] [PATCH 0/2] qemu-io: check the size of the I/O requests @ 2017-01-31 16:09 Alberto Garcia 2017-01-31 16:09 ` [Qemu-devel] [PATCH 1/2] qemu-io: don't allow I/O operations larger than INT_MAX Alberto Garcia 2017-01-31 16:09 ` [Qemu-devel] [PATCH 2/2] iov: assert that qiov->size doesn't exceed INT_MAX Alberto Garcia 0 siblings, 2 replies; 18+ messages in thread From: Alberto Garcia @ 2017-01-31 16:09 UTC (permalink / raw) To: qemu-devel; +Cc: qemu-block, Kevin Wolf, Max Reitz, Alberto Garcia Hi, qemu-io allows arbitrary values (up to SIZE_MAX) for the size of its I/O requests, but QEMU cannot handle anything larger than INT_MAX. $ qemu-io -c 'aio_write 0 2G' hd.qcow2 block/block-backend.c:1035: blk_aio_write_entry: Assertion `!rwco->qiov || rwco->qiov->size == acb->bytes' failed. $ qemu-io -c 'aio_read 0 1G 1G' hd.qcow2 block/block-backend.c:1024: blk_aio_read_entry: Assertion `rwco->qiov->size == acb->bytes' failed. This series checks that those values are within range and also adds assertions to qemu_iovec_add() and qemu_iovec_init_external() to detect these cases earlier. Regards, Berto Alberto Garcia (2): qemu-io: don't allow I/O operations larger than INT_MAX iov: assert that qiov->size doesn't exceed INT_MAX qemu-io-cmds.c | 21 ++++++++++++--------- util/iov.c | 7 ++++++- 2 files changed, 18 insertions(+), 10 deletions(-) -- 2.11.0 ^ permalink raw reply [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH 1/2] qemu-io: don't allow I/O operations larger than INT_MAX 2017-01-31 16:09 [Qemu-devel] [PATCH 0/2] qemu-io: check the size of the I/O requests Alberto Garcia @ 2017-01-31 16:09 ` Alberto Garcia 2017-01-31 16:31 ` Eric Blake ` (2 more replies) 2017-01-31 16:09 ` [Qemu-devel] [PATCH 2/2] iov: assert that qiov->size doesn't exceed INT_MAX Alberto Garcia 1 sibling, 3 replies; 18+ messages in thread From: Alberto Garcia @ 2017-01-31 16:09 UTC (permalink / raw) To: qemu-devel; +Cc: qemu-block, Kevin Wolf, Max Reitz, Alberto Garcia Passing a request size larger than INT_MAX to any of the I/O commands results in an error. While 'read' and 'write' handle the error correctly, 'aio_read' and 'aio_write' hit an assertion: blk_aio_read_entry: Assertion `rwco->qiov->size == acb->bytes' failed. The reason is that the QEMU I/O code cannot handle request sizes larger than INT_MAX, so this patch makes qemu-io check that all values are within range. Signed-off-by: Alberto Garcia <berto@igalia.com> --- qemu-io-cmds.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c index 95bcde1d88..d806a83076 100644 --- a/qemu-io-cmds.c +++ b/qemu-io-cmds.c @@ -388,9 +388,14 @@ create_iovec(BlockBackend *blk, QEMUIOVector *qiov, char **argv, int nr_iov, goto fail; } - if (len > SIZE_MAX) { - printf("Argument '%s' exceeds maximum size %llu\n", arg, - (unsigned long long)SIZE_MAX); + if (len > INT_MAX) { + printf("Argument '%s' exceeds maximum size %d\n", arg, INT_MAX); + goto fail; + } + + if (count > INT_MAX - len) { + printf("The total number of bytes exceed the maximum size %d\n", + INT_MAX); goto fail; } @@ -682,9 +687,8 @@ static int read_f(BlockBackend *blk, int argc, char **argv) if (count < 0) { print_cvtnum_err(count, argv[optind]); return 0; - } else if (count > SIZE_MAX) { - printf("length cannot exceed %" PRIu64 ", given %s\n", - (uint64_t) SIZE_MAX, argv[optind]); + } else if (count > INT_MAX) { + printf("length cannot exceed %d, given %s\n", INT_MAX, argv[optind]); return 0; } @@ -1004,9 +1008,8 @@ static int write_f(BlockBackend *blk, int argc, char **argv) if (count < 0) { print_cvtnum_err(count, argv[optind]); return 0; - } else if (count > SIZE_MAX) { - printf("length cannot exceed %" PRIu64 ", given %s\n", - (uint64_t) SIZE_MAX, argv[optind]); + } else if (count > INT_MAX) { + printf("length cannot exceed %d, given %s\n", INT_MAX, argv[optind]); return 0; } -- 2.11.0 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] qemu-io: don't allow I/O operations larger than INT_MAX 2017-01-31 16:09 ` [Qemu-devel] [PATCH 1/2] qemu-io: don't allow I/O operations larger than INT_MAX Alberto Garcia @ 2017-01-31 16:31 ` Eric Blake 2017-01-31 16:36 ` Alberto Garcia 2017-02-01 21:36 ` Max Reitz 2017-02-01 22:16 ` Max Reitz 2 siblings, 1 reply; 18+ messages in thread From: Eric Blake @ 2017-01-31 16:31 UTC (permalink / raw) To: Alberto Garcia, qemu-devel; +Cc: Kevin Wolf, qemu-block, Max Reitz [-- Attachment #1: Type: text/plain, Size: 1152 bytes --] On 01/31/2017 10:09 AM, Alberto Garcia wrote: > Passing a request size larger than INT_MAX to any of the I/O commands > results in an error. While 'read' and 'write' handle the error > correctly, 'aio_read' and 'aio_write' hit an assertion: > > blk_aio_read_entry: Assertion `rwco->qiov->size == acb->bytes' failed. > > The reason is that the QEMU I/O code cannot handle request sizes > larger than INT_MAX, so this patch makes qemu-io check that all values > are within range. Ideally, it would be nice to fix the block layer to allow larger requests (since we already have code to auto-fragment down to device limits, we should be able to rely on that code instead of having to duplicate artificial constraints everywhere else in the tree). But that's a bigger task, and this is a good patch in the interim. > > Signed-off-by: Alberto Garcia <berto@igalia.com> > --- > qemu-io-cmds.c | 21 ++++++++++++--------- > 1 file changed, 12 insertions(+), 9 deletions(-) Reviewed-by: Eric Blake <eblake@redhat.com> -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 604 bytes --] ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] qemu-io: don't allow I/O operations larger than INT_MAX 2017-01-31 16:31 ` Eric Blake @ 2017-01-31 16:36 ` Alberto Garcia 2017-01-31 16:41 ` Eric Blake 0 siblings, 1 reply; 18+ messages in thread From: Alberto Garcia @ 2017-01-31 16:36 UTC (permalink / raw) To: Eric Blake, qemu-devel; +Cc: Kevin Wolf, qemu-block, Max Reitz On Tue 31 Jan 2017 05:31:32 PM CET, Eric Blake wrote: > Ideally, it would be nice to fix the block layer to allow larger > requests (since we already have code to auto-fragment down to device > limits, we should be able to rely on that code instead of having to > duplicate artificial constraints everywhere else in the tree). But > that's a bigger task, and this is a good patch in the interim. Related question: what's the largest request than a guest can theoretically submit? Berto ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] qemu-io: don't allow I/O operations larger than INT_MAX 2017-01-31 16:36 ` Alberto Garcia @ 2017-01-31 16:41 ` Eric Blake 2017-01-31 18:11 ` Alberto Garcia 0 siblings, 1 reply; 18+ messages in thread From: Eric Blake @ 2017-01-31 16:41 UTC (permalink / raw) To: Alberto Garcia, qemu-devel; +Cc: Kevin Wolf, qemu-block, Max Reitz [-- Attachment #1: Type: text/plain, Size: 1034 bytes --] On 01/31/2017 10:36 AM, Alberto Garcia wrote: > On Tue 31 Jan 2017 05:31:32 PM CET, Eric Blake wrote: > >> Ideally, it would be nice to fix the block layer to allow larger >> requests (since we already have code to auto-fragment down to device >> limits, we should be able to rely on that code instead of having to >> duplicate artificial constraints everywhere else in the tree). But >> that's a bigger task, and this is a good patch in the interim. > > Related question: what's the largest request than a guest can > theoretically submit? off_t supports up to 2^63 (not 2^64, because it is a signed type). Ideally, we should be constrained only by the disk size (as no one actually has 2^63 bytes of storage available), by using uint64_t offset AND length in all our APIs; but right now, we still have a lot of 32-bit length issues, and often signed length limiting us to 2^31 depending on the API. -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 604 bytes --] ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] qemu-io: don't allow I/O operations larger than INT_MAX 2017-01-31 16:41 ` Eric Blake @ 2017-01-31 18:11 ` Alberto Garcia 2017-01-31 22:33 ` Max Reitz 0 siblings, 1 reply; 18+ messages in thread From: Alberto Garcia @ 2017-01-31 18:11 UTC (permalink / raw) To: Eric Blake, qemu-devel; +Cc: Kevin Wolf, qemu-block, Max Reitz On Tue 31 Jan 2017 05:41:23 PM CET, Eric Blake <eblake@redhat.com> wrote: >>> Ideally, it would be nice to fix the block layer to allow larger >>> requests (since we already have code to auto-fragment down to device >>> limits, we should be able to rely on that code instead of having to >>> duplicate artificial constraints everywhere else in the tree). But >>> that's a bigger task, and this is a good patch in the interim. >> >> Related question: what's the largest request than a guest can >> theoretically submit? > > off_t supports up to 2^63 (not 2^64, because it is a signed type). > Ideally, we should be constrained only by the disk size (as no one > actually has 2^63 bytes of storage available), by using uint64_t > offset AND length in all our APIs; but right now, we still have a lot > of 32-bit length issues, and often signed length limiting us to 2^31 > depending on the API. My question was more like: what happens if the guest submits a request with the maximum possible size? Does QEMU handle that correctly? Berto ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] qemu-io: don't allow I/O operations larger than INT_MAX 2017-01-31 18:11 ` Alberto Garcia @ 2017-01-31 22:33 ` Max Reitz 0 siblings, 0 replies; 18+ messages in thread From: Max Reitz @ 2017-01-31 22:33 UTC (permalink / raw) To: Alberto Garcia, Eric Blake, qemu-devel; +Cc: Kevin Wolf, qemu-block [-- Attachment #1: Type: text/plain, Size: 1213 bytes --] On 31.01.2017 19:11, Alberto Garcia wrote: > On Tue 31 Jan 2017 05:41:23 PM CET, Eric Blake <eblake@redhat.com> wrote: > >>>> Ideally, it would be nice to fix the block layer to allow larger >>>> requests (since we already have code to auto-fragment down to device >>>> limits, we should be able to rely on that code instead of having to >>>> duplicate artificial constraints everywhere else in the tree). But >>>> that's a bigger task, and this is a good patch in the interim. >>> >>> Related question: what's the largest request than a guest can >>> theoretically submit? >> >> off_t supports up to 2^63 (not 2^64, because it is a signed type). >> Ideally, we should be constrained only by the disk size (as no one >> actually has 2^63 bytes of storage available), by using uint64_t >> offset AND length in all our APIs; but right now, we still have a lot >> of 32-bit length issues, and often signed length limiting us to 2^31 >> depending on the API. > > My question was more like: what happens if the guest submits a request > with the maximum possible size? Does QEMU handle that correctly? As far as I'm aware we rely on the device emulation code to split the request. Max [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 512 bytes --] ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] qemu-io: don't allow I/O operations larger than INT_MAX 2017-01-31 16:09 ` [Qemu-devel] [PATCH 1/2] qemu-io: don't allow I/O operations larger than INT_MAX Alberto Garcia 2017-01-31 16:31 ` Eric Blake @ 2017-02-01 21:36 ` Max Reitz 2017-02-01 21:49 ` Alberto Garcia 2017-02-01 22:16 ` Max Reitz 2 siblings, 1 reply; 18+ messages in thread From: Max Reitz @ 2017-02-01 21:36 UTC (permalink / raw) To: Alberto Garcia, qemu-devel; +Cc: qemu-block, Kevin Wolf [-- Attachment #1: Type: text/plain, Size: 2574 bytes --] On 31.01.2017 17:09, Alberto Garcia wrote: > Passing a request size larger than INT_MAX to any of the I/O commands > results in an error. While 'read' and 'write' handle the error > correctly, 'aio_read' and 'aio_write' hit an assertion: > > blk_aio_read_entry: Assertion `rwco->qiov->size == acb->bytes' failed. > > The reason is that the QEMU I/O code cannot handle request sizes > larger than INT_MAX, so this patch makes qemu-io check that all values > are within range. > > Signed-off-by: Alberto Garcia <berto@igalia.com> > --- > qemu-io-cmds.c | 21 ++++++++++++--------- > 1 file changed, 12 insertions(+), 9 deletions(-) > > diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c > index 95bcde1d88..d806a83076 100644 > --- a/qemu-io-cmds.c > +++ b/qemu-io-cmds.c > @@ -388,9 +388,14 @@ create_iovec(BlockBackend *blk, QEMUIOVector *qiov, char **argv, int nr_iov, > goto fail; > } > > - if (len > SIZE_MAX) { > - printf("Argument '%s' exceeds maximum size %llu\n", arg, > - (unsigned long long)SIZE_MAX); > + if (len > INT_MAX) { > + printf("Argument '%s' exceeds maximum size %d\n", arg, INT_MAX); > + goto fail; > + } > + > + if (count > INT_MAX - len) { How about using BDRV_REQUEST_MAX_BYTES instead? (not yet in master, just in my block branch) Max > + printf("The total number of bytes exceed the maximum size %d\n", > + INT_MAX); > goto fail; > } > > @@ -682,9 +687,8 @@ static int read_f(BlockBackend *blk, int argc, char **argv) > if (count < 0) { > print_cvtnum_err(count, argv[optind]); > return 0; > - } else if (count > SIZE_MAX) { > - printf("length cannot exceed %" PRIu64 ", given %s\n", > - (uint64_t) SIZE_MAX, argv[optind]); > + } else if (count > INT_MAX) { > + printf("length cannot exceed %d, given %s\n", INT_MAX, argv[optind]); > return 0; > } > > @@ -1004,9 +1008,8 @@ static int write_f(BlockBackend *blk, int argc, char **argv) > if (count < 0) { > print_cvtnum_err(count, argv[optind]); > return 0; > - } else if (count > SIZE_MAX) { > - printf("length cannot exceed %" PRIu64 ", given %s\n", > - (uint64_t) SIZE_MAX, argv[optind]); > + } else if (count > INT_MAX) { > + printf("length cannot exceed %d, given %s\n", INT_MAX, argv[optind]); > return 0; > } > > [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 512 bytes --] ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] qemu-io: don't allow I/O operations larger than INT_MAX 2017-02-01 21:36 ` Max Reitz @ 2017-02-01 21:49 ` Alberto Garcia 0 siblings, 0 replies; 18+ messages in thread From: Alberto Garcia @ 2017-02-01 21:49 UTC (permalink / raw) To: Max Reitz, qemu-devel; +Cc: qemu-block, Kevin Wolf On Wed 01 Feb 2017 10:36:20 PM CET, Max Reitz <mreitz@redhat.com> wrote: >> + if (count > INT_MAX - len) { > > How about using BDRV_REQUEST_MAX_BYTES instead? > > (not yet in master, just in my block branch) Sounds good to me, feel free to edit my patch directly. Berto ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] qemu-io: don't allow I/O operations larger than INT_MAX 2017-01-31 16:09 ` [Qemu-devel] [PATCH 1/2] qemu-io: don't allow I/O operations larger than INT_MAX Alberto Garcia 2017-01-31 16:31 ` Eric Blake 2017-02-01 21:36 ` Max Reitz @ 2017-02-01 22:16 ` Max Reitz 2017-02-02 8:52 ` Alberto Garcia 2 siblings, 1 reply; 18+ messages in thread From: Max Reitz @ 2017-02-01 22:16 UTC (permalink / raw) To: Alberto Garcia, qemu-devel; +Cc: qemu-block, Kevin Wolf [-- Attachment #1: Type: text/plain, Size: 1001 bytes --] On 31.01.2017 17:09, Alberto Garcia wrote: > Passing a request size larger than INT_MAX to any of the I/O commands > results in an error. While 'read' and 'write' handle the error > correctly, 'aio_read' and 'aio_write' hit an assertion: > > blk_aio_read_entry: Assertion `rwco->qiov->size == acb->bytes' failed. > > The reason is that the QEMU I/O code cannot handle request sizes > larger than INT_MAX, so this patch makes qemu-io check that all values > are within range. > > Signed-off-by: Alberto Garcia <berto@igalia.com> > --- > qemu-io-cmds.c | 21 ++++++++++++--------- > 1 file changed, 12 insertions(+), 9 deletions(-) Thanks, applied to my block tree, with %s/INT_MAX/BDRV_REQUEST_MAX_BYTES/g: https://github.com/XanClic/qemu/commits/block (Maybe you should take a quick glance on whether all of the changes are really OK for you, the commit currently resides under https://github.com/XanClic/qemu/commit/beaf099368f91eb44ebd49e863c57bc0ff80659f ) Max [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 512 bytes --] ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] qemu-io: don't allow I/O operations larger than INT_MAX 2017-02-01 22:16 ` Max Reitz @ 2017-02-02 8:52 ` Alberto Garcia 2017-02-03 19:00 ` Max Reitz 0 siblings, 1 reply; 18+ messages in thread From: Alberto Garcia @ 2017-02-02 8:52 UTC (permalink / raw) To: Max Reitz, qemu-devel; +Cc: qemu-block, Kevin Wolf On Wed 01 Feb 2017 11:16:38 PM CET, Max Reitz <mreitz@redhat.com> wrote: > Thanks, applied to my block tree, with > %s/INT_MAX/BDRV_REQUEST_MAX_BYTES/g: I think you can use %d to print BDRV_REQUEST_MAX_BYTES, after all the definition guarantees that it won't be larger than MIN(SIZE_MAX,INT_MAX) But it's fine with me if you prefer to cast it to uint64_t, that way it'll remain valid if BDRV_REQUEST_MAX_BYTES is increased in the future. Berto ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] qemu-io: don't allow I/O operations larger than INT_MAX 2017-02-02 8:52 ` Alberto Garcia @ 2017-02-03 19:00 ` Max Reitz 0 siblings, 0 replies; 18+ messages in thread From: Max Reitz @ 2017-02-03 19:00 UTC (permalink / raw) To: Alberto Garcia, qemu-devel; +Cc: qemu-block, Kevin Wolf [-- Attachment #1: Type: text/plain, Size: 509 bytes --] On 02.02.2017 09:52, Alberto Garcia wrote: > On Wed 01 Feb 2017 11:16:38 PM CET, Max Reitz <mreitz@redhat.com> wrote: > >> Thanks, applied to my block tree, with >> %s/INT_MAX/BDRV_REQUEST_MAX_BYTES/g: > > I think you can use %d to print BDRV_REQUEST_MAX_BYTES, after all the > definition guarantees that it won't be larger than MIN(SIZE_MAX,INT_MAX) I'm not sure what C makes of that expression. I'd think it becomes a size_t, probably, regardless of whether it would fit into an int. Max [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 512 bytes --] ^ permalink raw reply [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH 2/2] iov: assert that qiov->size doesn't exceed INT_MAX 2017-01-31 16:09 [Qemu-devel] [PATCH 0/2] qemu-io: check the size of the I/O requests Alberto Garcia 2017-01-31 16:09 ` [Qemu-devel] [PATCH 1/2] qemu-io: don't allow I/O operations larger than INT_MAX Alberto Garcia @ 2017-01-31 16:09 ` Alberto Garcia 2017-01-31 16:45 ` Eric Blake 2017-02-01 21:51 ` Max Reitz 1 sibling, 2 replies; 18+ messages in thread From: Alberto Garcia @ 2017-01-31 16:09 UTC (permalink / raw) To: qemu-devel; +Cc: qemu-block, Kevin Wolf, Max Reitz, Alberto Garcia The type of qiov->size is size_t but the QEMU I/O code uses int all over the place to measure request sizes. Overflows are likely going to be detected by any of the many assert(qiov->size == nbytes), where nbytes is an int, but let's add proper checks in the QEMUIOVector initialization, which is where it belongs. Signed-off-by: Alberto Garcia <berto@igalia.com> --- util/iov.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/util/iov.c b/util/iov.c index 74e6ca8ed7..6b5cc9203c 100644 --- a/util/iov.c +++ b/util/iov.c @@ -283,13 +283,18 @@ void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov) qiov->niov = niov; qiov->nalloc = -1; qiov->size = 0; - for (i = 0; i < niov; i++) + for (i = 0; i < niov; i++) { + assert(iov[i].iov_len <= INT_MAX); + assert(qiov->size <= INT_MAX - iov[i].iov_len); qiov->size += iov[i].iov_len; + } } void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len) { assert(qiov->nalloc != -1); + assert(len <= INT_MAX); + assert(qiov->size <= INT_MAX - len); if (qiov->niov == qiov->nalloc) { qiov->nalloc = 2 * qiov->nalloc + 1; -- 2.11.0 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH 2/2] iov: assert that qiov->size doesn't exceed INT_MAX 2017-01-31 16:09 ` [Qemu-devel] [PATCH 2/2] iov: assert that qiov->size doesn't exceed INT_MAX Alberto Garcia @ 2017-01-31 16:45 ` Eric Blake 2017-02-01 21:51 ` Max Reitz 1 sibling, 0 replies; 18+ messages in thread From: Eric Blake @ 2017-01-31 16:45 UTC (permalink / raw) To: Alberto Garcia, qemu-devel; +Cc: Kevin Wolf, qemu-block, Max Reitz [-- Attachment #1: Type: text/plain, Size: 676 bytes --] On 01/31/2017 10:09 AM, Alberto Garcia wrote: > The type of qiov->size is size_t but the QEMU I/O code uses int all > over the place to measure request sizes. Overflows are likely going > to be detected by any of the many assert(qiov->size == nbytes), where > nbytes is an int, but let's add proper checks in the QEMUIOVector > initialization, which is where it belongs. > > Signed-off-by: Alberto Garcia <berto@igalia.com> > --- > util/iov.c | 7 ++++++- > 1 file changed, 6 insertions(+), 1 deletion(-) Reviewed-by: Eric Blake <eblake@redhat.com> -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 604 bytes --] ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH 2/2] iov: assert that qiov->size doesn't exceed INT_MAX 2017-01-31 16:09 ` [Qemu-devel] [PATCH 2/2] iov: assert that qiov->size doesn't exceed INT_MAX Alberto Garcia 2017-01-31 16:45 ` Eric Blake @ 2017-02-01 21:51 ` Max Reitz 2017-02-01 21:55 ` Alberto Garcia 1 sibling, 1 reply; 18+ messages in thread From: Max Reitz @ 2017-02-01 21:51 UTC (permalink / raw) To: Alberto Garcia, qemu-devel; +Cc: qemu-block, Kevin Wolf [-- Attachment #1: Type: text/plain, Size: 2028 bytes --] On 31.01.2017 17:09, Alberto Garcia wrote: > The type of qiov->size is size_t but the QEMU I/O code uses int all > over the place to measure request sizes. Overflows are likely going > to be detected by any of the many assert(qiov->size == nbytes), where > nbytes is an int, but let's add proper checks in the QEMUIOVector > initialization, which is where it belongs. I'm not entirely convinced that's where it belongs. In my opinion, the BlockBackend functions should all get uint64_t size parameters and let blk_check_byte_request() do the rest. I wouldn't mind too much if blk_check_byte_requests() did assertions instead of returning -EIO. But the thing with the I/O vector is that it's not exclusively used for the block layer. I can see at least hw/9pfs/9p.c and hw/usb/core.c using it internally. The assertion probably makes sense even for them, considering that size_t does not have a constant size. But I'm not entirely sold that the I/O vector creation is actually the place where the assertions belong. Max > > Signed-off-by: Alberto Garcia <berto@igalia.com> > --- > util/iov.c | 7 ++++++- > 1 file changed, 6 insertions(+), 1 deletion(-) > > diff --git a/util/iov.c b/util/iov.c > index 74e6ca8ed7..6b5cc9203c 100644 > --- a/util/iov.c > +++ b/util/iov.c > @@ -283,13 +283,18 @@ void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov) > qiov->niov = niov; > qiov->nalloc = -1; > qiov->size = 0; > - for (i = 0; i < niov; i++) > + for (i = 0; i < niov; i++) { > + assert(iov[i].iov_len <= INT_MAX); > + assert(qiov->size <= INT_MAX - iov[i].iov_len); > qiov->size += iov[i].iov_len; > + } > } > > void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len) > { > assert(qiov->nalloc != -1); > + assert(len <= INT_MAX); > + assert(qiov->size <= INT_MAX - len); > > if (qiov->niov == qiov->nalloc) { > qiov->nalloc = 2 * qiov->nalloc + 1; > [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 512 bytes --] ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH 2/2] iov: assert that qiov->size doesn't exceed INT_MAX 2017-02-01 21:51 ` Max Reitz @ 2017-02-01 21:55 ` Alberto Garcia 2017-02-01 21:56 ` Max Reitz 0 siblings, 1 reply; 18+ messages in thread From: Alberto Garcia @ 2017-02-01 21:55 UTC (permalink / raw) To: Max Reitz, qemu-devel; +Cc: qemu-block, Kevin Wolf On Wed 01 Feb 2017 10:51:01 PM CET, Max Reitz <mreitz@redhat.com> wrote: > The assertion probably makes sense even for them, considering that > size_t does not have a constant size. But I'm not entirely sold that > the I/O vector creation is actually the place where the assertions > belong. I was actually just reading virtio_blk_handle_request() and I see that the I/O vector is initialized before the check for the maximum request size that returns VIRTIO_BLK_S_IOERR. So you're probably right and it's safer not to add that assertion. Berto ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH 2/2] iov: assert that qiov->size doesn't exceed INT_MAX 2017-02-01 21:55 ` Alberto Garcia @ 2017-02-01 21:56 ` Max Reitz 2017-02-01 22:00 ` Alberto Garcia 0 siblings, 1 reply; 18+ messages in thread From: Max Reitz @ 2017-02-01 21:56 UTC (permalink / raw) To: Alberto Garcia, qemu-devel; +Cc: qemu-block, Kevin Wolf [-- Attachment #1: Type: text/plain, Size: 701 bytes --] On 01.02.2017 22:55, Alberto Garcia wrote: > On Wed 01 Feb 2017 10:51:01 PM CET, Max Reitz <mreitz@redhat.com> wrote: > >> The assertion probably makes sense even for them, considering that >> size_t does not have a constant size. But I'm not entirely sold that >> the I/O vector creation is actually the place where the assertions >> belong. > > I was actually just reading virtio_blk_handle_request() and I see that > the I/O vector is initialized before the check for the maximum request > size that returns VIRTIO_BLK_S_IOERR. > > So you're probably right and it's safer not to add that assertion. So... Apply patch 1 and hope we do everything right in the future? :-) Max [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 512 bytes --] ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH 2/2] iov: assert that qiov->size doesn't exceed INT_MAX 2017-02-01 21:56 ` Max Reitz @ 2017-02-01 22:00 ` Alberto Garcia 0 siblings, 0 replies; 18+ messages in thread From: Alberto Garcia @ 2017-02-01 22:00 UTC (permalink / raw) To: Max Reitz, qemu-devel; +Cc: qemu-block, Kevin Wolf On Wed 01 Feb 2017 10:56:29 PM CET, Max Reitz <mreitz@redhat.com> wrote: >> I was actually just reading virtio_blk_handle_request() and I see >> that the I/O vector is initialized before the check for the maximum >> request size that returns VIRTIO_BLK_S_IOERR. >> >> So you're probably right and it's safer not to add that assertion. > > So... Apply patch 1 and hope we do everything right in the future? :-) I think patch 1 is definitely necessary and enough to solve the crash that I reported. Tomorrow I'll think about what to do in place of the second one :-) Berto ^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2017-02-03 19:00 UTC | newest] Thread overview: 18+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2017-01-31 16:09 [Qemu-devel] [PATCH 0/2] qemu-io: check the size of the I/O requests Alberto Garcia 2017-01-31 16:09 ` [Qemu-devel] [PATCH 1/2] qemu-io: don't allow I/O operations larger than INT_MAX Alberto Garcia 2017-01-31 16:31 ` Eric Blake 2017-01-31 16:36 ` Alberto Garcia 2017-01-31 16:41 ` Eric Blake 2017-01-31 18:11 ` Alberto Garcia 2017-01-31 22:33 ` Max Reitz 2017-02-01 21:36 ` Max Reitz 2017-02-01 21:49 ` Alberto Garcia 2017-02-01 22:16 ` Max Reitz 2017-02-02 8:52 ` Alberto Garcia 2017-02-03 19:00 ` Max Reitz 2017-01-31 16:09 ` [Qemu-devel] [PATCH 2/2] iov: assert that qiov->size doesn't exceed INT_MAX Alberto Garcia 2017-01-31 16:45 ` Eric Blake 2017-02-01 21:51 ` Max Reitz 2017-02-01 21:55 ` Alberto Garcia 2017-02-01 21:56 ` Max Reitz 2017-02-01 22:00 ` Alberto Garcia
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).