mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-07 22:42:04 +00:00
xfs: allow unlinked symlinks and dirs with zero size
For a very very long time, inode inactivation has set the inode size to zero before unmapping the extents associated with the data fork. Unfortunately, commit3c6f46eacd
changed the inode verifier to prohibit zero-length symlinks and directories. If an inode happens to get logged in this state and the system crashes before freeing the inode, log recovery will also fail on the broken inode. Therefore, allow zero-size symlinks and directories as long as the link count is zero; nobody will be able to open these files by handle so there isn't any risk of data exposure. Fixes:3c6f46eacd
("xfs: sanity check directory inode di_size") Signed-off-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Chandan Babu R <chandanbabu@kernel.org>
This commit is contained in:
parent
288e1f693f
commit
1ec9307fc0
@ -379,10 +379,13 @@ xfs_dinode_verify_fork(
|
||||
/*
|
||||
* A directory small enough to fit in the inode must be stored
|
||||
* in local format. The directory sf <-> extents conversion
|
||||
* code updates the directory size accordingly.
|
||||
* code updates the directory size accordingly. Directories
|
||||
* being truncated have zero size and are not subject to this
|
||||
* check.
|
||||
*/
|
||||
if (S_ISDIR(mode)) {
|
||||
if (be64_to_cpu(dip->di_size) <= fork_size &&
|
||||
if (dip->di_size &&
|
||||
be64_to_cpu(dip->di_size) <= fork_size &&
|
||||
fork_format != XFS_DINODE_FMT_LOCAL)
|
||||
return __this_address;
|
||||
}
|
||||
@ -528,9 +531,19 @@ xfs_dinode_verify(
|
||||
if (mode && xfs_mode_to_ftype(mode) == XFS_DIR3_FT_UNKNOWN)
|
||||
return __this_address;
|
||||
|
||||
/* No zero-length symlinks/dirs. */
|
||||
if ((S_ISLNK(mode) || S_ISDIR(mode)) && di_size == 0)
|
||||
return __this_address;
|
||||
/*
|
||||
* No zero-length symlinks/dirs unless they're unlinked and hence being
|
||||
* inactivated.
|
||||
*/
|
||||
if ((S_ISLNK(mode) || S_ISDIR(mode)) && di_size == 0) {
|
||||
if (dip->di_version > 1) {
|
||||
if (dip->di_nlink)
|
||||
return __this_address;
|
||||
} else {
|
||||
if (dip->di_onlink)
|
||||
return __this_address;
|
||||
}
|
||||
}
|
||||
|
||||
fa = xfs_dinode_verify_nrext64(mp, dip);
|
||||
if (fa)
|
||||
|
Loading…
Reference in New Issue
Block a user