Skip to content

Commit 115ea07

Browse files
Darrick J. Wongcmaiolino
authored andcommitted
xfs: don't report half-built inodes to fserror
Sam Sun apparently found a syzbot way to fuzz a filesystem such that xfs_iget_cache_miss would free the inode before the fserror code could catch up. Frustratingly he doesn't use the syzbot dashboard so there's no C reproducer and not even a full error report, so I'm guessing that: Inodes that are being constructed or torn down inside XFS are not visible to the VFS. They should never be reported to fserror. Also, any inode that has been freshly allocated in _cache_miss should be marked INEW immediately because, well, it's an incompletely constructed inode that isn't yet visible to the VFS. Reported-by: Sam Sun <samsun1006219@gmail.com> Fixes: 5eb4cb1 ("xfs: convey metadata health events to the health monitor") Signed-off-by: "Darrick J. Wong" <djwong@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com> Signed-off-by: Carlos Maiolino <cem@kernel.org>
1 parent 75690e5 commit 115ea07

2 files changed

Lines changed: 14 additions & 3 deletions

File tree

fs/xfs/xfs_health.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -316,8 +316,12 @@ xfs_rgno_mark_sick(
316316

317317
static inline void xfs_inode_report_fserror(struct xfs_inode *ip)
318318
{
319-
/* Report metadata inodes as general filesystem corruption */
320-
if (xfs_is_internal_inode(ip)) {
319+
/*
320+
* Do not report inodes being constructed or freed, or metadata inodes,
321+
* to fsnotify.
322+
*/
323+
if (xfs_iflags_test(ip, XFS_INEW | XFS_IRECLAIM) ||
324+
xfs_is_internal_inode(ip)) {
321325
fserror_report_metadata(ip->i_mount->m_super, -EFSCORRUPTED,
322326
GFP_NOFS);
323327
return;

fs/xfs/xfs_icache.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,14 @@ xfs_iget_cache_miss(
639639
if (!ip)
640640
return -ENOMEM;
641641

642+
/*
643+
* Set XFS_INEW as early as possible so that the health code won't pass
644+
* the inode to the fserror code if the ondisk inode cannot be loaded.
645+
* We're going to free the xfs_inode immediately if that happens, which
646+
* would lead to UAF problems.
647+
*/
648+
xfs_iflags_set(ip, XFS_INEW);
649+
642650
error = xfs_imap(pag, tp, ip->i_ino, &ip->i_imap, flags);
643651
if (error)
644652
goto out_destroy;
@@ -716,7 +724,6 @@ xfs_iget_cache_miss(
716724
ip->i_udquot = NULL;
717725
ip->i_gdquot = NULL;
718726
ip->i_pdquot = NULL;
719-
xfs_iflags_set(ip, XFS_INEW);
720727

721728
/* insert the new inode */
722729
spin_lock(&pag->pag_ici_lock);

0 commit comments

Comments
 (0)