fs/ocfs2/dir.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
From: Shaurya Rane <ssrane_b23@ee.vjti.ac.in>
A syzbot report triggered a KASAN use-after-free read when creating a
file on a corrupted OCFS2 filesystem image.
The crash occurs in an error-handling path within the
ocfs2_dx_dir_lookup_rec function. When the function fails to find a
matching extent record (`found` is false), it attempts to log details
about the corruption by reading from the `rec` variable.
According to the KASAN report, the memory pointed to by `rec` can be
invalid at this point, leading to a kernel crash.
Fix this by modifying the error message to use only variables that are
known to be safe, such as the inode number and the extent block's
buffer head block number. This preserves the valuable error log for
debugging corrupted filesystems while preventing the memory safety
violation.
Reported-by: syzbot+30b53487d00b4f7f0922@syzkaller.appspotmail.com
Tested-by: syzbot+30b53487d00b4f7f0922@syzkaller.appspotmail.com
Signed-off-by: Shaurya Rane <ssrane_b23@ee.vjti.ac.in>
---
fs/ocfs2/dir.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c
index 8c9c4825f984..8c4dd61efa8d 100644
--- a/fs/ocfs2/dir.c
+++ b/fs/ocfs2/dir.c
@@ -820,8 +820,7 @@ static int ocfs2_dx_dir_lookup_rec(struct inode *inode,
ret = ocfs2_error(inode->i_sb,
"Inode %lu has bad extent record (%u, %u, 0) in btree\n",
inode->i_ino,
- le32_to_cpu(rec->e_cpos),
- ocfs2_rec_clusters(el, rec));
+ eb_bh ? (unsigned long long)eb_bh->b_blocknr : 0);
goto out;
}
--
2.34.1
Hi,
kernel test robot noticed the following build warnings:
[auto build test WARNING on brauner-vfs/vfs.all]
[also build test WARNING on linus/master v6.17 next-20251009]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/ssrane_b23-ee-vjti-ac-in/ocfs2-Fix-use-after-free-in-ocfs2_dx_dir_lookup_rec/20251009-163456
base: https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git vfs.all
patch link: https://lore.kernel.org/r/20251005151403.9012-1-ssranevjti%40gmail.com
patch subject: [PATCH] ocfs2: Fix use-after-free in ocfs2_dx_dir_lookup_rec
config: m68k-allyesconfig (https://download.01.org/0day-ci/archive/20251010/202510100838.uqgonWvJ-lkp@intel.com/config)
compiler: m68k-linux-gcc (GCC) 15.1.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251010/202510100838.uqgonWvJ-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202510100838.uqgonWvJ-lkp@intel.com/
All warnings (new ones prefixed by >>):
In file included from fs/ocfs2/dir.c:45:
fs/ocfs2/dir.c: In function 'ocfs2_dx_dir_lookup_rec':
>> fs/ocfs2/dir.c:821:35: warning: format '%u' expects argument of type 'unsigned int', but argument 5 has type 'long long unsigned int' [-Wformat=]
821 | "Inode %lu has bad extent record (%u, %u, 0) in btree\n",
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
822 | inode->i_ino,
823 | eb_bh ? (unsigned long long)eb_bh->b_blocknr : 0);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| long long unsigned int
fs/ocfs2/super.h:18:48: note: in definition of macro 'ocfs2_error'
18 | __ocfs2_error(sb, __PRETTY_FUNCTION__, fmt, ##__VA_ARGS__)
| ^~~
fs/ocfs2/dir.c:821:70: note: format string is defined here
821 | "Inode %lu has bad extent record (%u, %u, 0) in btree\n",
| ~^
| |
| unsigned int
| %llu
>> fs/ocfs2/dir.c:821:35: warning: format '%u' expects a matching 'unsigned int' argument [-Wformat=]
821 | "Inode %lu has bad extent record (%u, %u, 0) in btree\n",
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
fs/ocfs2/super.h:18:48: note: in definition of macro 'ocfs2_error'
18 | __ocfs2_error(sb, __PRETTY_FUNCTION__, fmt, ##__VA_ARGS__)
| ^~~
fs/ocfs2/dir.c:821:74: note: format string is defined here
821 | "Inode %lu has bad extent record (%u, %u, 0) in btree\n",
| ~^
| |
| unsigned int
vim +821 fs/ocfs2/dir.c
316f4b9f98a353a Mark Fasheh 2007-09-07 768
9b7895efac906d6 Mark Fasheh 2008-11-12 769 static int ocfs2_dx_dir_lookup_rec(struct inode *inode,
9b7895efac906d6 Mark Fasheh 2008-11-12 770 struct ocfs2_extent_list *el,
9b7895efac906d6 Mark Fasheh 2008-11-12 771 u32 major_hash,
9b7895efac906d6 Mark Fasheh 2008-11-12 772 u32 *ret_cpos,
9b7895efac906d6 Mark Fasheh 2008-11-12 773 u64 *ret_phys_blkno,
9b7895efac906d6 Mark Fasheh 2008-11-12 774 unsigned int *ret_clen)
23193e513d1cd69 Mark Fasheh 2007-09-12 775 {
9b7895efac906d6 Mark Fasheh 2008-11-12 776 int ret = 0, i, found;
9b7895efac906d6 Mark Fasheh 2008-11-12 777 struct buffer_head *eb_bh = NULL;
9b7895efac906d6 Mark Fasheh 2008-11-12 778 struct ocfs2_extent_block *eb;
9b7895efac906d6 Mark Fasheh 2008-11-12 779 struct ocfs2_extent_rec *rec = NULL;
23193e513d1cd69 Mark Fasheh 2007-09-12 780
9b7895efac906d6 Mark Fasheh 2008-11-12 781 if (el->l_tree_depth) {
facdb77f54f09a3 Joel Becker 2009-02-12 782 ret = ocfs2_find_leaf(INODE_CACHE(inode), el, major_hash,
facdb77f54f09a3 Joel Becker 2009-02-12 783 &eb_bh);
9b7895efac906d6 Mark Fasheh 2008-11-12 784 if (ret) {
9b7895efac906d6 Mark Fasheh 2008-11-12 785 mlog_errno(ret);
9b7895efac906d6 Mark Fasheh 2008-11-12 786 goto out;
9b7895efac906d6 Mark Fasheh 2008-11-12 787 }
23193e513d1cd69 Mark Fasheh 2007-09-12 788
9b7895efac906d6 Mark Fasheh 2008-11-12 789 eb = (struct ocfs2_extent_block *) eb_bh->b_data;
9b7895efac906d6 Mark Fasheh 2008-11-12 790 el = &eb->h_list;
4a12ca3a00a244e Mark Fasheh 2008-11-12 791
9b7895efac906d6 Mark Fasheh 2008-11-12 792 if (el->l_tree_depth) {
17a5b9ab32fe046 Goldwyn Rodrigues 2015-09-04 793 ret = ocfs2_error(inode->i_sb,
7ecef14ab1db961 Joe Perches 2015-09-04 794 "Inode %lu has non zero tree depth in btree tree block %llu\n",
7ecef14ab1db961 Joe Perches 2015-09-04 795 inode->i_ino,
9b7895efac906d6 Mark Fasheh 2008-11-12 796 (unsigned long long)eb_bh->b_blocknr);
9b7895efac906d6 Mark Fasheh 2008-11-12 797 goto out;
9b7895efac906d6 Mark Fasheh 2008-11-12 798 }
23193e513d1cd69 Mark Fasheh 2007-09-12 799 }
23193e513d1cd69 Mark Fasheh 2007-09-12 800
44acc46d182ff36 Ivan Pravdin 2025-07-07 801 if (le16_to_cpu(el->l_next_free_rec) == 0) {
44acc46d182ff36 Ivan Pravdin 2025-07-07 802 ret = ocfs2_error(inode->i_sb,
44acc46d182ff36 Ivan Pravdin 2025-07-07 803 "Inode %lu has empty extent list at depth %u\n",
44acc46d182ff36 Ivan Pravdin 2025-07-07 804 inode->i_ino,
44acc46d182ff36 Ivan Pravdin 2025-07-07 805 le16_to_cpu(el->l_tree_depth));
44acc46d182ff36 Ivan Pravdin 2025-07-07 806 goto out;
44acc46d182ff36 Ivan Pravdin 2025-07-07 807 }
44acc46d182ff36 Ivan Pravdin 2025-07-07 808
9b7895efac906d6 Mark Fasheh 2008-11-12 809 found = 0;
9b7895efac906d6 Mark Fasheh 2008-11-12 810 for (i = le16_to_cpu(el->l_next_free_rec) - 1; i >= 0; i--) {
9b7895efac906d6 Mark Fasheh 2008-11-12 811 rec = &el->l_recs[i];
9b7895efac906d6 Mark Fasheh 2008-11-12 812
9b7895efac906d6 Mark Fasheh 2008-11-12 813 if (le32_to_cpu(rec->e_cpos) <= major_hash) {
9b7895efac906d6 Mark Fasheh 2008-11-12 814 found = 1;
9b7895efac906d6 Mark Fasheh 2008-11-12 815 break;
9b7895efac906d6 Mark Fasheh 2008-11-12 816 }
9b7895efac906d6 Mark Fasheh 2008-11-12 817 }
9b7895efac906d6 Mark Fasheh 2008-11-12 818
9b7895efac906d6 Mark Fasheh 2008-11-12 819 if (!found) {
7ecef14ab1db961 Joe Perches 2015-09-04 820 ret = ocfs2_error(inode->i_sb,
7ecef14ab1db961 Joe Perches 2015-09-04 @821 "Inode %lu has bad extent record (%u, %u, 0) in btree\n",
7ecef14ab1db961 Joe Perches 2015-09-04 822 inode->i_ino,
82a88475c352f95 Shaurya Rane 2025-10-05 823 eb_bh ? (unsigned long long)eb_bh->b_blocknr : 0);
9b7895efac906d6 Mark Fasheh 2008-11-12 824 goto out;
9b7895efac906d6 Mark Fasheh 2008-11-12 825 }
9b7895efac906d6 Mark Fasheh 2008-11-12 826
9b7895efac906d6 Mark Fasheh 2008-11-12 827 if (ret_phys_blkno)
9b7895efac906d6 Mark Fasheh 2008-11-12 828 *ret_phys_blkno = le64_to_cpu(rec->e_blkno);
9b7895efac906d6 Mark Fasheh 2008-11-12 829 if (ret_cpos)
9b7895efac906d6 Mark Fasheh 2008-11-12 830 *ret_cpos = le32_to_cpu(rec->e_cpos);
9b7895efac906d6 Mark Fasheh 2008-11-12 831 if (ret_clen)
9b7895efac906d6 Mark Fasheh 2008-11-12 832 *ret_clen = le16_to_cpu(rec->e_leaf_clusters);
9b7895efac906d6 Mark Fasheh 2008-11-12 833
9b7895efac906d6 Mark Fasheh 2008-11-12 834 out:
9b7895efac906d6 Mark Fasheh 2008-11-12 835 brelse(eb_bh);
9b7895efac906d6 Mark Fasheh 2008-11-12 836 return ret;
9b7895efac906d6 Mark Fasheh 2008-11-12 837 }
38760e243249f03 Mark Fasheh 2007-09-11 838
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Hi, This seems to be fixed by the following commit: 44acc46d182f ocfs2: avoid NULL pointer dereference in dx_dir_lookup_rec() Thanks, Joseph On 2025/10/5 23:14, ssrane_b23@ee.vjti.ac.in wrote: > From: Shaurya Rane <ssrane_b23@ee.vjti.ac.in> > > A syzbot report triggered a KASAN use-after-free read when creating a > file on a corrupted OCFS2 filesystem image. > > The crash occurs in an error-handling path within the > ocfs2_dx_dir_lookup_rec function. When the function fails to find a > matching extent record (`found` is false), it attempts to log details > about the corruption by reading from the `rec` variable. > > According to the KASAN report, the memory pointed to by `rec` can be > invalid at this point, leading to a kernel crash. > > Fix this by modifying the error message to use only variables that are > known to be safe, such as the inode number and the extent block's > buffer head block number. This preserves the valuable error log for > debugging corrupted filesystems while preventing the memory safety > violation. > > Reported-by: syzbot+30b53487d00b4f7f0922@syzkaller.appspotmail.com > Tested-by: syzbot+30b53487d00b4f7f0922@syzkaller.appspotmail.com > Signed-off-by: Shaurya Rane <ssrane_b23@ee.vjti.ac.in> > --- > fs/ocfs2/dir.c | 3 +-- > 1 file changed, 1 insertion(+), 2 deletions(-) > > diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c > index 8c9c4825f984..8c4dd61efa8d 100644 > --- a/fs/ocfs2/dir.c > +++ b/fs/ocfs2/dir.c > @@ -820,8 +820,7 @@ static int ocfs2_dx_dir_lookup_rec(struct inode *inode, > ret = ocfs2_error(inode->i_sb, > "Inode %lu has bad extent record (%u, %u, 0) in btree\n", > inode->i_ino, > - le32_to_cpu(rec->e_cpos), > - ocfs2_rec_clusters(el, rec)); > + eb_bh ? (unsigned long long)eb_bh->b_blocknr : 0); > goto out; > } >
© 2016 - 2025 Red Hat, Inc.