From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pj1-f44.google.com (mail-pj1-f44.google.com [209.85.216.44]) (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 BB1D0157487 for ; Thu, 16 Apr 2026 08:21:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.44 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776327679; cv=none; b=cRK6KBofgh5L0GCY2opi35rgwuBvaTNGJZgwm7NB2WIHfARh086CmPtbC+VmiESSrZHvVShwTPp2hi1Hje53NyqDUCRpf7RWDK69TOjAiF9RMrUclvhd8/0ylEZ609TlZ/6w6jcaYxelsAHIY0H7mom2oSMs6enuBIGwVOOqqeg= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776327679; c=relaxed/simple; bh=rXZgWhf6RU6t2TQ8pUUk0XEOqGcsFxBwtq/oN0feW/Y=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=SDkfTBqlOBu+GQMY4KrXad79WpTZtlZlMuZcdJ9CfmwxqsCz5n6gAaFiZUapYZ3hiSsUck5U9DUspQWThxF0M2NvAAo43gvml7I3+m9rAzfvWpXXsmcx/xCjfcylo55eF2J1D13sO9zRAPJ5mfHUf6W6xvxuMgpjixEa44vUc8U= 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=tKqpw/wn; arc=none smtp.client-ip=209.85.216.44 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="tKqpw/wn" Received: by mail-pj1-f44.google.com with SMTP id 98e67ed59e1d1-35d965648a2so6650679a91.0 for ; Thu, 16 Apr 2026 01:21:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776327677; x=1776932477; 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=jDZnjSVKHLSnbqxqD+kJoFN/wG42/6FEZwqR7tAgE1c=; b=tKqpw/wnBRy5eo99rrN3e8oxFjFOaTUonWGfXqoOgG9Ho47nlu0TJamQUv3pBizARG MO8VsPqRyE92CGX8Bbxif6JrjzgMG6TRBDAG3fb+/IcLsSPawA05Q65pqBiXP4hcVRSi cjXESPwIMGovIt9isXDlZVrYOlx3jRrgBHjRezFhmG6Ttnn1GxFAtXzhaq9+Z5Bt4RLa ZYDfvI+xeY5A+csN0sU4iLhYBFJhKrMxkFMGxoR00Tk6oaJdNwesr1TY/CIH4IBCrhYx E0GeTMMt/hudjmm8l0cBTZH/V9rV12tUS5kF8G4mvfSktpR59Ankj28v0Jm7xWORvZFw rDSQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776327677; x=1776932477; 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=jDZnjSVKHLSnbqxqD+kJoFN/wG42/6FEZwqR7tAgE1c=; b=ROQ7cqMBqD70AbOS3X15LTX9B0ZR2pfEiVL2NR6/PDmp1gkojA0V4mkgMHGM7sx9vu lK8njY3AVNF1fZfnJRMopKw+uMv9C2aR8h51710/1XAB+BXvPkeHGlTBunz6Gog4phsz 8Yr/FXvb5o9Oh1y4ypTvvb/MSJ3Adv+0hQ85XlfMk6OIUDn/79Pkbeqff5psWvsAUT8f qSVWq54sUHRBWeTvnaqbJfJexJNViAKI4RdttQIOExJYiwFNULVxz13uD/GpsrWDhwRT /9SoNUoHEtqIptDVKiEEDCrkT0OgkT1ElGsmbvUtCqJazw8QMZIELnCjU08wN/tpJe3N I3xg== X-Forwarded-Encrypted: i=1; AFNElJ+9v/IQC/MugQwRUtAOJksJ5giY+ACFT9/zEtFS8KZzS+ZHDmFELecYiiuPEc8Mus1Z1BwKrazg89aa/XA=@vger.kernel.org X-Gm-Message-State: AOJu0YxeMKAgm97vHI1mTFaVpqrNsJjVYMFpkq4H5Q418baJq+Nk6E90 Y8BjGChya/3b5Qrn09IQs81K9MxiuQZ6UiRLBCRb0UkUhbH1/JMImiLu X-Gm-Gg: AeBDieu8pzUH4WeZrEwCuW3qxn2le35lndPhZl5V45Efnk2uaWR4Y8EyDeCqq7k3A81 6NtaRiUrfLybm+RgVtcn8C+ZyWa8eeWkFja816Uebjb3klIUw4YN0ak0bKNtzSWdvQV/tTzHb/S bJ10dDBvI+WmzODudWcESlWVl88Vm6RhXygmexnqTDbH7nTOsCtJLIyvrMvarke+hXg5w4l3amP VXr1MdRDqJ7gav1gI9VuHwswEWa+/RBRxX74ACeMWsdB1dZDI27pV8UUbau0B3mbibjj19aA1n1 iG68XCFykUUQ4su3ofNF0wRsGzfgMLtf64yplpeAbmAarbGG3qPIqSZScI300B0lTj7ff0o5KET dcfAoRB6xgmCb1H+V7MQ5l1/euYH7tCVEOsnvuDtL/XmnUnbLSsnRmn9N5XrbxrcUIOmKW+kOg1 XMiCPBUCo1HqOZ/anlZffJsDmILDfxWk04f8EhUPe0Y1Zhaan0BZComF1wEc8yU89nbZgClTw= X-Received: by 2002:a05:6300:8a05:b0:398:ac0d:9a0b with SMTP id adf61e73a8af0-39fe4057490mr21298837637.50.1776327676866; Thu, 16 Apr 2026 01:21:16 -0700 (PDT) Received: from kernel-fuzz.. ([103.172.182.26]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-82f8066a240sm435563b3a.20.2026.04.16.01.21.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 16 Apr 2026 01:21:16 -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 dx entry list counts on read Date: Thu, 16 Apr 2026 16:21:05 +0800 Message-ID: <20260416082105.1295887-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: 8bit [BUG] A corrupt indexed directory block can carry de_num_used larger than de_count. When create() needs to rebalance the directory index, that corrupt count reaches ocfs2_dx_dir_transfer_leaf() and trips fortify: kernel BUG at lib/string_helpers.c:1043! RIP: 0010:__fortify_panic+0x24/0x30 lib/string_helpers.c:1043 Call Trace: fortify_memset_chk include/linux/fortify-string.h:497 [inline] ocfs2_dx_dir_transfer_leaf fs/ocfs2/dir.c:3677 [inline] ocfs2_dx_dir_rebalance.isra.0+0x231a/0x24c0 fs/ocfs2/dir.c:3873 ocfs2_find_dir_space_dx.isra.0+0x32c/0x5f0 fs/ocfs2/dir.c:3950 ocfs2_prepare_dx_dir_for_insert.isra.0+0x750/0xf20 fs/ocfs2/dir.c:4207 ocfs2_prepare_dir_for_insert+0xe79/0x1630 fs/ocfs2/dir.c:4288 ocfs2_mknod+0x81c/0x2400 fs/ocfs2/namei.c:297 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] DX leaf and inline dx root blocks validate signatures and ECC, but they do not validate the geometry of struct ocfs2_dx_entry_list. Corrupt de_count/de_num_used values therefore survive block read and are later used as traversal bounds and memset lengths in lookup, delete and rebalance paths. [FIX] Validate dx entry-list geometry in the metadata read callbacks. de_count must match the block layout for the current superblock, and de_num_used must not exceed de_count. Do this for both dx leaves and inline dx roots so corrupted metadata is rejected before any caller walks or rewrites de_entries[]. Signed-off-by: ZhengYuan Huang --- No Fixes tag is included because this is a missing metadata validation check, not a regression attributable to a single introducing commit. --- fs/ocfs2/dir.c | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index 8e6b03238327..a89634e20b32 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c @@ -578,6 +578,29 @@ static int ocfs2_read_dir_block_direct(struct inode *dir, u64 phys, return ret; } +static int ocfs2_validate_dx_entry_list(struct super_block *sb, u64 blkno, + struct ocfs2_dx_entry_list *entry_list, + unsigned int expected, + const char *owner) +{ + unsigned int count = le16_to_cpu(entry_list->de_count); + unsigned int num_used = le16_to_cpu(entry_list->de_num_used); + + if (count != expected) + return ocfs2_error(sb, + "%s # %llu has invalid de_count %u (expected %u)\n", + owner, (unsigned long long)blkno, count, + expected); + + if (num_used > count) + return ocfs2_error(sb, + "%s # %llu has invalid de_num_used %u (de_count %u)\n", + owner, (unsigned long long)blkno, num_used, + count); + + return 0; +} + static int ocfs2_validate_dx_root(struct super_block *sb, struct buffer_head *bh) { @@ -604,7 +625,14 @@ static int ocfs2_validate_dx_root(struct super_block *sb, goto bail; } - if (!(dx_root->dr_flags & OCFS2_DX_FLAG_INLINE)) { + if (dx_root->dr_flags & OCFS2_DX_FLAG_INLINE) { + ret = ocfs2_validate_dx_entry_list(sb, bh->b_blocknr, + &dx_root->dr_entries, + ocfs2_dx_entries_per_root(sb), + "Dir Index Root"); + if (ret) + goto bail; + } else { struct ocfs2_extent_list *el = &dx_root->dr_list; if (le16_to_cpu(el->l_count) != ocfs2_extent_recs_per_dx_root(sb)) { @@ -660,13 +688,21 @@ static int ocfs2_validate_dx_leaf(struct super_block *sb, mlog(ML_ERROR, "Checksum failed for dir index leaf block %llu\n", (unsigned long long)bh->b_blocknr); - return ret; + goto bail; } if (!OCFS2_IS_VALID_DX_LEAF(dx_leaf)) { ret = ocfs2_error(sb, "Dir Index Leaf has bad signature %.*s\n", 7, dx_leaf->dl_signature); + goto bail; } + ret = ocfs2_validate_dx_entry_list(sb, bh->b_blocknr, + &dx_leaf->dl_list, + ocfs2_dx_entries_per_leaf(sb), + "Dir Index Leaf"); + +bail: + return ret; } -- 2.43.0