From nobody Sun Apr 5 16:36:20 2026 Received: from mail-pl1-f172.google.com (mail-pl1-f172.google.com [209.85.214.172]) (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 E7FC431354C for ; Wed, 1 Apr 2026 02:16:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775009803; cv=none; b=CPTaoB6alg+JuvQF7Q//dLrUA80NqMimk79S7iRoe5fRUK/58BXMipI25lanpzFSI/DZnJItDScTkPQbWAvoQPunldJJ/n2keYvHBvypW5dmB/agI4sQKyutqy8zQSedaneyNvyukAlpCEhsknDrMSpVAGZ8spGt8iScvMmetqs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775009803; c=relaxed/simple; bh=N8kMqBOJX93r+Vs28NGISdGP2MWTao8jJDmtRqhpOuY=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=gHS7oVxl7ZRPcQkbape9fu+oxTv+WqW071gFiN+LkpwY0N+GDb0SSqrytU3xiiRqVnYbhhTq2yJ4AZS6FNmksFhgUhrln67MonHY9jvyPjw4gXqqn8H5PWYaWCq1XWC9GjLnzMxTrMFyRTmmOGO6zGrksUcN7puKpbW8caxqVMo= ARC-Authentication-Results: i=1; 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=D7kbKi+U; arc=none smtp.client-ip=209.85.214.172 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="D7kbKi+U" Received: by mail-pl1-f172.google.com with SMTP id d9443c01a7336-2b23f90f53aso39627405ad.0 for ; Tue, 31 Mar 2026 19:16:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1775009801; x=1775614601; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=pkBv6FP2deV5lgxpjjtrzHLtwb/A6rKJwAEu5tfKaVs=; b=D7kbKi+U94M+etSqmh6pmdShOi+E+Ikai6Vz5ebdxO3mvqALBba3QSOockwcH05gJD BJeqJt20kNLoGMrESnEdQCxqFs+TKVKbEh8UiyQCrLZCNJdrbOw9QoxAbtWnMdamzu/n 0tlMpLaT8v64z36sPbds+tcklDE9rP1Eiiova+4U6JHDJH1xNDT6ie2INA5ZC3rX4W7u 9kpWuqbD7X8c7lR0EKeWBg1CwsXB6c7Mt9h+T4EAqDFULvBT6yHFeOTjDHxj4m8kVa3r Ewc0omyQ29fdu59eIsxNep1uDYVeeS/D4irLvBZbDDAPz4DkBSvRmtWjrvjpY7MuyzTv gqGw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775009801; x=1775614601; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=pkBv6FP2deV5lgxpjjtrzHLtwb/A6rKJwAEu5tfKaVs=; b=UvE69i5RGa4GrMsmtqEMhU2MkgHQr6/fUd9A1E4yDOgZQFy9szG8p7yaZ1A2EZ6f16 o8JlefQHpVq3gjeAEiJfDXmWQatBEDa6TxRvgSLGQNNVS0oKxp/hnngLAmHVgVk9MHwt AMjcFJcfmF6Ya+Vo00LTBnjg7p5zUaWZFJwmzF61F9DDcqJv6uFTtfcPfFPVH2kofqMr QqPyxGypNojXejOeLvVYaBO55Y0NkCm6xGPOlzXrHbgTHIHC5A1FPeo80hH8jYSsDTyv iWLpvS7/wFqTKDxdt4SWrEyc/BDK/Nf/Mt5K5zfqiSBZ5ryb7wVOC3+xbaLIH5PehuIN vPwQ== X-Forwarded-Encrypted: i=1; AJvYcCWqPaCaq6F9O64WlW8kgNJ31KdCR4NuDYElJSwynbQQLsTJrYeuo6oHvulaEYlZIXR9qaFf2kxPBpYdV9M=@vger.kernel.org X-Gm-Message-State: AOJu0YxxzAYGfVO3dQid7AxHRuGTpDyqziQ8RMsID92mVFsEcXZvGsfy Qw9EfMvKaWfegnYrX9UfWdigMwj82+3dxOowbfZi0UTvN60qMihnGIUF X-Gm-Gg: ATEYQzwN2SWmmWi8FiaeVNG4H8rsawT1o0uPeQs3YoAgwOaIFvfVt4DCmTvaNq2q8Xg QunPJoxb7saE1Rsym1EEfkxanD8shJ9dq7KThyhFiqKtDWIAYLedxtiP06rAjFRkK8jDGPf0pQj DKhW2gEQBzPnWe6Yjstpw516zOHqbj3Xk3gR/Nsq53pIGUTVopJt7ctxSKrZBERexmh4U5KjQwb ySEgUS+62U+aBjURyOrD65ypx+FJL1j3d+6yZ/UHFOcHKF6r4pmkCAIkJn5Uqxm9LFzrFyx/i9U XxXDg3SxlgrpizC5qCu+4UMZiW7yjVGYh2opQL39Ns8IS/KZcMKYHWGjsB9z4lE81hjrQZz/ZtB y01MtIqzd9QpusRlNebEIi8jTbn9fwf3U9n5b2NAPLHuGbk76oM0XbBzN0wfitYHtzy+KqLIxdh gZc2k/r9NaRsTSVFYX0I2UHbWcCGjIcvCWZZ+qKeKy/AE1suP0b6jpfdcKIkxsxAtb2V4xO+I= X-Received: by 2002:a17:903:946:b0:2b2:549f:7d2b with SMTP id d9443c01a7336-2b269b0d4bbmr14975385ad.11.1775009801207; Tue, 31 Mar 2026 19:16:41 -0700 (PDT) Received: from kernel-fuzz.. ([103.172.182.26]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2b24264292asm132156035ad.4.2026.03.31.19.16.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 31 Mar 2026 19:16:40 -0700 (PDT) From: ZhengYuan Huang To: mark@fasheh.com, jlbec@evilplan.org, joseph.qi@linux.alibaba.com Cc: ocfs2-devel@lists.linux.dev, linux-kernel@vger.kernel.org, baijiaju1990@gmail.com, r33s3n6@gmail.com, zzzccc427@gmail.com, ZhengYuan Huang Subject: [PATCH v2] ocfs2: validate bg_list extent bounds in discontig groups Date: Wed, 1 Apr 2026 10:16:22 +0800 Message-ID: <20260401021622.3560952-1-gality369@gmail.com> X-Mailer: git-send-email 2.43.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" [BUG] Running ocfs2 on a corrupted image with a discontiguous block group whose bg_list.l_next_free_rec is set to an excessively large value triggers a KASAN use-after-free crash: BUG: KASAN: use-after-free in ocfs2_bg_discontig_fix_by_rec fs/ocfs2/suball= oc.c:1678 [inline] BUG: KASAN: use-after-free in ocfs2_bg_discontig_fix_result+0x4a4/0x560 fs/= ocfs2/suballoc.c:1715 Read of size 4 at addr ffff88801a85f000 by task syz.0.115/552 Call Trace: ... __asan_report_load4_noabort+0x14/0x30 mm/kasan/report_generic.c:380 ocfs2_bg_discontig_fix_by_rec fs/ocfs2/suballoc.c:1678 [inline] ocfs2_bg_discontig_fix_result+0x4a4/0x560 fs/ocfs2/suballoc.c:1715 ocfs2_search_one_group fs/ocfs2/suballoc.c:1752 [inline] ocfs2_claim_suballoc_bits+0x13c3/0x1cd0 fs/ocfs2/suballoc.c:1984 ocfs2_claim_new_inode+0x2e7/0x8a0 fs/ocfs2/suballoc.c:2292 ocfs2_mknod_locked.constprop.0+0x121/0x2a0 fs/ocfs2/namei.c:637 ocfs2_mknod+0xc71/0x2400 fs/ocfs2/namei.c:384 ocfs2_create+0x158/0x390 fs/ocfs2/namei.c:676 lookup_open.isra.0+0x10a1/0x1460 fs/namei.c:3796 open_last_lookups fs/namei.c:3895 [inline] path_openat+0x11fe/0x2ce0 fs/namei.c:4131 do_filp_open+0x1f6/0x430 fs/namei.c:4161 do_sys_openat2+0x117/0x1c0 fs/open.c:1437 do_sys_open fs/open.c:1452 [inline] __do_sys_openat fs/open.c:1468 [inline] ... [CAUSE] ocfs2_bg_discontig_fix_result() iterates over bg->bg_list.l_recs[] using l_next_free_rec as the upper bound without any sanity check: for (i =3D 0; i < le16_to_cpu(bg->bg_list.l_next_free_rec); i++) { rec =3D &bg->bg_list.l_recs[i]; l_next_free_rec is read directly from the on-disk group descriptor and is trusted blindly. On a 4 KiB block device, bg_list.l_recs[] can hold at most 235 entries (ocfs2_extent_recs_per_gd(sb)). A corrupted or crafted filesystem image can set l_next_free_rec to an arbitrarily large value, causing the loop to index past the end of the group descriptor buffer_head data page and into an adjacent freed page. [FIX] Validate discontiguous bg_list.l_count against ocfs2_extent_recs_per_gd(sb), then reject l_next_free_rec values that exceed l_count. This keeps the on-disk extent list self-consistent and matches how the rest of ocfs2 uses l_count as the extent-list bound. Signed-off-by: ZhengYuan Huang Reviewed-by: Joseph Qi --- Changes in v2: - Validate bg_list.l_count against ocfs2_extent_recs_per_gd(sb). - Bound bg_list.l_next_free_rec by bg_list.l_count. - Update the changelog text to explain the l_count validation. --- fs/ocfs2/suballoc.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 6ac4dcd54588..29a8a878c2df 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -196,6 +196,31 @@ static int ocfs2_validate_gd_self(struct super_block *= sb, 8 * le16_to_cpu(gd->bg_size)); } =20 + /* + * For discontiguous block groups, validate the on-disk extent list + * against the maximum number of extent records that can physically + * fit in a single block. + */ + if (ocfs2_gd_is_discontig(gd)) { + u16 max_recs =3D ocfs2_extent_recs_per_gd(sb); + u16 l_count =3D le16_to_cpu(gd->bg_list.l_count); + u16 l_next_free_rec =3D le16_to_cpu(gd->bg_list.l_next_free_rec); + + if (l_count !=3D max_recs) { + do_error("Group descriptor #%llu bad discontig l_count %u expected %u\n= ", + (unsigned long long)bh->b_blocknr, + l_count, + max_recs); + } + + if (l_next_free_rec > l_count) { + do_error("Group descriptor #%llu bad discontig l_next_free_rec %u max %= u\n", + (unsigned long long)bh->b_blocknr, + l_next_free_rec, + l_count); + } + } + return 0; } =20 --=20 2.43.0