vringh: Fix loop descriptors check in the indirect cases
authorXie Yongji <xieyongji@bytedance.com>
Thu, 5 May 2022 10:09:10 +0000 (18:09 +0800)
committerMichael S. Tsirkin <mst@redhat.com>
Wed, 8 Jun 2022 12:56:03 +0000 (08:56 -0400)
We should use size of descriptor chain to test loop condition
in the indirect case. And another statistical count is also introduced
for indirect descriptors to avoid conflict with the statistical count
of direct descriptors.

Fixes: f87d0fbb5798 ("vringh: host-side implementation of virtio rings.")
Signed-off-by: Xie Yongji <xieyongji@bytedance.com>
Signed-off-by: Fam Zheng <fam.zheng@bytedance.com>
Message-Id: <20220505100910.137-1-xieyongji@bytedance.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Jason Wang <jasowang@redhat.com>
drivers/vhost/vringh.c

index 14e2043d7685216c9a26adaf007228e2c47f276e..eab55accf381f83ad96ffaaa0998f276dca8551a 100644 (file)
@@ -292,7 +292,7 @@ __vringh_iov(struct vringh *vrh, u16 i,
             int (*copy)(const struct vringh *vrh,
                         void *dst, const void *src, size_t len))
 {
-       int err, count = 0, up_next, desc_max;
+       int err, count = 0, indirect_count = 0, up_next, desc_max;
        struct vring_desc desc, *descs;
        struct vringh_range range = { -1ULL, 0 }, slowrange;
        bool slow = false;
@@ -349,7 +349,12 @@ __vringh_iov(struct vringh *vrh, u16 i,
                        continue;
                }
 
-               if (count++ == vrh->vring.num) {
+               if (up_next == -1)
+                       count++;
+               else
+                       indirect_count++;
+
+               if (count > vrh->vring.num || indirect_count > desc_max) {
                        vringh_bad("Descriptor loop in %p", descs);
                        err = -ELOOP;
                        goto fail;
@@ -411,6 +416,7 @@ __vringh_iov(struct vringh *vrh, u16 i,
                                i = return_from_indirect(vrh, &up_next,
                                                         &descs, &desc_max);
                                slow = false;
+                               indirect_count = 0;
                        } else
                                break;
                }