Re: [Libguestfs] [libnbd PATCH v2 5/6] block_status: Fix assertion on bad 64-bit block status reply

2023-09-22 Thread Laszlo Ersek
On 9/21/23 22:58, Eric Blake wrote:
> If a server replies to a block status command with an invalid count in
> NBD_REPLY_TYPE_BLOCK_STATUS_EXT, we correctly detect the server's
> error, but fail to mark that we've consumed enough data off the wire
> to resync back to the server's next reply.  Rich's fuzzing run
> initially found this, but I was able to quickly write a one-byte patch
> on top of my pending qemu patches [1] to reproduce it:
> 
> [1] https://lists.gnu.org/archive/html/qemu-devel/2023-08/msg05231.html
> 
> | diff --git i/nbd/server.c w/nbd/server.c
> | index 898580a9b0b..bd8d46ba3c4 100644
> | --- i/nbd/server.c
> | +++ w/nbd/server.c
> | @@ -2326,7 +2326,7 @@ nbd_co_send_extents(NBDClient *client, NBDRequest 
> *request, NBDExtentArray *ea,
> |  iov[1].iov_base = _ext;
> |  iov[1].iov_len = sizeof(meta_ext);
> |  stl_be_p(_ext.context_id, context_id);
> | -stl_be_p(_ext.count, ea->count);
> | +stl_be_p(_ext.count, !ea->count);
> |
> |  nbd_extent_array_convert_to_be(ea);
> |  iov[2].iov_base = ea->extents;
> 
> then with a just-built 'qemu-nbd -f raw -r file -t &' running, we have
> pre-patch:
> 
> $ ./run nbdsh --base -u nbd://localhost -c - <<\EOF
>> def f(*k):
>>  pass
>> try:
>>  h.block_status(1,0,f)
>> except nbd.Error as ex:
>>  print(ex.string)
>> h.shutdown()
>> EOF
> nbdsh: generator/states-reply-chunk.c:701: 
> enter_STATE_REPLY_CHUNK_REPLY_FINISH: Assertion `h->payload_left == 0' failed.
> Aborted (core dumped)
> 
> vs. post-patch:
> 
> $ ./run nbdsh --base -u nbd://localhost -c - <<\EOF
>> def f(*k):
>>  pass
>> try:
>>  h.block_status(1,0,f)
>> except nbd.Error as ex:
>>  print(ex.string)
>> h.shutdown()
>> EOF
> nbd_block_status: block-status: command failed: Protocol error
> 
> Appears to be a casualty of rebasing: I added h->payload_left
> verification fairly late in the game, then floated it earlier in the
> series, and missed a spot where I added a state machine jump to RESYNC
> without having updated h->payload_left.  An audit of h->hlen
> modification sites show that all other chunked reads updated
> h->payload_left appropriately (often in the next statement, but
> sometimes in a later state when that made logic easier).
> 
> Requires a non-compliant server, and only possible when extended
> headers are negotiated, which does not affect any stable released
> libnbd.  Thus, there is no reason to create a CVE, although since I
> will already be doing a security info email about previous patches
> also addressing fuzzer findings, I can mention this at the same time.
> 
> Fixes: ab992766cd ("block_status: Accept 64-bit extents during block status")
> Thanks: Richard W.M. Jones 
> Signed-off-by: Eric Blake 
> ---
>  generator/states-reply-chunk.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/generator/states-reply-chunk.c b/generator/states-reply-chunk.c
> index 20407d91..5a31c192 100644
> --- a/generator/states-reply-chunk.c
> +++ b/generator/states-reply-chunk.c
> @@ -476,6 +476,7 @@  REPLY.CHUNK_REPLY.RECV_BS_HEADER:
>if (h->bs_count != be32toh (h->sbuf.reply.payload.bs_hdr_64.count)) {
>  h->rbuf = NULL;
>  h->rlen = h->payload_left;
> +h->payload_left = 0;
>  SET_NEXT_STATE (%RESYNC);
>  return 0;
>}

Right, this seems consistent with other transitions to RESYNC (we zero
out payload_left in all those locations), and after we go from RESYNC to
FINISH, FINISH asserts the zero value.

Reviewed-by: Laszlo Ersek 

___
Libguestfs mailing list
Libguestfs@redhat.com
https://listman.redhat.com/mailman/listinfo/libguestfs



Re: [Libguestfs] [libnbd PATCH v2 5/6] block_status: Fix assertion on bad 64-bit block status reply

2023-09-21 Thread Richard W.M. Jones
On Thu, Sep 21, 2023 at 03:58:04PM -0500, Eric Blake wrote:
> If a server replies to a block status command with an invalid count in
> NBD_REPLY_TYPE_BLOCK_STATUS_EXT, we correctly detect the server's
> error, but fail to mark that we've consumed enough data off the wire
> to resync back to the server's next reply.  Rich's fuzzing run
> initially found this, but I was able to quickly write a one-byte patch
> on top of my pending qemu patches [1] to reproduce it:
> 
> [1] https://lists.gnu.org/archive/html/qemu-devel/2023-08/msg05231.html
> 
> | diff --git i/nbd/server.c w/nbd/server.c
> | index 898580a9b0b..bd8d46ba3c4 100644
> | --- i/nbd/server.c
> | +++ w/nbd/server.c
> | @@ -2326,7 +2326,7 @@ nbd_co_send_extents(NBDClient *client, NBDRequest 
> *request, NBDExtentArray *ea,
> |  iov[1].iov_base = _ext;
> |  iov[1].iov_len = sizeof(meta_ext);
> |  stl_be_p(_ext.context_id, context_id);
> | -stl_be_p(_ext.count, ea->count);
> | +stl_be_p(_ext.count, !ea->count);
> |
> |  nbd_extent_array_convert_to_be(ea);
> |  iov[2].iov_base = ea->extents;
> 
> then with a just-built 'qemu-nbd -f raw -r file -t &' running, we have
> pre-patch:
> 
> $ ./run nbdsh --base -u nbd://localhost -c - <<\EOF
> > def f(*k):
> >  pass
> > try:
> >  h.block_status(1,0,f)
> > except nbd.Error as ex:
> >  print(ex.string)
> > h.shutdown()
> > EOF
> nbdsh: generator/states-reply-chunk.c:701: 
> enter_STATE_REPLY_CHUNK_REPLY_FINISH: Assertion `h->payload_left == 0' failed.
> Aborted (core dumped)
> 
> vs. post-patch:
> 
> $ ./run nbdsh --base -u nbd://localhost -c - <<\EOF
> > def f(*k):
> >  pass
> > try:
> >  h.block_status(1,0,f)
> > except nbd.Error as ex:
> >  print(ex.string)
> > h.shutdown()
> > EOF
> nbd_block_status: block-status: command failed: Protocol error
> 
> Appears to be a casualty of rebasing: I added h->payload_left
> verification fairly late in the game, then floated it earlier in the
> series, and missed a spot where I added a state machine jump to RESYNC
> without having updated h->payload_left.  An audit of h->hlen
> modification sites show that all other chunked reads updated
> h->payload_left appropriately (often in the next statement, but
> sometimes in a later state when that made logic easier).
> 
> Requires a non-compliant server, and only possible when extended
> headers are negotiated, which does not affect any stable released
> libnbd.  Thus, there is no reason to create a CVE, although since I
> will already be doing a security info email about previous patches
> also addressing fuzzer findings, I can mention this at the same time.
> 
> Fixes: ab992766cd ("block_status: Accept 64-bit extents during block status")
> Thanks: Richard W.M. Jones 
> Signed-off-by: Eric Blake 
> ---
>  generator/states-reply-chunk.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/generator/states-reply-chunk.c b/generator/states-reply-chunk.c
> index 20407d91..5a31c192 100644
> --- a/generator/states-reply-chunk.c
> +++ b/generator/states-reply-chunk.c
> @@ -476,6 +476,7 @@  REPLY.CHUNK_REPLY.RECV_BS_HEADER:
>if (h->bs_count != be32toh (h->sbuf.reply.payload.bs_hdr_64.count)) {
>  h->rbuf = NULL;
>  h->rlen = h->payload_left;
> +h->payload_left = 0;
>  SET_NEXT_STATE (%RESYNC);
>  return 0;
>}

Reviewed-by: Richard W.M. Jones 


-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
libguestfs lets you edit virtual machines.  Supports shell scripting,
bindings from many languages.  http://libguestfs.org
___
Libguestfs mailing list
Libguestfs@redhat.com
https://listman.redhat.com/mailman/listinfo/libguestfs



[Libguestfs] [libnbd PATCH v2 5/6] block_status: Fix assertion on bad 64-bit block status reply

2023-09-21 Thread Eric Blake
If a server replies to a block status command with an invalid count in
NBD_REPLY_TYPE_BLOCK_STATUS_EXT, we correctly detect the server's
error, but fail to mark that we've consumed enough data off the wire
to resync back to the server's next reply.  Rich's fuzzing run
initially found this, but I was able to quickly write a one-byte patch
on top of my pending qemu patches [1] to reproduce it:

[1] https://lists.gnu.org/archive/html/qemu-devel/2023-08/msg05231.html

| diff --git i/nbd/server.c w/nbd/server.c
| index 898580a9b0b..bd8d46ba3c4 100644
| --- i/nbd/server.c
| +++ w/nbd/server.c
| @@ -2326,7 +2326,7 @@ nbd_co_send_extents(NBDClient *client, NBDRequest 
*request, NBDExtentArray *ea,
|  iov[1].iov_base = _ext;
|  iov[1].iov_len = sizeof(meta_ext);
|  stl_be_p(_ext.context_id, context_id);
| -stl_be_p(_ext.count, ea->count);
| +stl_be_p(_ext.count, !ea->count);
|
|  nbd_extent_array_convert_to_be(ea);
|  iov[2].iov_base = ea->extents;

then with a just-built 'qemu-nbd -f raw -r file -t &' running, we have
pre-patch:

$ ./run nbdsh --base -u nbd://localhost -c - <<\EOF
> def f(*k):
>  pass
> try:
>  h.block_status(1,0,f)
> except nbd.Error as ex:
>  print(ex.string)
> h.shutdown()
> EOF
nbdsh: generator/states-reply-chunk.c:701: 
enter_STATE_REPLY_CHUNK_REPLY_FINISH: Assertion `h->payload_left == 0' failed.
Aborted (core dumped)

vs. post-patch:

$ ./run nbdsh --base -u nbd://localhost -c - <<\EOF
> def f(*k):
>  pass
> try:
>  h.block_status(1,0,f)
> except nbd.Error as ex:
>  print(ex.string)
> h.shutdown()
> EOF
nbd_block_status: block-status: command failed: Protocol error

Appears to be a casualty of rebasing: I added h->payload_left
verification fairly late in the game, then floated it earlier in the
series, and missed a spot where I added a state machine jump to RESYNC
without having updated h->payload_left.  An audit of h->hlen
modification sites show that all other chunked reads updated
h->payload_left appropriately (often in the next statement, but
sometimes in a later state when that made logic easier).

Requires a non-compliant server, and only possible when extended
headers are negotiated, which does not affect any stable released
libnbd.  Thus, there is no reason to create a CVE, although since I
will already be doing a security info email about previous patches
also addressing fuzzer findings, I can mention this at the same time.

Fixes: ab992766cd ("block_status: Accept 64-bit extents during block status")
Thanks: Richard W.M. Jones 
Signed-off-by: Eric Blake 
---
 generator/states-reply-chunk.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/generator/states-reply-chunk.c b/generator/states-reply-chunk.c
index 20407d91..5a31c192 100644
--- a/generator/states-reply-chunk.c
+++ b/generator/states-reply-chunk.c
@@ -476,6 +476,7 @@  REPLY.CHUNK_REPLY.RECV_BS_HEADER:
   if (h->bs_count != be32toh (h->sbuf.reply.payload.bs_hdr_64.count)) {
 h->rbuf = NULL;
 h->rlen = h->payload_left;
+h->payload_left = 0;
 SET_NEXT_STATE (%RESYNC);
 return 0;
   }
-- 
2.41.0

___
Libguestfs mailing list
Libguestfs@redhat.com
https://listman.redhat.com/mailman/listinfo/libguestfs