linux/fs/ocfs2
Joseph Qi df8ce7ab48 ocfs2: fix boundary check in ocfs2_check_dir_entry() to use buffer offset
Commit 390ac56cf0 ("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 = 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 >=
sb->s_blocksize, 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=usrquota,grpquota

  ocfs2_check_dir_entry:314 ERROR: directory entry (#18: offset=512) too close to end or out-of-bounds
  ocfs2_init_local_system_inodes:496 ERROR: status=-22, sysfile=12, slot=0
  ocfs2_mount_volume:1757 ERROR: status = -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.

Link: https://lore.kernel.org/20260710040512.3310736-1-joseph.qi@linux.alibaba.com
Fixes: 390ac56cf0 ("ocfs2: add boundary check to ocfs2_check_dir_entry()")
Signed-off-by: Joseph Qi <joseph.qi@linux.alibaba.com>
Reviewed-by: Dmitry Antipov <dmantipov@yandex.ru>
Tested-by: Dmitry Antipov <dmantipov@yandex.ru>
Cc: Mark Fasheh <mark@fasheh.com>
Cc: Joel Becker <jlbec@evilplan.org>
Cc: Junxiao Bi <junxiao.bi@oracle.com>
Cc: Changwei Ge <gechangwei@live.cn>
Cc: Jun Piao <piaojun@huawei.com>
Cc: Heming Zhao <heming.zhao@suse.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
2026-07-20 17:41:28 -07:00
..
cluster ocfs2/heartbeat: fix slot mapping rollback leaks on error paths 2026-04-15 02:15:01 -07:00
dlm mm.git review status for mm-hotfixes-stable..mm-nonmm-stable 2026-06-21 13:20:19 -07:00
dlmfs treewide: change inode->i_ino from unsigned long to u64 2026-03-06 14:31:28 +01:00
acl.c fs: inline current_umask() and move it to fs_struct.h 2025-11-05 22:51:23 +01:00
acl.h fs: port ->set_acl() to pass mnt_idmap 2023-01-19 09:24:27 +01:00
alloc.c ocfs2: reject FITRIM ranges shorter than a cluster 2026-06-04 14:49:29 -07:00
alloc.h ocfs2: convert ocfs2_map_and_dirty_page() to ocfs2_map_and_dirty_folio() 2025-01-12 20:21:13 -08:00
aops.c ocfs2: fix circular locking dependency in ocfs2_dio_end_io_write 2026-06-17 15:37:48 -07:00
aops.h ocfs2: remove ocfs2_start_walk_page_trans() prototype 2025-01-12 20:21:13 -08:00
blockcheck.c treewide: remove editor modelines and cruft 2021-05-07 00:26:34 -07:00
blockcheck.h treewide: remove editor modelines and cruft 2021-05-07 00:26:34 -07:00
buffer_head_io.c mm.git review status for mm-hotfixes-stable..mm-nonmm-stable 2026-06-21 13:20:19 -07:00
buffer_head_io.h treewide: remove editor modelines and cruft 2021-05-07 00:26:34 -07:00
dcache.c for_each_alias(): helper macro for iterating through dentries of given inode 2026-04-02 03:45:02 -04:00
dcache.h treewide: remove editor modelines and cruft 2021-05-07 00:26:34 -07:00
dir.c ocfs2: fix boundary check in ocfs2_check_dir_entry() to use buffer offset 2026-07-20 17:41:28 -07:00
dir.h treewide: remove editor modelines and cruft 2021-05-07 00:26:34 -07:00
dlmglue.c ocfs2: rebase copied fsdlm LVB pointers in locking_state 2026-06-04 14:49:26 -07:00
dlmglue.h ocfs2: convert ocfs2_inode_lock_with_page() to ocfs2_inode_lock_with_folio() 2025-01-12 20:21:10 -08:00
export.c ocfs2: detect released suballocator BG for fh_to_[dentry|parent] 2026-01-20 19:44:16 -08:00
export.h treewide: remove editor modelines and cruft 2021-05-07 00:26:34 -07:00
extent_map.c treewide: change inode->i_ino from unsigned long to u64 2026-03-06 14:31:28 +01:00
extent_map.h treewide: remove editor modelines and cruft 2021-05-07 00:26:34 -07:00
file.c ocfs2: reject inconsistent inode size before truncate 2026-05-28 21:24:47 -07:00
file.h ocfs2: store cookie in private data 2024-09-12 11:58:44 +02:00
filecheck.c treewide: Replace kmalloc with kmalloc_obj for non-scalar types 2026-02-21 01:02:28 -08:00
filecheck.h treewide: remove editor modelines and cruft 2021-05-07 00:26:34 -07:00
heartbeat.c ocfs2: fix a typo in a comment 2022-07-29 18:12:36 -07:00
heartbeat.h treewide: remove editor modelines and cruft 2021-05-07 00:26:34 -07:00
inode.c ocfs2: fix UBSAN array-index-out-of-bounds in ocfs2_sum_rightmost_rec 2026-06-17 15:37:46 -07:00
inode.h ocfs2: retire ocfs2_drop_inode() and I_WILL_FREE usage 2025-10-20 20:22:25 +02:00
ioctl.c ocfs2: validate bg_bits during freefrag scan 2026-04-15 02:15:03 -07:00
ioctl.h tree-wide: s/struct fileattr/struct file_kattr/g 2025-07-04 16:14:39 +02:00
journal.c ocfs2: fix NULL h_transaction deref in ocfs2_assure_trans_credits 2026-06-17 15:37:47 -07:00
journal.h ocfs2: add journal NULL check in ocfs2_checkpoint_inode() 2026-06-04 14:49:28 -07:00
Kconfig fs: add CONFIG_BUFFER_HEAD 2023-08-02 09:13:09 -06:00
localalloc.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
localalloc.h treewide: remove editor modelines and cruft 2021-05-07 00:26:34 -07:00
locks.c ocfs2: adapt to breakup of struct file_lock 2024-02-05 13:11:43 +01:00
locks.h treewide: remove editor modelines and cruft 2021-05-07 00:26:34 -07:00
Makefile
mmap.c ocfs2: fix use-after-free in ocfs2_fault() when VM_FAULT_RETRY 2026-04-15 02:15:02 -07:00
mmap.h fs: replace mmap hook with .mmap_prepare for simple mappings 2025-06-19 13:56:59 +02:00
move_extents.c ocfs2: avoid moving extents to occupied clusters 2026-06-17 15:37:47 -07:00
move_extents.h treewide: remove editor modelines and cruft 2021-05-07 00:26:34 -07:00
namei.c ocfs2: Drop pointless sync_mapping_buffers() calls 2026-03-26 15:03:27 +01:00
namei.h treewide: remove editor modelines and cruft 2021-05-07 00:26:34 -07:00
ocfs1_fs_compat.h treewide: remove editor modelines and cruft 2021-05-07 00:26:34 -07:00
ocfs2_fs.h ocfs2: annotate more flexible array members with __counted_by_le() 2026-01-20 19:44:18 -08:00
ocfs2_ioctl.h ocfs2: miscellaneous spelling fixes 2025-01-12 20:21:07 -08:00
ocfs2_lockid.h ocfs2: miscellaneous spelling fixes 2025-01-12 20:21:07 -08:00
ocfs2_lockingver.h treewide: remove editor modelines and cruft 2021-05-07 00:26:34 -07:00
ocfs2_trace.h ocfs2: fix use-after-free in ocfs2_fault() when VM_FAULT_RETRY 2026-04-15 02:15:02 -07:00
ocfs2.h ocfs2: kill osb->system_file_mutex lock 2026-05-28 21:24:57 -07:00
quota_global.c ocfs2: fix deadlock when creating quota file 2026-03-27 21:19:38 -07:00
quota_local.c ocfs2: use kzalloc for quota recovery bitmap allocation 2026-05-28 21:24:40 -07:00
quota.h ocfs2: remove unused declaration in header file 2024-11-05 17:12:26 -08:00
refcounttree.c ocfs2: fix out-of-bounds write in ocfs2_remove_refcount_extent 2026-06-04 14:49:29 -07:00
refcounttree.h treewide: remove editor modelines and cruft 2021-05-07 00:26:34 -07:00
reservations.c ocfs2: correctly use ocfs2_find_next_zero_bit() 2024-04-25 21:07:01 -07:00
reservations.h ocfs2: miscellaneous spelling fixes 2025-01-12 20:21:07 -08:00
resize.c ocfs2: validate group add input before caching 2026-04-15 02:15:03 -07:00
resize.h treewide: remove editor modelines and cruft 2021-05-07 00:26:34 -07:00
slot_map.c Convert more 'alloc_obj' cases to default GFP_KERNEL arguments 2026-02-21 20:03:00 -08:00
slot_map.h treewide: remove editor modelines and cruft 2021-05-07 00:26:34 -07:00
stack_o2cb.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
stack_user.c ocfs2: fix race between ocfs2_control_install_private() and ocfs2_control_release() 2026-06-04 14:49:29 -07:00
stackglue.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
stackglue.h ocfs2: miscellaneous spelling fixes 2025-01-12 20:21:07 -08:00
suballoc.c ocfs2: reject oversized group bitmap descriptors 2026-06-04 14:49:27 -07:00
suballoc.h ocfs2: fix the issue with discontiguous allocation in the global_bitmap 2025-05-07 23:39:37 -07:00
super.c mm.git review status for mm-hotfixes-stable..mm-nonmm-stable 2026-06-21 13:20:19 -07:00
super.h treewide: remove editor modelines and cruft 2021-05-07 00:26:34 -07:00
symlink.c ocfs2: use a folio in ocfs2_fast_symlink_read_folio() 2025-01-12 20:21:13 -08:00
symlink.h treewide: remove editor modelines and cruft 2021-05-07 00:26:34 -07:00
sysfile.c ocfs2: kill osb->system_file_mutex lock 2026-05-28 21:24:57 -07:00
sysfile.h treewide: remove editor modelines and cruft 2021-05-07 00:26:34 -07:00
uptodate.c treewide: remove editor modelines and cruft 2021-05-07 00:26:34 -07:00
uptodate.h treewide: remove editor modelines and cruft 2021-05-07 00:26:34 -07:00
xattr.c ocfs2: validate inline xattr header before reflinking inline xattrs 2026-05-28 21:24:48 -07:00
xattr.h ocfs2: move ocfs2_xattr_handlers and ocfs2_xattr_handler_map to .rodata 2023-10-09 16:24:20 +02:00