From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from out28-122.mail.aliyun.com (out28-122.mail.aliyun.com [115.124.28.122]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EB0ED36D500 for ; Sat, 26 Sep 2026 16:08:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=115.124.28.122 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790438889; cv=none; b=twopNUViqfOTMH0ada4MxyD+HXDNhdS2EqrAHdt9OdKCVigFVCsEeF7N43pLeAh836N1yH/zHJnhfcWmCfs2UY4Shv5Lsm2/g0B8lW6hr3/9zLVLD/nYN5VnVhS8+PO1EDf5XXn4op6zdZnQlwEpIRlLPnpdMK5rmYhoxn1a5gs= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790438889; c=relaxed/simple; bh=tqLckBEZHvSegR6zv+qVZBZSgGXz+gwBiExasXQX3fI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ltiH6k91UwCw2zYiK+lFUOQGYuhXXKWDTSSZt/UghRtPfBzb7L/OthmcjeQOxO2RikmvTP4Md8Ee4DfnR1Rym8IVlxg9684AoReO030cBomVTI2J5i4EqCAwpqOJM6BEFoKhfBzDWMC6v0pdMMBbr31/EIKPZgr4BoQ+7Oq+nXo= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=xiaopeng.com; spf=pass smtp.mailfrom=xiaopeng.com; dkim=pass (1024-bit key) header.d=xiaopeng.com header.i=@xiaopeng.com header.b=pyPyB0br; arc=none smtp.client-ip=115.124.28.122 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=xiaopeng.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=xiaopeng.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=xiaopeng.com header.i=@xiaopeng.com header.b="pyPyB0br" DKIM-Signature:v=1; a=rsa-sha256; c=relaxed/relaxed; d=xiaopeng.com; s=default; t=1790438878; h=From:To:Subject:Date:Message-ID:MIME-Version; bh=Vmew8F6cGoltC/zlxLQ/V2Ko/5hlJ0diq7QdLHv/b2g=; b=pyPyB0brJjkU6YAnShJGXKM0IIkWQV6CkkyiQwgYBV+8zTaTE+UOXwb2Rq/RtqMJHBUOnv6gcHy+vQ688j0/rgtzlsfW+V/qMqfSZd+m+Nva4H5U7ztHA5F8jfMba/p1QVMpYl8OBXo5u+fW4UdqqayrpUU9lLqd/ZHhOwgp64o= X-Alimail-AntiSpam:AC=CONTINUE;BC=0.0451441|-1;CH=green;DM=|CONTINUE|false|;DS=CONTINUE|ham_alarm|0.0306825-0.00118257-0.968135;FP=3451580394671390456|0|0|0|0|-1|-1|-1;HT=maildocker-contentspam033037006180;MF=fangxy@xiaopeng.com;NM=1;PH=DS;RN=9;RT=9;SR=0;TI=SMTPD_---.jOPHQ-s_1790438876; Received: from localhost.localdomain(mailfrom:fangxy@xiaopeng.com fp:SMTPD_---.jOPHQ-s_1790438876 cluster:ay29) by smtp.aliyun-inc.com; Sun, 27 Sep 2026 00:07:57 +0800 From: Fang Xieyan To: "Michael S . Tsirkin" , Jason Wang , =?UTF-8?q?Eugenio=20P=C3=A9rez?= Cc: Rusty Russell , stable@vger.kernel.org, virtualization@lists.linux.dev, kvm@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2] vringh: reject empty / undersized indirect descriptor tables Date: Sun, 27 Sep 2026 00:07:55 +0800 Message-ID: <20260926160755.21485-1-fangxy@xiaopeng.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20260924030627.13287-1-fangxy@xiaopeng.com> References: <20260924030627.13287-1-fangxy@xiaopeng.com> Precedence: bulk X-Mailing-List: virtualization@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit move_to_indirect() validates an indirect descriptor table only with "len % sizeof(struct vring_desc)". A descriptor flagged VRING_DESC_F_INDIRECT with len == 0 passes that test, so *desc_max is set to 0 while *descs points at the empty table. __vringh_iov() then copies one struct vring_desc from descs[0] -- 16 bytes past the end of the table -- before the "indirect_count > desc_max" loop detection aborts the walk. The over-read value is discarded when the walk aborts and is never used to map anything, but the access itself is out of bounds. Reject any len smaller than one descriptor, alongside the existing stride check, so an empty table is refused with -EINVAL and no descriptor is ever fetched from it. Fixes: f87d0fbb5798 ("vringh: host-side implementation of virtio rings.") Cc: stable@vger.kernel.org Assisted-by: Hawkeye:GLM-5.3-flash Assisted-by: Qoder:Qwen3.8-Max Signed-off-by: Fang Xieyan --- drivers/vhost/vringh.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) Changes in v2: - Commit message rewritten per Michael's review: the over-read value is copied into a local struct vring_desc and never reaches the caller, so the security framing ("leak" etc.) is dropped and this is presented as the plain out-of-bounds read fix it is. - Code is unchanged; the diff is identical to v1. Testing: Userspace reproducer carrying the move_to_indirect()/__vringh_iov() logic with an instrumented copy() (len == 0 indirect table, 2048-byte mapped region followed by 64 guard bytes): without the fix: reads 16 bytes past the table end, returns -ELOOP with the fix: returns -EINVAL, no read past the table end diff --git a/drivers/vhost/vringh.c b/drivers/vhost/vringh.c index 9066f9f..0767748 100644 --- a/drivers/vhost/vringh.c +++ b/drivers/vhost/vringh.c @@ -197,8 +197,9 @@ static int move_to_indirect(const struct vringh *vrh, } len = vringh32_to_cpu(vrh, desc->len); - if (unlikely(len % sizeof(struct vring_desc))) { - vringh_bad("Strange indirect len %u", desc->len); + if (unlikely(len < sizeof(struct vring_desc) || + len % sizeof(struct vring_desc))) { + vringh_bad("Invalid indirect len %u", desc->len); return -EINVAL; } -- 2.50.1