diff options
author | Darrick J. Wong <djwong@kernel.org> | 2021-05-12 12:51:26 -0700 |
---|---|---|
committer | Darrick J. Wong <djwong@kernel.org> | 2021-05-21 09:07:11 -0700 |
commit | c11ab4d2682dff41c5e34c1d422bd4f6faf51aaf (patch) | |
tree | 9e318c8805aa252ed9d63d8ed32d54d72c83b2cc /fs/xfs/libxfs/xfs_inode_buf.c | |
parent | 2aae28759abf9ca09b322f04fabff7a3dccee789 (diff) |
xfs: validate extsz hints against rt extent size when rtinherit is setextsize-fixes-5.13_2021-05-23
The RTINHERIT bit can be set on a directory so that newly created
regular files will have the REALTIME bit set to store their data on the
realtime volume. If an extent size hint (and EXTSZINHERIT) are set on
the directory, the hint will also be copied into the new file.
As pointed out in previous patches, for realtime files we require the
extent size hint be an integer multiple of the realtime extent, but we
don't perform the same validation on a directory with both RTINHERIT and
EXTSZINHERIT set, even though the only use-case of that combination is
to propagate extent size hints into new realtime files. This leads to
inode corruption errors when the bad values are propagated.
Because there may be existing filesystems with such a configuration, we
cannot simply amend the inode verifier to trip on these directories and
call it a day because that will cause previously "working" filesystems
to start throwing errors abruptly. Note that it's valid to have
directories with rtinherit set even if there is no realtime volume, in
which case the problem does not manifest because rtinherit is ignored if
there's no realtime device; and it's possible that someone set the flag,
crashed, repaired the filesystem (which clears the hint on the realtime
file) and continued.
Therefore, mitigate this issue in several ways: First, if we try to
write out an inode with both rtinherit/extszinherit set and an unaligned
extent size hint, we'll simply turn off the hint to correct the error.
Second, if someone tries to misconfigure a file via the fssetxattr
ioctl, we'll fail the ioctl. Third, we reverify both extent size hint
values when we propagate heritable inode attributes from parent to
child, so that we prevent misconfigurations from spreading.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Diffstat (limited to 'fs/xfs/libxfs/xfs_inode_buf.c')
-rw-r--r-- | fs/xfs/libxfs/xfs_inode_buf.c | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c index 045118c7bf78..23c19e632c2d 100644 --- a/fs/xfs/libxfs/xfs_inode_buf.c +++ b/fs/xfs/libxfs/xfs_inode_buf.c @@ -589,6 +589,19 @@ xfs_inode_validate_extsize( inherit_flag = (flags & XFS_DIFLAG_EXTSZINHERIT); extsize_bytes = XFS_FSB_TO_B(mp, extsize); + /* + * This comment describes a historic gap in this verifier function. + * On older kernels, XFS doesnt't check that the extent size hint is + * an integer multiple of the rt extent size on a directory with both + * RTINHERIT and EXTSZINHERIT flags set. This results in corruption + * shutdowns when the misaligned hint propagates into new realtime + * files, since they do check the rextsize alignment of the hint for + * files with the REALTIME flag set. There could be filesystems with + * misconfigured directories in the wild, so we cannot add it to the + * verifier now because that would cause new corruption shutdowns on + * the directories. + */ + if (rt_flag) blocksize_bytes = mp->m_sb.sb_rextsize << mp->m_sb.sb_blocklog; else |