From nobody Sun Jul 26 01:45:47 2026 Received: from out30-118.freemail.mail.aliyun.com (out30-118.freemail.mail.aliyun.com [115.124.30.118]) (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 38E4E28CF5F for ; Fri, 10 Jul 2026 04:05:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=115.124.30.118 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783656323; cv=none; b=o42eSnV9/avgTvfLESfwvecE5Lcx9W7/GXGWx+XcXAozg+PgqZb+fExj7BbbJYPIso3NVIcOWbUChL0TMsYGtXb3UzrAQJ/aAcBvnaIqaBPR1nGN7b3CO/VgNwPAOgCPM48/ddVUerDi87qK3Va+2g0/0ybB5vDQF8tRTuCZMQ8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783656323; c=relaxed/simple; bh=rm79TWkic+Rq06rKReJm9mEJujRKDTmzQSoOVpmtwUI=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version; b=KEQGaZHEW/1hZGB4n/VK1maYx9j7viEQMt8BrUPRQtpvgpQHetf4cVaEF5kgPNLb7trITMA2PtIuaBeE/zBoOqNPh8+G7I7dunGGnxjqMbwuqnW580erebvWn/9RWfIFpSPdJCvKiSFcvftAC4FZ4SDptanucEc2m3+VY8jopsw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.alibaba.com; spf=pass smtp.mailfrom=linux.alibaba.com; dkim=pass (1024-bit key) header.d=linux.alibaba.com header.i=@linux.alibaba.com header.b=A+H1nci7; arc=none smtp.client-ip=115.124.30.118 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.alibaba.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.alibaba.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.alibaba.com header.i=@linux.alibaba.com header.b="A+H1nci7" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.alibaba.com; s=default; t=1783656313; h=From:To:Subject:Date:Message-Id:MIME-Version; bh=WlUeLkABVKtf7psjdIBHU9lx9UC31omiBN1CwOJFo3A=; b=A+H1nci7EcpJM4QYXPrChftVcSgRrHkxod9o/PFhVjC+G4No1+BsfT4MHiEeS/K9deTDhDrRjp+ABG3IMfTj2YbOpFjAlaj6v4entYiHezxUxFXj8JGyCoBYr5YgbOCyNsAyeW2TPieBBX3aQkTV5saFCWJXkcAhGO4+6MDJBc0= X-Alimail-AntiSpam: AC=PASS;BC=-1|-1;BR=01201311R301e4;CH=green;DM=||false|;DS=||;FP=0|-1|-1|-1|0|-1|-1|-1;HT=maildocker-contentspam033037033178;MF=joseph.qi@linux.alibaba.com;NM=1;PH=DS;RN=5;SR=0;TI=SMTPD_---0X6mRzPB_1783656312; Received: from localhost(mailfrom:joseph.qi@linux.alibaba.com fp:SMTPD_---0X6mRzPB_1783656312 cluster:ay36) by smtp.aliyun-inc.com; Fri, 10 Jul 2026 12:05:12 +0800 From: Joseph Qi To: Andrew Morton , Heming Zhao Cc: Dmitry Antipov , ocfs2-devel@lists.linux.dev, linux-kernel@vger.kernel.org Subject: [PATCH] ocfs2: fix boundary check in ocfs2_check_dir_entry() to use buffer offset Date: Fri, 10 Jul 2026 12:05:12 +0800 Message-Id: <20260710040512.3310736-1-joseph.qi@linux.alibaba.com> X-Mailer: git-send-email 2.39.3 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" Commit 390ac56cf0f6 ("ocfs2: add boundary check to ocfs2_check_dir_entry()") added an out-of-bounds guard using the caller-supplied 'offset' argument: if (offset > size - OCFS2_DIR_REC_LEN(1)) return 0; However, 'offset' and 'size' are not measured against the same base for all callers. In the block-based lookup path, ocfs2_find_entry_el() passes 'offset' as an absolute offset into the whole directory: i =3D ocfs2_search_dirblock(bh, dir, name, namelen, block << sb->s_blocksize_bits, bh->b_data, sb->s_blocksize, res_dir); while 'size' is a single block size (sb->s_blocksize). For any directory entry located in the second or later block, 'offset' is >=3D sb->s_blocksiz= e, so the guard rejects every such entry even though it is perfectly valid and lies entirely within its block buffer. This makes mounting fail for filesystems whose system directory spans more than one block, e.g. a volume formatted with a small block size: mkfs.ocfs2 -b 512 -C 4096 -N 2 -T datafiles --fs-features=3Dusrquota,grpq= uota ocfs2_check_dir_entry:314 ERROR: directory entry (#18: offset=3D512) too = close to end or out-of-bounds ocfs2_init_local_system_inodes:496 ERROR: status=3D-22, sysfile=3D12, slo= t=3D0 ocfs2_mount_volume:1757 ERROR: status =3D -22 The dirent's position within the buffer being validated is ((char *)de - buf), which is what the rest of the function already uses (via next_offset) and what must be bounds-checked against 'size'. Compute that buffer-relative offset and use it for the guard. The subtraction is reordered to size - buf_offset < OCFS2_DIR_REC_LEN(1) to avoid an unsigned underflow when size is smaller than the minimal record length. Fixes: 390ac56cf0f6 ("ocfs2: add boundary check to ocfs2_check_dir_entry()") Cc: stable@vger.kernel.org Signed-off-by: Joseph Qi --- fs/ocfs2/dir.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index 8e6b032383278..d7fc3cccf2f4b 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c @@ -302,10 +302,11 @@ static int ocfs2_check_dir_entry(struct inode *dir, unsigned long offset) { const char *error_msg =3D NULL; + unsigned long buf_offset =3D (char *)de - buf; unsigned long next_offset; int rlen; =20 - if (offset > size - OCFS2_DIR_REC_LEN(1)) { + if (buf_offset > size || size - buf_offset < OCFS2_DIR_REC_LEN(1)) { /* Dirent is (maybe partially) beyond the buffer * boundaries so touching 'de' members is unsafe. */ @@ -316,7 +317,7 @@ static int ocfs2_check_dir_entry(struct inode *dir, } =20 rlen =3D le16_to_cpu(de->rec_len); - next_offset =3D ((char *) de - buf) + rlen; + next_offset =3D buf_offset + rlen; =20 if (unlikely(rlen < OCFS2_DIR_REC_LEN(1))) error_msg =3D "rec_len is smaller than minimal"; --=20 2.39.3