Received: by 2002:a05:6a10:6d25:0:0:0:0 with SMTP id gq37csp1562613pxb; Sun, 12 Sep 2021 23:59:27 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwj6HIDntZuG4qiDNufW5tQ82hdZtvd5/o4DtMv8vnMmau+oDjHKOeK0F4PeNg1K+rGMjOm X-Received: by 2002:a17:906:2db1:: with SMTP id g17mr11078522eji.286.1631516367295; Sun, 12 Sep 2021 23:59:27 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1631516367; cv=none; d=google.com; s=arc-20160816; b=fmHdDHqx9MMm4R1tXwZ6yKT3vzpAgX8Kg22SQYC9SVXaH89Z4A6GG70VfDXV3usZ0o lu1M0mU4apRMxUa/EZ+9+sRJgkNotYbopHo3rMyjSolq9YYRK3VZyM6QdlnPNLx8VmrZ lPVs8ZcF9ke0mehnMd/Qe5OJCVzyA/S3EZC8f9C8f9DSJuXRL3WN2qcGeJId9BcbGxTj kkhNFagp+/ZhAp/JpQ0835IkO7Z52EvZpdwCFlmO/j3IVfO2vG36BlKf6ZSCJv1s6B7+ PJEp4yJDAqYXDZOySHaTYQGHEdFcolSSzA2Sitl21vtK2N45hvvMLJS1MVoaiuasQwt5 SDeQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:in-reply-to:content-disposition:mime-version :references:message-id:subject:cc:to:from:date:dkim-signature; bh=Uq9tbu3TDqgOAJs2JRYdBCy2+stYK+Aour5wYZ0uUGA=; b=OQKaivreMCe4kg0PAUc4SutFtb6JyU59WodKVJCo16qKooRYUr2KRlxBhXa95bABVb aFH/T2j1f98J7hvok7pHSkbBESg6Ekb0V+7hcgs3FifyGlKM0x7IDl/QzrCWGPkRQtuN BSeiFqqa3NEVeCsvX8NEGXgn0vqCZA34chpIPbP2n0dp1WWp4GMvNU4r2q1ktytNWqz+ +0HmIhsNsT4WR6eN5D/fQih3VGZvgJyBa5gP3MbjOAV9kpwIbYK/sAjVw7I2TA/Q/3pl wmP5EHQh0xC8XX7+CXjGUBWuC6/tL3Qo+muhuoTza6OwKLREmIlIN/naxss4HObO0Fft hTQA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=CYzAFp8A; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id z12si6255390edb.223.2021.09.12.23.59.03; Sun, 12 Sep 2021 23:59:27 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=CYzAFp8A; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237467AbhIMG6i (ORCPT + 99 others); Mon, 13 Sep 2021 02:58:38 -0400 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:54527 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237429AbhIMG6i (ORCPT ); Mon, 13 Sep 2021 02:58:38 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1631516242; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=Uq9tbu3TDqgOAJs2JRYdBCy2+stYK+Aour5wYZ0uUGA=; b=CYzAFp8Arz1xilEWN36TRZmhHpbFLet3O/CT1EvmXYAiRAH0SkBMWEIuZq9W96K0hUiWFm Z1VtP7YLP7dxAWSRgDhLEtkNRiTU5GEeOTGvgzFyUjrA9MGhMpwQnzx6BH+sTGgKNhUw6I ghzafzpEnY/ifZ+YUZIGMZyb9xBuwE8= Received: from mail-ej1-f72.google.com (mail-ej1-f72.google.com [209.85.218.72]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-457-t7UF_ycFO1iT1Fu2aDQvOQ-1; Mon, 13 Sep 2021 02:57:18 -0400 X-MC-Unique: t7UF_ycFO1iT1Fu2aDQvOQ-1 Received: by mail-ej1-f72.google.com with SMTP id v12-20020a170906858c00b005f03d2ccaf5so845740ejx.14 for ; Sun, 12 Sep 2021 23:57:18 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to; bh=Uq9tbu3TDqgOAJs2JRYdBCy2+stYK+Aour5wYZ0uUGA=; b=s4MhcR/82LCA41Cpuv7ymKysiITQCVkTfZ1T3szrzW94rujVs0N4FX3fahAZA3MHpr HCKSk2RZIbNlrXashQGSmb/OlltlvVzy0Zw51DjSk0E9A+iMC0q+IRgRATcdiNGpxSmX pdUSx6sVNLq38G87YFfENuhMLC3YzL6d0c8sfTG7ewCtixVwKDrskRoyff/tqLos5d6g yGZd4erMwZeOtWN73tSkUkeChJTMzwOCBOnvedqbeBn3jiZCKvqNSDiPRGW2zdjdmy8v MnMNzy60MWPQ/KUdOyiuUXgWG88hkGLatcYUV76D6QvLrwqUXUinCjCD3ZrdO2TP3akn 8kGg== X-Gm-Message-State: AOAM532njHxaN8vNufCwLArA6JhVjTu3yvj9SL3+PGgtV8DVwpyzqzSk CoKAd1J2ydtkMJBmFr2hmEa/BTcrblkE1ZqPh3iYz7np2dsb6tG6hzkGSngauxPL4pa0755fqkl oGgVBZ1Aesjqs7+sT6ZuwOdlQ X-Received: by 2002:a17:906:b104:: with SMTP id u4mr11298286ejy.201.1631516237578; Sun, 12 Sep 2021 23:57:17 -0700 (PDT) X-Received: by 2002:a17:906:b104:: with SMTP id u4mr11298276ejy.201.1631516237402; Sun, 12 Sep 2021 23:57:17 -0700 (PDT) Received: from redhat.com ([2.55.27.174]) by smtp.gmail.com with ESMTPSA id lz19sm3027248ejb.40.2021.09.12.23.57.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 12 Sep 2021 23:57:16 -0700 (PDT) Date: Mon, 13 Sep 2021 02:57:13 -0400 From: "Michael S. Tsirkin" To: Jason Wang Cc: virtualization , linux-kernel , "Hetzelt, Felicitas" , "kaplan, david" , Konrad Rzeszutek Wilk Subject: Re: [PATCH 9/9] virtio_ring: validate used buffer length Message-ID: <20210913025145-mutt-send-email-mst@kernel.org> References: <20210913055353.35219-1-jasowang@redhat.com> <20210913055353.35219-10-jasowang@redhat.com> <20210913023428-mutt-send-email-mst@kernel.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Mon, Sep 13, 2021 at 02:40:09PM +0800, Jason Wang wrote: > On Mon, Sep 13, 2021 at 2:36 PM Michael S. Tsirkin wrote: > > > > On Mon, Sep 13, 2021 at 01:53:53PM +0800, Jason Wang wrote: > > > This patch validate the used buffer length provided by the device > > > before trying to use it. This is done by record the in buffer length > > > in a new field in desc_state structure during virtqueue_add(), then we > > > can fail the virtqueue_get_buf() when we find the device is trying to > > > give us a used buffer length which is greater than the in buffer > > > length. > > > > > > Signed-off-by: Jason Wang > > > > Hmm this was proposed in the past. The overhead here is > > not negligeable, so I'd like to know more - > > when is it a problem if the used len is too big? > > One example is: https://github.com/fuzzsa/fuzzsa-bugs/blob/master/virtio_rng.md > > And there would be more I guess. That seems to suggest hwrng validation is better, and I think it makes sense: will fix all rng drivers in one go. > > Don't the affected drivers already track the length somewhere > > and so can validated it without the extra cost in > > virtio core? > > Probably, but this requires the changes in each device driver. And it > would be easily forgotten if new drivers are introduced? > > Thanks My thinking is one just has to be aware that before enabling any drivers they have to be audited. We can validate used length but e.g. for virtio net the length is inside the buffer anyway. If we really have to, maybe use extra->len? And maybe have a mod param so the check can be turned off e.g. for benchmarking purposes. > > > > > --- > > > drivers/virtio/virtio_ring.c | 23 +++++++++++++++++++++++ > > > 1 file changed, 23 insertions(+) > > > > > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c > > > index d2ca0a7365f8..b8374a6144f3 100644 > > > --- a/drivers/virtio/virtio_ring.c > > > +++ b/drivers/virtio/virtio_ring.c > > > @@ -69,6 +69,7 @@ > > > struct vring_desc_state_split { > > > void *data; /* Data for callback. */ > > > struct vring_desc *indir_desc; /* Indirect descriptor, if any. */ > > > + u64 buflen; /* In buffer length */ > > > }; > > > > > > struct vring_desc_state_packed { > > > @@ -76,6 +77,7 @@ struct vring_desc_state_packed { > > > struct vring_packed_desc *indir_desc; /* Indirect descriptor, if any. */ > > > u16 num; /* Descriptor list length. */ > > > u16 last; /* The last desc state in a list. */ > > > + u64 buflen; /* In buffer length */ > > > }; > > > > > > struct vring_desc_extra { > > > @@ -490,6 +492,7 @@ static inline int virtqueue_add_split(struct virtqueue *_vq, > > > unsigned int i, n, avail, descs_used, prev, err_idx; > > > int head; > > > bool indirect; > > > + u64 buflen = 0; > > > > > > START_USE(vq); > > > > > > @@ -571,6 +574,7 @@ static inline int virtqueue_add_split(struct virtqueue *_vq, > > > VRING_DESC_F_NEXT | > > > VRING_DESC_F_WRITE, > > > indirect); > > > + buflen += sg->length; > > > } > > > } > > > /* Last one doesn't continue. */ > > > @@ -605,6 +609,7 @@ static inline int virtqueue_add_split(struct virtqueue *_vq, > > > > > > /* Store token and indirect buffer state. */ > > > vq->split.desc_state[head].data = data; > > > + vq->split.desc_state[head].buflen = buflen; > > > if (indirect) > > > vq->split.desc_state[head].indir_desc = desc; > > > else > > > @@ -784,6 +789,11 @@ static void *virtqueue_get_buf_ctx_split(struct virtqueue *_vq, > > > BAD_RING(vq, "id %u is not a head!\n", i); > > > return NULL; > > > } > > > + if (unlikely(*len > vq->split.desc_state[i].buflen)) { > > > + BAD_RING(vq, "used len %d is larger than in buflen %lld\n", > > > + *len, vq->split.desc_state[i].buflen); > > > + return NULL; > > > + } > > > > > > /* detach_buf_split clears data, so grab it now. */ > > > ret = vq->split.desc_state[i].data; > > > @@ -1062,6 +1072,7 @@ static int virtqueue_add_indirect_packed(struct vring_virtqueue *vq, > > > unsigned int i, n, err_idx; > > > u16 head, id; > > > dma_addr_t addr; > > > + u64 buflen = 0; > > > > > > head = vq->packed.next_avail_idx; > > > desc = alloc_indirect_packed(total_sg, gfp); > > > @@ -1089,6 +1100,8 @@ static int virtqueue_add_indirect_packed(struct vring_virtqueue *vq, > > > desc[i].addr = cpu_to_le64(addr); > > > desc[i].len = cpu_to_le32(sg->length); > > > i++; > > > + if (n >= out_sgs) > > > + buflen += sg->length; > > > } > > > } > > > > > > @@ -1141,6 +1154,7 @@ static int virtqueue_add_indirect_packed(struct vring_virtqueue *vq, > > > vq->packed.desc_state[id].data = data; > > > vq->packed.desc_state[id].indir_desc = desc; > > > vq->packed.desc_state[id].last = id; > > > + vq->packed.desc_state[id].buflen = buflen; > > > > > > vq->num_added += 1; > > > > > > @@ -1176,6 +1190,7 @@ static inline int virtqueue_add_packed(struct virtqueue *_vq, > > > unsigned int i, n, c, descs_used, err_idx; > > > __le16 head_flags, flags; > > > u16 head, id, prev, curr, avail_used_flags; > > > + u64 buflen = 0; > > > > > > START_USE(vq); > > > > > > @@ -1250,6 +1265,8 @@ static inline int virtqueue_add_packed(struct virtqueue *_vq, > > > 1 << VRING_PACKED_DESC_F_AVAIL | > > > 1 << VRING_PACKED_DESC_F_USED; > > > } > > > + if (n >= out_sgs) > > > + buflen += sg->length; > > > } > > > } > > > > > > @@ -1268,6 +1285,7 @@ static inline int virtqueue_add_packed(struct virtqueue *_vq, > > > vq->packed.desc_state[id].data = data; > > > vq->packed.desc_state[id].indir_desc = ctx; > > > vq->packed.desc_state[id].last = prev; > > > + vq->packed.desc_state[id].buflen = buflen; > > > > > > /* > > > * A driver MUST NOT make the first descriptor in the list > > > @@ -1455,6 +1473,11 @@ static void *virtqueue_get_buf_ctx_packed(struct virtqueue *_vq, > > > BAD_RING(vq, "id %u is not a head!\n", id); > > > return NULL; > > > } > > > + if (unlikely(*len > vq->packed.desc_state[id].buflen)) { > > > + BAD_RING(vq, "used len %d is larger than in buflen %lld\n", > > > + *len, vq->packed.desc_state[id].buflen); > > > + return NULL; > > > + } > > > > > > /* detach_buf_packed clears data, so grab it now. */ > > > ret = vq->packed.desc_state[id].data; > > > -- > > > 2.25.1 > >