nilfs2: reject non-regular inodes in dsync recovery

During roll-forward recovery, nilfs_recover_dsync_blocks() obtains the
inode designated by fi_ino of a dsync log without checking its type.
If a corrupted image designates a special inode (e.g. a device node)
there, the inode's embedded bmap was never initialized:
__nilfs_read_inode() calls nilfs_bmap_read() only for regular files,
directories and symlinks.  The subsequent nilfs_get_block() then
dereferences the uninitialized bmap->b_ops and jumps through it,
crashing the kernel or worse.

Regular files, directories, and symlinks are the only inode types
with data blocks to recover; reject anything else before touching
its block mapping.

[ryusuke: conformed AI tag to guidelines]

Fixes: 0f3e1c7f23 ("nilfs2: recovery functions")
Assisted-by: Claude:claude-mythos-5
Signed-off-by: Jake Labelle <southampton.jake.labelle@gmail.com>
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
Signed-off-by: Viacheslav Dubeyko <slava@dubeyko.com>
This commit is contained in:
Jake Labelle 2026-10-08 20:52:47 +09:00 committed by Viacheslav Dubeyko
parent 814f5a53b4
commit ef2ccb1554

View File

@ -545,6 +545,23 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
goto failed_inode;
}
/*
* Regular files, directories, and symlinks are the only
* inode types with data blocks and an initialized bmap;
* a crafted image can reference some other inode type
* here, whose i_bmap_data was never set up by
* __nilfs_read_inode().
*/
if (!likely(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
S_ISLNK(inode->i_mode))) {
nilfs_warn(sb,
"%s: invalid inode type (ino=%lu, mode=0%o)",
__func__, (unsigned long)rb->ino,
inode->i_mode);
err = -EINVAL;
goto failed_inode;
}
pos = rb->blkoff << inode->i_blkbits;
err = block_write_begin(inode->i_mapping, pos, blocksize,
&folio, nilfs_get_block);