All of lore.kernel.org
 help / color / mirror / Atom feed
From: Halil Pasic <pasic@linux.ibm.com>
To: Stefano Garzarella <sgarzare@redhat.com>
Cc: Jason Wang <jasowang@redhat.com>, mst <mst@redhat.com>,
	virtualization <virtualization@lists.linux-foundation.org>,
	"Hetzelt, Felicitas" <f.hetzelt@tu-berlin.de>,
	linux-kernel <linux-kernel@vger.kernel.org>,
	"kaplan, david" <david.kaplan@amd.com>,
	Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>,
	Stefan Hajnoczi <stefanha@redhat.com>,
	Halil Pasic <pasic@linux.ibm.com>
Subject: Re: [PATCH V5 1/4] virtio_ring: validate used buffer length
Date: Mon, 22 Nov 2021 15:24:32 +0100	[thread overview]
Message-ID: <20211122152432.23a70a12.pasic@linux.ibm.com> (raw)
In-Reply-To: <20211122110822.3xqcdluezrcapkyp@steredhat>

On Mon, 22 Nov 2021 12:08:22 +0100
Stefano Garzarella <sgarzare@redhat.com> wrote:

> On Mon, Nov 22, 2021 at 08:55:24AM +0100, Stefano Garzarella wrote:
> >On Mon, Nov 22, 2021 at 02:25:26PM +0800, Jason Wang wrote:  
> >>On Mon, Nov 22, 2021 at 1:49 PM Halil Pasic <pasic@linux.ibm.com> wrote:  
> >>>
> >>>On Mon, 22 Nov 2021 06:35:18 +0100
> >>>Halil Pasic <pasic@linux.ibm.com> wrote:
> >>>  
> >>>> > I think it should be a common issue, looking at
> >>>> > vhost_vsock_handle_tx_kick(), it did:
> >>>> >
> >>>> > len += sizeof(pkt->hdr);
> >>>> > vhost_add_used(vq, head, len);
> >>>> >
> >>>> > which looks like a violation of the spec since it's TX.  
> >>>>
> >>>> I'm not sure the lines above look like a violation of the spec. If you
> >>>> examine vhost_vsock_alloc_pkt() I believe that you will agree that:
> >>>> len == pkt->len == pkt->hdr.len
> >>>> which makes sense since according to the spec both tx and rx messages
> >>>> are hdr+payload. And I believe hdr.len is the size of the payload,
> >>>> although that does not seem to be properly documented by the spec.  
> >>
> >>Sorry for being unclear, what I meant is that we probably should use
> >>zero here. TX doesn't use in buffer actually.
> >>
> >>According to the spec, 0 should be the used length:
> >>
> >>"and len the total of bytes written into the buffer."
> >>  
> >>>>
> >>>> On the other hand tx messages are stated to be device read-only (in the
> >>>> spec) so if the device writes stuff, that is certainly wrong.
> >>>>  
> >>
> >>Yes.
> >>  
> >>>> If that is what happens.
> >>>>
> >>>> Looking at virtqueue_get_buf_ctx_split() I'm not sure that is what
> >>>> happens. My hypothesis is that we just a last descriptor is an 'in'
> >>>> type descriptor (i.e. a device writable one). For tx that assumption
> >>>> would be wrong.
> >>>>
> >>>> I will have another look at this today and send a fix patch if my
> >>>> suspicion is confirmed.  
> >>>
> >>>If my suspicion is right something like:
> >>>
> >>>diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> >>>index 00f64f2f8b72..efb57898920b 100644
> >>>--- a/drivers/virtio/virtio_ring.c
> >>>+++ b/drivers/virtio/virtio_ring.c
> >>>@@ -764,6 +764,7 @@ static void *virtqueue_get_buf_ctx_split(struct virtqueue *_vq,
> >>>        struct vring_virtqueue *vq = to_vvq(_vq);
> >>>        void *ret;
> >>>        unsigned int i;
> >>>+       bool has_in;
> >>>        u16 last_used;
> >>>
> >>>        START_USE(vq);
> >>>@@ -787,6 +788,9 @@ static void *virtqueue_get_buf_ctx_split(struct virtqueue *_vq,
> >>>                        vq->split.vring.used->ring[last_used].id);
> >>>        *len = virtio32_to_cpu(_vq->vdev,
> >>>                        vq->split.vring.used->ring[last_used].len);
> >>>+       has_in = virtio16_to_cpu(_vq->vdev,
> >>>+                       vq->split.vring.used->ring[last_used].flags)
> >>>+                               & VRING_DESC_F_WRITE;  
> >>
> >>Did you mean vring.desc actually? If yes, it's better not depend on
> >>the descriptor ring which can be modified by the device. We've stored
> >>the flags in desc_extra[].
> >>  
> >>>
> >>>        if (unlikely(i >= vq->split.vring.num)) {
> >>>                BAD_RING(vq, "id %u out of range\n", i);
> >>>@@ -796,7 +800,7 @@ static void *virtqueue_get_buf_ctx_split(struct virtqueue *_vq,
> >>>                BAD_RING(vq, "id %u is not a head!\n", i);
> >>>                return NULL;
> >>>        }
> >>>-       if (vq->buflen && unlikely(*len > vq->buflen[i])) {
> >>>+       if (has_in && q->buflen && unlikely(*len > vq->buflen[i])) {
> >>>                BAD_RING(vq, "used len %d is larger than in buflen %u\n",
> >>>                        *len, vq->buflen[i]);
> >>>                return NULL;
> >>>
> >>>would fix the problem for split. I will try that out and let you know
> >>>later.  
> >>
> >>I'm not sure I get this, in virtqueue_add_split, the buflen[i] only
> >>contains the in buffer length.
> >>
> >>I think the fixes are:
> >>
> >>1) fixing the vhost vsock  
> >
> >Yep, in vhost_vsock_handle_tx_kick() we should have vhost_add_used(vq, 
> >head, 0) since the device doesn't write anything.
> >  
> >>2) use suppress_used_validation=true to let vsock driver to validate
> >>the in buffer length
> >>3) probably a new feature so the driver can only enable the validation
> >>when the feature is enabled.  
> >
> >I fully agree with these steps.  
> 
> Michael sent a patch to suppress the validation, so I think we should 
> just fix vhost-vsock. I mean something like this:
> 
> diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c
> index 938aefbc75ec..4e3b95af7ee4 100644
> --- a/drivers/vhost/vsock.c
> +++ b/drivers/vhost/vsock.c
> @@ -554,7 +554,7 @@ static void vhost_vsock_handle_tx_kick(struct vhost_work *work)
>                          virtio_transport_free_pkt(pkt);
> 
>                  len += sizeof(pkt->hdr);
> -               vhost_add_used(vq, head, len);
> +               vhost_add_used(vq, head, 0);
>                  total_len += len;
>                  added = true;
>          } while(likely(!vhost_exceeds_weight(vq, ++pkts, total_len)));
> 
> I checked and the problem is there from the first commit, so we should 
> add:
> 
> Fixes: 433fc58e6bf2 ("VSOCK: Introduce vhost_vsock.ko")
> 
> I tested this patch and it works even without suppressing validation in 
> the virtio core.  But for backwards compatibility we have to suppress it 
> for sure as Michael did.
> 
> Maybe we can have a patch just with this change to backport it easily 
> and one after to clean up a bit the code that was added after (len, 
> total_len).
> 
> @Halil Let me know if you want to do it, otherwise I can do it.
> 

It is fine, it was you guys who figured out the solution so I think
it should either be Jason or you who take credit for the patch. Thanks
for addressing the issue this quickly!

Regards,
Halil

WARNING: multiple messages have this Message-ID (diff)
From: Halil Pasic <pasic@linux.ibm.com>
To: Stefano Garzarella <sgarzare@redhat.com>
Cc: "kaplan, david" <david.kaplan@amd.com>, mst <mst@redhat.com>,
	"Hetzelt, Felicitas" <f.hetzelt@tu-berlin.de>,
	linux-kernel <linux-kernel@vger.kernel.org>,
	virtualization <virtualization@lists.linux-foundation.org>,
	Halil Pasic <pasic@linux.ibm.com>,
	Stefan Hajnoczi <stefanha@redhat.com>,
	Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Subject: Re: [PATCH V5 1/4] virtio_ring: validate used buffer length
Date: Mon, 22 Nov 2021 15:24:32 +0100	[thread overview]
Message-ID: <20211122152432.23a70a12.pasic@linux.ibm.com> (raw)
In-Reply-To: <20211122110822.3xqcdluezrcapkyp@steredhat>

On Mon, 22 Nov 2021 12:08:22 +0100
Stefano Garzarella <sgarzare@redhat.com> wrote:

> On Mon, Nov 22, 2021 at 08:55:24AM +0100, Stefano Garzarella wrote:
> >On Mon, Nov 22, 2021 at 02:25:26PM +0800, Jason Wang wrote:  
> >>On Mon, Nov 22, 2021 at 1:49 PM Halil Pasic <pasic@linux.ibm.com> wrote:  
> >>>
> >>>On Mon, 22 Nov 2021 06:35:18 +0100
> >>>Halil Pasic <pasic@linux.ibm.com> wrote:
> >>>  
> >>>> > I think it should be a common issue, looking at
> >>>> > vhost_vsock_handle_tx_kick(), it did:
> >>>> >
> >>>> > len += sizeof(pkt->hdr);
> >>>> > vhost_add_used(vq, head, len);
> >>>> >
> >>>> > which looks like a violation of the spec since it's TX.  
> >>>>
> >>>> I'm not sure the lines above look like a violation of the spec. If you
> >>>> examine vhost_vsock_alloc_pkt() I believe that you will agree that:
> >>>> len == pkt->len == pkt->hdr.len
> >>>> which makes sense since according to the spec both tx and rx messages
> >>>> are hdr+payload. And I believe hdr.len is the size of the payload,
> >>>> although that does not seem to be properly documented by the spec.  
> >>
> >>Sorry for being unclear, what I meant is that we probably should use
> >>zero here. TX doesn't use in buffer actually.
> >>
> >>According to the spec, 0 should be the used length:
> >>
> >>"and len the total of bytes written into the buffer."
> >>  
> >>>>
> >>>> On the other hand tx messages are stated to be device read-only (in the
> >>>> spec) so if the device writes stuff, that is certainly wrong.
> >>>>  
> >>
> >>Yes.
> >>  
> >>>> If that is what happens.
> >>>>
> >>>> Looking at virtqueue_get_buf_ctx_split() I'm not sure that is what
> >>>> happens. My hypothesis is that we just a last descriptor is an 'in'
> >>>> type descriptor (i.e. a device writable one). For tx that assumption
> >>>> would be wrong.
> >>>>
> >>>> I will have another look at this today and send a fix patch if my
> >>>> suspicion is confirmed.  
> >>>
> >>>If my suspicion is right something like:
> >>>
> >>>diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> >>>index 00f64f2f8b72..efb57898920b 100644
> >>>--- a/drivers/virtio/virtio_ring.c
> >>>+++ b/drivers/virtio/virtio_ring.c
> >>>@@ -764,6 +764,7 @@ static void *virtqueue_get_buf_ctx_split(struct virtqueue *_vq,
> >>>        struct vring_virtqueue *vq = to_vvq(_vq);
> >>>        void *ret;
> >>>        unsigned int i;
> >>>+       bool has_in;
> >>>        u16 last_used;
> >>>
> >>>        START_USE(vq);
> >>>@@ -787,6 +788,9 @@ static void *virtqueue_get_buf_ctx_split(struct virtqueue *_vq,
> >>>                        vq->split.vring.used->ring[last_used].id);
> >>>        *len = virtio32_to_cpu(_vq->vdev,
> >>>                        vq->split.vring.used->ring[last_used].len);
> >>>+       has_in = virtio16_to_cpu(_vq->vdev,
> >>>+                       vq->split.vring.used->ring[last_used].flags)
> >>>+                               & VRING_DESC_F_WRITE;  
> >>
> >>Did you mean vring.desc actually? If yes, it's better not depend on
> >>the descriptor ring which can be modified by the device. We've stored
> >>the flags in desc_extra[].
> >>  
> >>>
> >>>        if (unlikely(i >= vq->split.vring.num)) {
> >>>                BAD_RING(vq, "id %u out of range\n", i);
> >>>@@ -796,7 +800,7 @@ static void *virtqueue_get_buf_ctx_split(struct virtqueue *_vq,
> >>>                BAD_RING(vq, "id %u is not a head!\n", i);
> >>>                return NULL;
> >>>        }
> >>>-       if (vq->buflen && unlikely(*len > vq->buflen[i])) {
> >>>+       if (has_in && q->buflen && unlikely(*len > vq->buflen[i])) {
> >>>                BAD_RING(vq, "used len %d is larger than in buflen %u\n",
> >>>                        *len, vq->buflen[i]);
> >>>                return NULL;
> >>>
> >>>would fix the problem for split. I will try that out and let you know
> >>>later.  
> >>
> >>I'm not sure I get this, in virtqueue_add_split, the buflen[i] only
> >>contains the in buffer length.
> >>
> >>I think the fixes are:
> >>
> >>1) fixing the vhost vsock  
> >
> >Yep, in vhost_vsock_handle_tx_kick() we should have vhost_add_used(vq, 
> >head, 0) since the device doesn't write anything.
> >  
> >>2) use suppress_used_validation=true to let vsock driver to validate
> >>the in buffer length
> >>3) probably a new feature so the driver can only enable the validation
> >>when the feature is enabled.  
> >
> >I fully agree with these steps.  
> 
> Michael sent a patch to suppress the validation, so I think we should 
> just fix vhost-vsock. I mean something like this:
> 
> diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c
> index 938aefbc75ec..4e3b95af7ee4 100644
> --- a/drivers/vhost/vsock.c
> +++ b/drivers/vhost/vsock.c
> @@ -554,7 +554,7 @@ static void vhost_vsock_handle_tx_kick(struct vhost_work *work)
>                          virtio_transport_free_pkt(pkt);
> 
>                  len += sizeof(pkt->hdr);
> -               vhost_add_used(vq, head, len);
> +               vhost_add_used(vq, head, 0);
>                  total_len += len;
>                  added = true;
>          } while(likely(!vhost_exceeds_weight(vq, ++pkts, total_len)));
> 
> I checked and the problem is there from the first commit, so we should 
> add:
> 
> Fixes: 433fc58e6bf2 ("VSOCK: Introduce vhost_vsock.ko")
> 
> I tested this patch and it works even without suppressing validation in 
> the virtio core.  But for backwards compatibility we have to suppress it 
> for sure as Michael did.
> 
> Maybe we can have a patch just with this change to backport it easily 
> and one after to clean up a bit the code that was added after (len, 
> total_len).
> 
> @Halil Let me know if you want to do it, otherwise I can do it.
> 

It is fine, it was you guys who figured out the solution so I think
it should either be Jason or you who take credit for the patch. Thanks
for addressing the issue this quickly!

Regards,
Halil
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

  reply	other threads:[~2021-11-22 14:24 UTC|newest]

Thread overview: 65+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-27  2:21 [PATCH V5 0/4] Validate used buffer length Jason Wang
2021-10-27  2:21 ` Jason Wang
2021-10-27  2:21 ` [PATCH V5 1/4] virtio_ring: validate " Jason Wang
2021-10-27  2:21   ` Jason Wang
2021-11-02  3:18   ` Xuan Zhuo
2021-11-02  3:54     ` Jason Wang
2021-11-02  3:54       ` Jason Wang
2021-11-19 15:09   ` Halil Pasic
2021-11-19 15:09     ` Halil Pasic
2021-11-22  3:51     ` Jason Wang
2021-11-22  3:51       ` Jason Wang
2021-11-22  5:35       ` Halil Pasic
2021-11-22  5:35         ` Halil Pasic
2021-11-22  5:49         ` Halil Pasic
2021-11-22  5:49           ` Halil Pasic
2021-11-22  6:25           ` Jason Wang
2021-11-22  6:25             ` Jason Wang
2021-11-22  7:55             ` Stefano Garzarella
2021-11-22  7:55               ` Stefano Garzarella
2021-11-22 11:08               ` Stefano Garzarella
2021-11-22 11:08                 ` Stefano Garzarella
2021-11-22 14:24                 ` Halil Pasic [this message]
2021-11-22 14:24                   ` Halil Pasic
2021-11-22 16:23                   ` Stefano Garzarella
2021-11-22 16:23                     ` Stefano Garzarella
2021-11-22 13:50             ` Halil Pasic
2021-11-22 13:50               ` Halil Pasic
2021-11-23  2:30               ` Jason Wang
2021-11-23  2:30                 ` Jason Wang
2021-11-23 12:17               ` Michael S. Tsirkin
2021-11-23 12:17                 ` Michael S. Tsirkin
2021-11-23 12:43                 ` Halil Pasic
2021-11-23 12:43                   ` Halil Pasic
2021-11-22 20:23             ` Halil Pasic
2021-11-22 20:23               ` Halil Pasic
2021-11-23  2:25               ` Jason Wang
2021-11-23  2:25                 ` Jason Wang
2021-11-23 11:05                 ` Michael S. Tsirkin
2021-11-23 11:05                   ` Michael S. Tsirkin
2021-11-24  1:30                   ` Michael Ellerman
2021-11-24  1:30                     ` Michael Ellerman
2021-11-24  2:26                     ` Jason Wang
2021-11-24  2:26                       ` Jason Wang
2021-11-24  2:33                       ` Jason Wang
2021-11-24  2:33                         ` Jason Wang
2021-11-24  7:22                         ` Michael S. Tsirkin
2021-11-24  7:22                           ` Michael S. Tsirkin
2021-11-24  7:59                           ` Jason Wang
2021-11-24  7:59                             ` Jason Wang
2021-11-24  8:24                             ` Michael S. Tsirkin
2021-11-24  8:24                               ` Michael S. Tsirkin
2021-11-24  8:28                               ` Jason Wang
2021-11-24  8:28                                 ` Jason Wang
2021-11-24 11:33                         ` Halil Pasic
2021-11-24 11:33                           ` Halil Pasic
2021-11-25  2:27                           ` Jason Wang
2021-11-25  2:27                             ` Jason Wang
2021-11-22  7:42       ` Stefano Garzarella
2021-11-22  7:42         ` Stefano Garzarella
2021-10-27  2:21 ` [PATCH V5 2/4] virtio-net: don't let virtio core to validate used length Jason Wang
2021-10-27  2:21   ` Jason Wang
2021-10-27  2:21 ` [PATCH V5 3/4] virtio-blk: " Jason Wang
2021-10-27  2:21   ` Jason Wang
2021-10-27  2:21 ` [PATCH V5 4/4] virtio-scsi: don't let virtio core to validate used buffer length Jason Wang
2021-10-27  2:21   ` Jason Wang

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=20211122152432.23a70a12.pasic@linux.ibm.com \
    --to=pasic@linux.ibm.com \
    --cc=david.kaplan@amd.com \
    --cc=f.hetzelt@tu-berlin.de \
    --cc=jasowang@redhat.com \
    --cc=konrad.wilk@oracle.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mst@redhat.com \
    --cc=sgarzare@redhat.com \
    --cc=stefanha@redhat.com \
    --cc=virtualization@lists.linux-foundation.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 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.