__vringh_iov()'s F_INDIRECT branch does `continue` before the descriptor accounting block, so a top-level indirect descriptor is never charged to `count`. When such a descriptor also carries NEXT pointing to itself, returning from the indirect table resumes at the same uncharged descriptor; `count` stays flat and `indirect_count` is reset to 0 on every return, so neither bound in the loop check can ever trip. A guest can keep the host vringh worker spinning inside __vringh_iov(), causing a host DoS.
Patch 1/2 moves the accounting block above the INDIRECT switch so each top-level descriptor, including INDIRECT ones, is charged one traversal step before the walk descends. Legitimate chains and indirect descriptors stay within vring.num; a cyclic indirect descriptor is now rejected with -ELOOP. Patch 1 carries the Fixes tag and is Cc'd to stable. Patch 2/2 appends a regression test to tools/virtio/vringh_test.c. It builds the offending ring: top-level desc[1].flags = VRING_DESC_F_INDIRECT | VRING_DESC_F_NEXT and desc[1].next = 1, with a single-entry indirect table, and asserts that vringh_getdesc_user() returns -ELOOP. Verified against v7.3-rc3: both patches pass git apply --check. With the fix, vringh_test --indirect observes -ELOOP and exits 0. With the fix reverted, the walk re-enters the same descriptor without making forward progress and never returns -ELOOP, so the assertion does not hold and the regression is caught either way. Fang Xieyan (2): vringh: bound top-level re-entry into indirect tables vringh: add regression test for cyclic indirect descriptor drivers/vhost/vringh.c | 22 ++++++++++---------- tools/virtio/vringh_test.c | 41 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 11 deletions(-) -- 2.50.1

