From nobody Wed Apr 1 09:46:38 2026 Received: from mail-pj1-f54.google.com (mail-pj1-f54.google.com [209.85.216.54]) (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 4FAF53290CB for ; Tue, 31 Mar 2026 13:31:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774963912; cv=none; b=UwZMwLo8TSMR6sYzIfYdc+xG9bO9LfW7lpMwn737hUyx8ZGFK+byvdoK2VevecnuZFpH27j+0aKepoddApQVRknCAJA5qXiE8byUD2RXj+yUDEn8FReeGqrGtYqrqKVI+wtYIXQZ7XvTpwfSaOXwJvdtAodrRAd1IvKXA66x1Ww= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774963912; c=relaxed/simple; bh=m5CBGrM+6+LszPbi68nNgQBYQZANFLsWy/WMD5SOrbw=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=l54/xYzKFUiWEaptu0ReniBLHOctJjjX67yciMZAeH3/9NBbgqjHp0N2xKm/9KSW5LXTWfJB2JWpx+nbSXSzGvy5tKWq9y/Uf9+qzSatA6OwuaTmkbqqqkBK69fX+pKMbMAi+IJHsjfnaP9X1uEe0jfZKACCFzREktZSWSuEIPY= 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=jMsHEJtz; arc=none smtp.client-ip=209.85.216.54 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="jMsHEJtz" Received: by mail-pj1-f54.google.com with SMTP id 98e67ed59e1d1-35d94f4ee36so1854153a91.3 for ; Tue, 31 Mar 2026 06:31:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1774963911; x=1775568711; 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=EOrhnZnCh2rpQmJ1V2h/7OPGGw+8zSWT5Qa5xYP2Wzc=; b=jMsHEJtzXSZ2sRa8pqwOgPsf3b9tQqwWK0iz0k+Nrc9EZ6KTIN6M7fqqGqiKBF/a9c qRifd3Zlu28IFibP9U2oKCUxJbqgH8+c3PWDXKai9xPzgaJdbA1HUqBjFYWv4x8ilxv6 RFQSuMwcZqQ1GVQYt3JqDdI65f2WMP1+XHIqmWRlrYPFJCzKmo6V2JqT1bTQylJN1Knh kELGuW409r7Gt4acCfbqPP+xYXAytNEsmq6GsjhRWAG5FXMDappWpsi9ShOC+8hTwHEm YeiTUrTnwQiGnXQMaClQjAScSrZeGkf/etm4FeF00DQy76k+Xo7GmBiT4A6rQSZ2c/9C 9flg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774963911; x=1775568711; 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=EOrhnZnCh2rpQmJ1V2h/7OPGGw+8zSWT5Qa5xYP2Wzc=; b=AWUgAWY8Hjcc9gGOFuEP+RHmp9LF2fAmgUahi+8DmV5OnX3z/KNLUPEhgac4dCxaEB BnuaKFy7pPpqzmzovt7V0e8VwJk1784shMbY7z5ErQ3j8vD2FUlu2wDmkFiFGCY6bTrk TQKNzvwO2rmQVmXgHTgbc+395+2uRaWKySA0q02bmoL0YyYQNFdw9wdPeqX7AjZFVzSQ vAagIISb6Feed7GU4HV+qtJXGFHmYI/E4SQNBtk6gD/J62kT93zzpl2LzKAvET9/bpgD hMo+9LlVwgizALM9Oj46NlRe5hL9OVgMvA0LWWWR+FxJ3n+XasnsTAVy6dgzaZ3wl/VZ f5eA== X-Forwarded-Encrypted: i=1; AJvYcCXd5AaxF1AFMiChnt+7M6F49r6bdUiUQsTF0hzaLnkijmgcORmVvdJiUqw/BI5zz3Mt7GOZuiLOebl1et0=@vger.kernel.org X-Gm-Message-State: AOJu0Ywi99URBaxPPrWJD3exJAJ4dTcMEfF+l1ASJ1RUVh2HtbXIGC7l OPZWXA4Ps/ifb9X0jWZftTg9ZaIifd/3KXEKWaVGwKNePx4VJGkUtQcK X-Gm-Gg: ATEYQzxEaoR7IYnapzesDKebRP1pryf1OlrpG7XFd7mTWLDLM2gJz1X9ow/w/RagPc4 AL77oLGYL3h7sNKjtuVnOTgPM6QZh1CC6QrbL5F9/wo+g4ZEtkMbTUH4htecvkVnLQ6EPJ02w1T SYysKFMau0yB/N5/TiwxIm1tiRNf3813zUd5qffDDwEHWaQesKAzD+do62K0C2fe3ltWPB/SYhh MncUsImsgjMZBs23TClzLLoIw0V5BRngSxK2880N5d6lDXV+X2qHDc24VZd45HyobUaIMcIfDpe E4i6ucNjzVBDnE1oDAabxnGgtQJikoviKcbuKSXLiYE95jtUgfm6rrYtML+jaK657PdGu9zpbQw ZhppBG/FRz7HOYBztHHyboebJHoUejC+9ikkstkv8JF24DGPJeUykmak18AhiZA4uFMfzZgzNON 4U46LNN443P6x6XOZ9A+LMvDmhV2xYWhZndToSvFGnxnBC/GVAW5qrt3Y0H7ONXQrIs06vStg= X-Received: by 2002:a17:90b:4c52:b0:35d:a2aa:3b05 with SMTP id 98e67ed59e1d1-35da2aa3d37mr9160415a91.5.1774963908946; Tue, 31 Mar 2026 06:31:48 -0700 (PDT) Received: from kernel-fuzz.. ([103.172.182.26]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35dba5d9529sm757088a91.3.2026.03.31.06.31.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 31 Mar 2026 06:31:48 -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] ocfs2: validate bg_list.l_next_free_rec in discontig group descriptor Date: Tue, 31 Mar 2026 21:31:33 +0800 Message-ID: <20260331133134.1842372-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] __se_sys_openat fs/open.c:1463 [inline] __x64_sys_openat+0x15b/0x220 fs/open.c:1463 ... [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] Fix this by adding a bounds check in ocfs2_validate_gd_self(), which is called for every group descriptor read via ocfs2_read_group_descriptor(). Use ocfs2_gd_is_discontig() to restrict the check to discontiguous block groups, and ocfs2_extent_recs_per_gd(sb) as the physical upper bound (rather than trusting the on-disk l_count, which could also be corrupted). This follows the same do_error() pattern used by the existing field sanity checks in ocfs2_validate_gd_self(). Signed-off-by: ZhengYuan Huang --- fs/ocfs2/suballoc.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 6ac4dcd54588..6dcf45fda457 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -196,6 +196,22 @@ static int ocfs2_validate_gd_self(struct super_block *= sb, 8 * le16_to_cpu(gd->bg_size)); } =20 + /* + * For discontiguous block groups, validate that bg_list.l_next_free_rec + * does not exceed the maximum number of extent records that can physical= ly + * fit in a single block. + */ + if (ocfs2_gd_is_discontig(gd)) { + u16 max_recs =3D ocfs2_extent_recs_per_gd(sb); + + if (le16_to_cpu(gd->bg_list.l_next_free_rec) > max_recs) { + do_error("Group descriptor #%llu bad discontig l_next_free_rec %u max %= u\n", + (unsigned long long)bh->b_blocknr, + le16_to_cpu(gd->bg_list.l_next_free_rec), + max_recs); + } + } + return 0; } =20 --=20 2.43.0