forked from Minki/linux
Changes since last update:
- Enhance inode fork verifiers to prevent loading of corrupted metadata. - Fix a crash when we try to convert extents format inodes to btree format, we run out of space, but forget to revert the in-core state changes. - Fix file size checks when doing INSERT_RANGE that could cause files to end up negative size if there previously was an extent mapped at s_maxbytes. - Fix a bug when doing a remove-then-add ATTR_REPLACE xattr update where we forget to clear ATTR_REPLACE after the remove, which causes the attr to be lost and the fs to shut down due to (what it thinks is) inconsistent in-core state. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABCgAGBQJa2gs1AAoJEPh/dxk0SrTru50P+wZuY2DRfBSCH20Oq3qTbO9M dQGBnOIqRUC+9IDkpRExB4BYVZoK9/v3fnW3zttRMlEmTQfHtMsoEUXpByoETY5b /bTZh+c7fMhj7eNZspfc+8xsHvq0k3hSxrITe4zjL2rSy72KUrsYtDoIu2UvXyZK nJsqCiyFOdFgMi6IBRLOAVBPzs/q8sIBfl/axjyvokLL/6ki/TfvCAtLkdT4FRIt UHzE8ly/Z99honciPQW4axZ9TobAVd6g2d11XJpbhku3ijTL/vHyflRCFgmM/2T3 VyJ3tTH/w3rCAXOEEj3H8TvKAlHiKpB+g9VwhsTZrP0B14/ljkClm/yEFnCOLmb1 /26t+A++fkqy71PoqeQvXGJGEAxC/1TGo7dxq6Gn5SESc1yr8CjXXMiWTMBBWgfF xIsBNA6Ok0F5+OkEhfSUtfIBziPeUIjbmNGTnMV/EiL9stpHwrQS+JLAK5+POHvQ ZoH5RTY69mK5rJtzN6USGyPe4J0f+S7YTf9fjKTcjjpWHLjJYEYJcGvQb3ynZSV+ 5Wu1TqaUkl/Mp3mkZ1KFMq+MXBgOnarOZug80fbhkv3Vyzbelzpebuc5fMJnzofp 0x6BQUC+bwOxB2KJX8TC+9ajen8O+oxrE2RyehVtCZL0O830NvZ4hQg3yxjKUbwv 8Y0Mq6Q2CQEmsBJkIHH2 =lFf0 -----END PGP SIGNATURE----- Merge tag 'xfs-4.17-fixes-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux Pull xfs fixes from Darrick Wong: "Here are a few more bug fixes for xfs for 4.17-rc4. Most of them are fixes for bad behavior. This series has been run through a full xfstests run during LSF and through a quick xfstests run against this morning's master, with no major failures reported. Summary: - Enhance inode fork verifiers to prevent loading of corrupted metadata. - Fix a crash when we try to convert extents format inodes to btree format, we run out of space, but forget to revert the in-core state changes. - Fix file size checks when doing INSERT_RANGE that could cause files to end up negative size if there previously was an extent mapped at s_maxbytes. - Fix a bug when doing a remove-then-add ATTR_REPLACE xattr update where we forget to clear ATTR_REPLACE after the remove, which causes the attr to be lost and the fs to shut down due to (what it thinks is) inconsistent in-core state" * tag 'xfs-4.17-fixes-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: xfs: don't fail when converting shortform attr to long form during ATTR_REPLACE xfs: prevent creating negative-sized file via INSERT_RANGE xfs: set format back to extents if xfs_bmap_extents_to_btree xfs: enhance dinode verifier
This commit is contained in:
commit
f2125992e7
@ -511,7 +511,14 @@ xfs_attr_shortform_addname(xfs_da_args_t *args)
|
||||
if (args->flags & ATTR_CREATE)
|
||||
return retval;
|
||||
retval = xfs_attr_shortform_remove(args);
|
||||
ASSERT(retval == 0);
|
||||
if (retval)
|
||||
return retval;
|
||||
/*
|
||||
* Since we have removed the old attr, clear ATTR_REPLACE so
|
||||
* that the leaf format add routine won't trip over the attr
|
||||
* not being around.
|
||||
*/
|
||||
args->flags &= ~ATTR_REPLACE;
|
||||
}
|
||||
|
||||
if (args->namelen >= XFS_ATTR_SF_ENTSIZE_MAX ||
|
||||
|
@ -725,12 +725,16 @@ xfs_bmap_extents_to_btree(
|
||||
*logflagsp = 0;
|
||||
if ((error = xfs_alloc_vextent(&args))) {
|
||||
xfs_iroot_realloc(ip, -1, whichfork);
|
||||
ASSERT(ifp->if_broot == NULL);
|
||||
XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
|
||||
xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
|
||||
return error;
|
||||
}
|
||||
|
||||
if (WARN_ON_ONCE(args.fsbno == NULLFSBLOCK)) {
|
||||
xfs_iroot_realloc(ip, -1, whichfork);
|
||||
ASSERT(ifp->if_broot == NULL);
|
||||
XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS);
|
||||
xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
@ -466,6 +466,8 @@ xfs_dinode_verify(
|
||||
return __this_address;
|
||||
if (di_size > XFS_DFORK_DSIZE(dip, mp))
|
||||
return __this_address;
|
||||
if (dip->di_nextents)
|
||||
return __this_address;
|
||||
/* fall through */
|
||||
case XFS_DINODE_FMT_EXTENTS:
|
||||
case XFS_DINODE_FMT_BTREE:
|
||||
@ -484,12 +486,31 @@ xfs_dinode_verify(
|
||||
if (XFS_DFORK_Q(dip)) {
|
||||
switch (dip->di_aformat) {
|
||||
case XFS_DINODE_FMT_LOCAL:
|
||||
if (dip->di_anextents)
|
||||
return __this_address;
|
||||
/* fall through */
|
||||
case XFS_DINODE_FMT_EXTENTS:
|
||||
case XFS_DINODE_FMT_BTREE:
|
||||
break;
|
||||
default:
|
||||
return __this_address;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* If there is no fork offset, this may be a freshly-made inode
|
||||
* in a new disk cluster, in which case di_aformat is zeroed.
|
||||
* Otherwise, such an inode must be in EXTENTS format; this goes
|
||||
* for freed inodes as well.
|
||||
*/
|
||||
switch (dip->di_aformat) {
|
||||
case 0:
|
||||
case XFS_DINODE_FMT_EXTENTS:
|
||||
break;
|
||||
default:
|
||||
return __this_address;
|
||||
}
|
||||
if (dip->di_anextents)
|
||||
return __this_address;
|
||||
}
|
||||
|
||||
/* only version 3 or greater inodes are extensively verified here */
|
||||
|
@ -778,22 +778,26 @@ xfs_file_fallocate(
|
||||
if (error)
|
||||
goto out_unlock;
|
||||
} else if (mode & FALLOC_FL_INSERT_RANGE) {
|
||||
unsigned int blksize_mask = i_blocksize(inode) - 1;
|
||||
unsigned int blksize_mask = i_blocksize(inode) - 1;
|
||||
loff_t isize = i_size_read(inode);
|
||||
|
||||
new_size = i_size_read(inode) + len;
|
||||
if (offset & blksize_mask || len & blksize_mask) {
|
||||
error = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
/* check the new inode size does not wrap through zero */
|
||||
if (new_size > inode->i_sb->s_maxbytes) {
|
||||
/*
|
||||
* New inode size must not exceed ->s_maxbytes, accounting for
|
||||
* possible signed overflow.
|
||||
*/
|
||||
if (inode->i_sb->s_maxbytes - isize < len) {
|
||||
error = -EFBIG;
|
||||
goto out_unlock;
|
||||
}
|
||||
new_size = isize + len;
|
||||
|
||||
/* Offset should be less than i_size */
|
||||
if (offset >= i_size_read(inode)) {
|
||||
if (offset >= isize) {
|
||||
error = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user