From nobody Fri Oct 2 11:44:02 2026 Received: from mail-qv1-f51.google.com (mail-qv1-f51.google.com [209.85.219.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A9903334C3D for ; Sat, 1 Aug 2026 10:45:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=209.85.219.51 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785581152; cv=pass; b=MrNbuVIDn5cqgR58yXQUGw+a0VemWE5ZdwcV9HCGrWryZIYvqNSo15vv3vcBQvOBqh8dp9FlX3wbHr74ChJQp0z84kdQ97FGBQqaam5Vkw4gspH/GAsHvXddbfQWy7LCs+wEcNzOOT0BXC25p9IjpxzQ5xOpJSqlRxQTHOuipa0= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785581152; c=relaxed/simple; bh=xw0mDJ/J+46rWB6ZD8G/eCScOkTXGEEN33n4aloiE6M=; h=MIME-Version:From:Date:Message-ID:Subject:To:Cc:Content-Type; b=mOP5JIweH6IqNa+Do/MrWcc1o0pzh69YMy2aNmGgvgGtBz7ltcGjou62xND2xyJzVZ+HwseGE3X1wGnNIPwM8Fv0J0hlHKzlxGOOJpQmIAhXpwUrBU5k8orUuqyJSm8wYYF4YhF0BT4NqT1ZdwieV9H4Y8r30IjbdMDFMVsHPTo= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Hw+MNrLR; arc=pass smtp.client-ip=209.85.219.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Hw+MNrLR" Received: by mail-qv1-f51.google.com with SMTP id 6a1803df08f44-90004d2f7b7so20283596d6.1 for ; Sat, 01 Aug 2026 03:45:50 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1785581149; cv=none; d=google.com; s=arc-20260327; b=SAEBCBQDxeCpDT+i+DwAnHoSuVZ1YFeY+qbzI1fSUh7Nl5FjkXC3LRJ6CtVBqlwyl0 zg0kGwjK23JH0MioE8UanTLxJ2ZoYPezERoGf7mPcx1b/tDHTEQ8bNYHIvG2fR7+8r8Z jHHmLhfIj24ItSqYYvA9JA236UqT5o5S1U86YfE2B+gccTTvKm3LRrA/FCHZxaQP/ynK 8XHQQDkqKVo1iUI+x2uPxdLz6XdgXL4k6j4mwlpBnXCfR7YMvZjeP7u6Qj73eHPbnS0Z mm2k8Z02wOA8SiKL0H6FF0ykcj/G1rFiELHdY0gSVHpdpVfaBpsI+6dVNk9s0Hr6n3HJ dP4w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=cc:to:subject:message-id:date:from:mime-version:dkim-signature; bh=uulZJQHRZOGVz9GVE1j0LkjMnS/Yn2XWMcuKNx0w1L4=; fh=CVR15WBrzKr9Y0kUSQodTMIOdIvVemQ99nY7VwVVzvs=; b=mf4LmLYcvqO3nwAO+gQPKzM81S2mRwXwyi2tDT96K5A3WBuPa87/Rd6tbQnHUZDi9n JG7NfyrmTG+v4DVO+XwjfEScK2pXmuZv9wQ8LjmEP72W6xpRlHne0yVhfNo6bRvmAZy4 y10GXRDMI86o2M+uL+2ararZ+HkUo9Rw4lipRwMTtsHWd675iPLx1D1d9ZS9SdQ3MAw+ EhKCPiMz/UEV/xECDR4w55sa0RuPcfG0FvHYOPvCofJzDhSHHKmOPQCR6ewJoRz97Szn E/pd3jbas6LrgRj+nRDb+xqe0wUdL9uYxUO3XOV3IKNcdSsufnl8dcuEu+KBkPmyszaj u1+w==; darn=vger.kernel.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785581149; x=1786185949; darn=vger.kernel.org; h=content-type:cc:to:subject:message-id:date:from:mime-version:from :to:cc:subject:date:message-id:reply-to:content-type; bh=uulZJQHRZOGVz9GVE1j0LkjMnS/Yn2XWMcuKNx0w1L4=; b=Hw+MNrLRDGXc7ja+divIa7qF/52+Gp/ZuRn0vxRsYiWlrC9hZkkrzCYmgfQO1y09Zi nDJ2PlDj91W1C3wQt0UX1dFaRGlUkSNPnvatRHB5WdmZUGF1djZl0UE9nMPm8CkqSwqO h/XcSY7w9FArChQDWQVMDL4y7w+/kd0BeTMFDIlHTr0/eCseKtUOd1wSoLc9FQ1ug/4D E4ypp8+qDJuueGeggttgKCMDg1UOXn9nYWSa2snx2sIUIWckWlhuHYpEkFgiZTwgPwNO qyekXVoxSyUyGUNGH9NnmlutTh2FynOHh0bQtc1VhtWkICXQjHDQ/USBWUuo3lp7/c8c cdgA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785581149; x=1786185949; h=content-type:cc:to:subject:message-id:date:from:mime-version :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to:content-type; bh=uulZJQHRZOGVz9GVE1j0LkjMnS/Yn2XWMcuKNx0w1L4=; b=g2jtnnc6hK/4jnpFvTJQNmDinOBjYThHB5LFGNgaPUfKGz/XUuR9aC+qZJmRLyDkRu A+5T4+Zh97xgELFmhMoEqmRJ2PPZzS1doHn48uF/joGWY2bKoB6P5Keakxr5LIbEyAoI rhpiTG44G6ZP4loaoBeAgSk4rx4APu5xxctoiuP3qmnyqTh3WPWGpyMfh3w3Nz0Ja1rv 0e0i0oX88uIGI1Sxp8x9xZl8p2IM4oiGChpt9trTus5AostmrMuJWtWhAtwJit0AbrbX HeQEC46OjSgQyN3qRw+4UtakzUdABfBWIgTUDaF+Pms58npHOXMmO8UvGY+sJBDXUash gDug== X-Forwarded-Encrypted: i=1; AHgh+Rpl2BZuDMZuIjdz7kyEkzy9xC086cE7SqgP+eeExrgYyjgK3F6PC/fM7qoWQXXSTEmWZCuJgCFY1Jv6hqI=@vger.kernel.org X-Gm-Message-State: AOJu0Yx7pmsfG8pq3ZsdKR52T3RpRpj4xCIzruxGhHZTIcw7zQ23gt+5 MO0Sr6IdsIMq49tjIOyS+LwLN2yi2/borYF0DVVCqlRT3ijGfzdB4qZQXBW+KXWSHqIym4ec2Ed wBRFxAkW/lPZUVTEzX8lbCNR6fiQ78sA= X-Gm-Gg: AR+sD12CUkmDV6UlTi4WgzJm/49FDDWPp/2UNNMAl56mOtlTTYFu4WlWvgR8P2CZncu PgI6XujvpGkKzWbEp7izVzoHRord6fm9nmjmSdVCq2ePUn4ZMC96kfw62vMcntfl54YoqF3fCUS 3Ck1Vpm3LztWKUhXykPke7mfuvOrHhFZai1G0KWdpn4qw8LhC8DfvkXx5O+W5kZ61vk//1rDTxb JKDhDNoooul3RlbxNCmZShr/7w/MYlqLN3xcuNDFWM9oKIcsQ4qSn6BTeRXZxUFGZ381EemOQnK Iriq7vOh9Uv7TVcUxp+nmPIWTQpf0b6+EilI0ylvhNhSCw== X-Received: by 2002:a05:6214:4014:b0:907:bfc0:781e with SMTP id 6a1803df08f44-90849673497mr56715356d6.30.1785581149291; Sat, 01 Aug 2026 03:45:49 -0700 (PDT) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: =?UTF-8?B?xJDhu6ljIEPhuqNuaCBOZ3V54buFbg==?= <0206canh@gmail.com> Date: Sat, 1 Aug 2026 17:45:37 +0700 X-Gm-Features: AUfX_mxSpiLlXpuQywhIuudO-6Ranqkb740b_MCeiEXPY-SlY4DJuNS9ya--BAM Message-ID: Subject: [PATCH] freevxfs: fix divide-by-zero in vxfs_bmap_ext4() causing oops on mount To: hch@infradead.org Cc: brauner@kernel.org, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org Content-Type: multipart/mixed; boundary="00000000000020176d0657fa02b8" --00000000000020176d0657fa02b8 Content-Type: multipart/alternative; boundary="00000000000020176c0657fa02b6" --00000000000020176c0657fa02b6 Content-Type: text/plain; charset="UTF-8" vxfs_bmap_ext4() divides by attacker-controlled values from the on-disk inode without fully validating them. A crafted VxFS image triggers a kernel "divide error" (oops) as soon as it is mounted -- no read or ioctl is required. The crash is reached from vxfs_fill_super() -> vxfs_iget() -> vxfs_get_page() -> vxfs_read_folio() -> vxfs_bmap1() -> vxfs_bmap_ext4(). Two independent paths hit the division by zero: 1. ve4_indsize == 0: line 62 computes the denominator (indsize * indsize * bsize / 4) == 0. The existing guard (line 52) only rejects indsize > s_blocksize, so 0 gets through. 2. bn == 0: if block 0 is not covered by the first direct extent (size == 0), bn stays 0 after the direct-extent loop. With indsize > 0 the expression at line 73, indir[(bn / indsize) % (indsize * bn)], becomes 0 % 0. Reproduced in QEMU on a 7.0.0-28-generic kernel: Oops: divide error: 0000 [#1] SMP NOPTI RIP: 0010:vxfs_bmap_ext4+0xfc/0x1c0 [freevxfs] RAX: 0000000000000000 RBX: 0000000000000000 RDX: 0000000000000000 Call Trace: vxfs_bmap_ext4+0xfc/0x1c0 [freevxfs] vxfs_bmap1+0x42/0x70 [freevxfs] vxfs_getblk+0x17/0x70 [freevxfs] block_read_full_folio+0x109/0x270 vxfs_read_folio+0x18/0x30 [freevxfs] vxfs_get_page+0x13/0x40 [freevxfs] __vxfs_iget+0x3a/0xd0 [freevxfs] vxfs_iget+0x5b/0x1a0 [freevxfs] vxfs_fill_super+0x159/0x340 [freevxfs] get_tree_bdev_flags+0x141/0x1e0 ... __x64_sys_mount+0x12b/0x160 Reject indsize == 0 up front and bail out when the logical block is 0. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: canhnguyen26 (Nguyen Duc Canh) <0206canh@gmail.com> --- fs/freevxfs/vxfs_bmap.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/freevxfs/vxfs_bmap.c b/fs/freevxfs/vxfs_bmap.c index e85222892038..4c2a5b42df3c 100644 --- a/fs/freevxfs/vxfs_bmap.c +++ b/fs/freevxfs/vxfs_bmap.c @@ -49,7 +49,7 @@ vxfs_bmap_ext4(struct inode *ip, long bn) unsigned long bsize = sb->s_blocksize; u32 indsize = fs32_to_cpu(sbi, vip->vii_ext4.ve4_indsize); int i; - if (indsize > sb->s_blocksize) + if (indsize == 0 || indsize > sb->s_blocksize) goto fail_size; for (i = 0; i < VXFS_NDADDR; i++) { @@ -62,7 +62,8 @@ vxfs_bmap_ext4(struct inode *ip, long bn) bn -= fs32_to_cpu(sbi, d->size); } - if ((bn / (indsize * indsize * bsize / 4)) == 0) { + if (bn == 0) + goto fail_buf; + if ((bn / (indsize * indsize * bsize / 4)) == 0) { struct buffer_head *buf; daddr_t bno; __fs32 *indir; -- 2.39.5 --00000000000020176c0657fa02b6 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
vxfs_bmap_ext4() divides by attacker-controlled values fro= m the on-disk
inode without fully validating them.=C2=A0 A crafted VxFS = image triggers a
kernel "divide error" (oops) as soon as it is= mounted -- no read or
ioctl is required.=C2=A0 The crash is reached fro= m vxfs_fill_super() ->
vxfs_iget() -> vxfs_get_page() -> vxfs_r= ead_folio() -> vxfs_bmap1() ->
vxfs_bmap_ext4().

Two indepe= ndent paths hit the division by zero:

1. ve4_indsize =3D=3D 0: line = 62 computes the denominator
=C2=A0 =C2=A0(indsize * indsize * bsize / 4)= =3D=3D 0.=C2=A0 The existing guard
=C2=A0 =C2=A0(line 52) only rejects = indsize > s_blocksize, so 0 gets through.

2. bn =3D=3D 0: if bloc= k 0 is not covered by the first direct extent
=C2=A0 =C2=A0(size =3D=3D = 0), bn stays 0 after the direct-extent loop.=C2=A0 With
=C2=A0 =C2=A0ind= size > 0 the expression at line 73,
=C2=A0 =C2=A0indir[(bn / indsize)= % (indsize * bn)], becomes 0 % 0.

Reproduced in QEMU on a 7.0.0-28-= generic kernel:

=C2=A0 Oops: divide error: 0000 [#1] SMP NOPTI
= =C2=A0 RIP: 0010:vxfs_bmap_ext4+0xfc/0x1c0 [freevxfs]
=C2=A0 RAX: 000000= 0000000000 RBX: 0000000000000000 RDX: 0000000000000000
=C2=A0 Call Trace= :
=C2=A0 =C2=A0 vxfs_bmap_ext4+0xfc/0x1c0 [freevxfs]
=C2=A0 =C2=A0 vx= fs_bmap1+0x42/0x70 [freevxfs]
=C2=A0 =C2=A0 vxfs_getblk+0x17/0x70 [freev= xfs]
=C2=A0 =C2=A0 block_read_full_folio+0x109/0x270
=C2=A0 =C2=A0 vx= fs_read_folio+0x18/0x30 [freevxfs]
=C2=A0 =C2=A0 vxfs_get_page+0x13/0x40= [freevxfs]
=C2=A0 =C2=A0 __vxfs_iget+0x3a/0xd0 [freevxfs]
=C2=A0 =C2= =A0 vxfs_iget+0x5b/0x1a0 [freevxfs]
=C2=A0 =C2=A0 vxfs_fill_super+0x159/= 0x340 [freevxfs]
=C2=A0 =C2=A0 get_tree_bdev_flags+0x141/0x1e0
=C2=A0= =C2=A0 ...
=C2=A0 =C2=A0 __x64_sys_mount+0x12b/0x160

Reject inds= ize =3D=3D 0 up front and bail out when the logical block is 0.

Fixe= s: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: canhnguyen= 26 (Nguyen Duc Canh) <0206canh@gma= il.com>
---
=C2=A0fs/freevxfs/vxfs_bmap.c | 4 +++-
=C2=A01 = file changed, 3 insertions(+), 1 deletion(-)

diff --git a/fs/freevxf= s/vxfs_bmap.c b/fs/freevxfs/vxfs_bmap.c
index e85222892038..4c2a5b42df3c= 100644
--- a/fs/freevxfs/vxfs_bmap.c
+++ b/fs/freevxfs/vxfs_bmap.c@@ -49,7 +49,7 @@ vxfs_bmap_ext4(struct inode *ip, long bn)
=C2=A0 uns= igned long bsize =3D sb->s_blocksize;
=C2=A0 u32 indsize =3D fs32_to_= cpu(sbi, vip->vii_ext4.ve4_indsize);
=C2=A0 int i;
=C2=A0
- if = (indsize > sb->s_blocksize)
+ if (indsize =3D=3D 0 || indsize >= sb->s_blocksize)
=C2=A0 goto fail_size;
=C2=A0
=C2=A0 for (i = =3D 0; i < VXFS_NDADDR; i++) {
@@ -62,7 +62,8 @@ vxfs_bmap_ext4(struc= t inode *ip, long bn)
=C2=A0 bn -=3D fs32_to_cpu(sbi, d->size);
= =C2=A0 }
=C2=A0
- if ((bn / (indsize * indsize * bsize / 4)) =3D=3D 0= ) {
+ if (bn =3D=3D 0)
+ goto fail_buf;
+ if ((bn / (indsize * in= dsize * bsize / 4)) =3D=3D 0) {
=C2=A0 struct buffer_head *buf;
=C2= =A0 daddr_t bno;
=C2=A0 __fs32 *indir;
--
2.39.5
--00000000000020176c0657fa02b6-- --00000000000020176d0657fa02b8 Content-Type: text/x-patch; charset="US-ASCII"; name="freevxfs-fix-divide-by-zero.patch" Content-Disposition: attachment; filename="freevxfs-fix-divide-by-zero.patch" Content-Transfer-Encoding: base64 Content-ID: X-Attachment-Id: f_msa8wkvu0 ZGlmZiAtLWdpdCBhL2ZzL2ZyZWV2eGZzL3Z4ZnNfYm1hcC5jIGIvZnMvZnJlZXZ4ZnMvdnhmc19i bWFwLmMKLS0tIGEvZnMvZnJlZXZ4ZnMvdnhmc19ibWFwLmMKKysrIGIvZnMvZnJlZXZ4ZnMvdnhm c19ibWFwLmMKQEAgLTQ5LDcgKzQ5LDcgQEAgdnhmc19ibWFwX2V4dDQoc3RydWN0IGlub2RlICpp cCwgbG9uZyBibikKIAl1bnNpZ25lZCBsb25nIGJzaXplID0gc2ItPnNfYmxvY2tzaXplOwogCXUz MiBpbmRzaXplID0gZnMzMl90b19jcHUoc2JpLCB2aXAtPnZpaV9leHQ0LnZlNF9pbmRzaXplKTsK IAlpbnQgaTsKIAotCWlmIChpbmRzaXplID4gc2ItPnNfYmxvY2tzaXplKQorCWlmIChpbmRzaXpl ID09IDAgfHwgaW5kc2l6ZSA+IHNiLT5zX2Jsb2Nrc2l6ZSkKIAkJZ290byBmYWlsX3NpemU7CiAK IAlmb3IgKGkgPSAwOyBpIDwgVlhGU19OREFERFI7IGkrKykgewpAQCAtNjIsNyArNjIsOCBAQCB2 eGZzX2JtYXBfZXh0NChzdHJ1Y3QgaW5vZGUgKmlwLCBsb25nIGJuKQogCQlibiAtPSBmczMyX3Rv X2NwdShzYmksIGQtPnNpemUpOwogCX0KIAotCWlmICgoYm4gLyAoaW5kc2l6ZSAqIGluZHNpemUg KiBic2l6ZSAvIDQpKSA9PSAwKSB7CisJaWYgKGJuID09IDApCisJCWdvdG8gZmFpbF9idWY7CisJ aWYgKChibiAvIChpbmRzaXplICogaW5kc2l6ZSAqIGJzaXplIC8gNCkpID09IDApIHsKIAkJc3Ry dWN0IGJ1ZmZlcl9oZWFkICpidWY7CiAJCWRhZGRyX3QJYm5vOwogCQlfX2ZzMzIgKmluZGlyOwo= --00000000000020176d0657fa02b8--