ext4/overlayfs: fiemap related fixes
Subsystems (4)
cover ext4/overlayfs: fiemap related fixes
Hello All,
Here are some changes, which as I understand, takes the right approach in fixing the offset/length bounds check problem reported in threads [1]-[2]. These warnings in iomap_apply/ext4 path are reported after ext4_fiemap() was moved to use iomap framework and when overlayfs is mounted on top of ext4. Though the issues were identified after ext4 moved to iomap framework, but these changes tries to fix the problem which are anyways present in current code irrespective of ext4 using iomap framework for fiemap or not.
Patch 1 & 4 commit msg may give more details of the problem.
Tests done
==========
1. Tested xfstest-suite with "-g quick" & "-overlay -g quick" configuration on a 4k blocksize on x86 & Power. There were no new failures reported due to these changes.
2. Tested syzcaller reported problem with this change. [1]
3. Tested below change which was reported by Murphy. [2]
The minimal reproducer is:
-------------------------------------
fallocate -l 256M test.img
mkfs.ext4 -Fq -b 4096 -I 256 test.img
mkdir -p test
mount -o loop test.img test || exit
pushd test
rm -rf l u w m
mkdir -p l u w m
mount -t overlay -o lowerdir=l,upperdir=u,workdir=w overlay m || exit xfs_io -f -c "pwrite 0 4096" -c "fiemap" m/tf
umount m
rm -rf l u w m
popd
umount -d test
rm -rf test test.img
-------------------------------------
Comments/feedback are much welcome!!
References
==========
[1]: https://lkml.org/lkml/2020/4/11/46
[2]: https://patchwork.ozlabs.org/project/linux-ext4/patch/[email protected]/
Ritesh Harjani (5):
ext4: Fix EXT4_MAX_LOGICAL_BLOCK macro
ext4: Rename fiemap_check_ranges() to make it ext4 specific
vfs: EXPORT_SYMBOL for fiemap_check_ranges()
overlayfs: Check for range bounds before calling i_op->fiemap()
ext4: Get rid of ext4_fiemap_check_ranges
fs/ext4/ext4.h | 2 +- fs/ext4/ioctl.c | 23 ----------------------- fs/ioctl.c | 5 +++-- fs/overlayfs/inode.c | 7 ++++++- include/linux/fs.h | 2 ++ 5 files changed, 12 insertions(+), 27 deletions(-)
Signature · 1 line
2.21.0
PATCH 1/5 ext4: Fix EXT4_MAX_LOGICAL_BLOCK macro
ext4 supports max number of logical blocks in a file to be 0xffffffff. (This is since ext4_extent's ee_block is __le32).
This means that EXT4_MAX_LOGICAL_BLOCK should be 0xfffffffe (starting from 0 logical offset). This patch fixes this.
The issue was seen when ext4 moved to iomap_fiemap API and when overlayfs was mounted on top of ext4. Since overlayfs was missing filemap_check_ranges(), so it could pass a arbitrary huge length which lead to overflow of map.m_len logic.
This patch fixes that.
--- fs/ext4/ext4.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/ext4/ext4.h +1 -1
@@ -722,7 +722,7 @@ enum {#define EXT4_MAX_BLOCK_FILE_PHYS 0xFFFFFFFF/* Max logical block we can support */ -#define EXT4_MAX_LOGICAL_BLOCK 0xFFFFFFFF +#define EXT4_MAX_LOGICAL_BLOCK 0xFFFFFFFE/* * Structure of an inode on the disk
Signature · 1 line
2.21.0
PATCH 2/5 ext4: Rename fiemap_check_ranges() to make it ext4 specific
In reply to Ritesh HarjaniThis renames the fiemap_check_ranges() copy of function within ext4/ioctl.c to become ext4_fiemap_check_ranges(). This is required so that we can finally get rid of this duplicate version.
Since overlayfs anyways need to use this in it's ovl_fiemap() function, so later patches make it available for use by others via EXPORT_SYMBOL.
--- fs/ext4/ioctl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/ext4/ioctl.c +2 -2
@@ -734,7 +734,7 @@ static void ext4_fill_fsxattr(struct inode *inode, struct fsxattr *fa) }/* copied from fs/ioctl.c */ -static int fiemap_check_ranges (struct super_block *sb, +static int ext4_fiemap_check_ranges (struct super_block *sb,u64 start,u64 len,u64 *new_len) {u64 maxbytes = (u64 ) sb->s_maxbytes;
@@ -775,7 +775,7 @@ static int ext4_ioctl_get_es_cache(struct file *filp, unsigned long arg)if (fiemap.fm_extent_count >FIEMAP_MAX_EXTENTS )return -EINVAL ; - error =fiemap_check_ranges (sb, fiemap.fm_start, fiemap.fm_length, + error =ext4_fiemap_check_ranges (sb, fiemap.fm_start, fiemap.fm_length, &len);if (error)return error;
Signature · 1 line
2.21.0
PATCH 3/5 vfs: EXPORT_SYMBOL for fiemap_check_ranges()
In reply to Ritesh Harjani1. fiemap_check_ranges() is needed by ovl_fiemap() to check for ranges before calling underlying inode's ->fiemap() call.
2. With this change even ext4 can use generic fiemap_check_ranges() instead of having a duplicate copy of it.
So make this EXPORT_SYMBOL for use by overlayfs.
--- fs/ioctl.c | 5 +++-- include/linux/fs.h | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-)
fs/ioctl.c +3 -2
@@ -166,8 +166,8 @@ int fiemap_check_flags(struct fiemap_extent_info *fieinfo, u32 fs_flags) }EXPORT_SYMBOL (fiemap_check_flags); -static int fiemap_check_ranges (struct super_block *sb, -u64 start,u64 len,u64 *new_len) +int fiemap_check_ranges (struct super_block *sb,u64 start,u64 len, +u64 *new_len) {u64 maxbytes = (u64 ) sb->s_maxbytes;
@@ -187,6 +187,7 @@ static int fiemap_check_ranges(struct super_block *sb,return 0 ; } +EXPORT_SYMBOL (fiemap_check_ranges);static int ioctl_fiemap (struct file *filp,struct fiemap __user *ufiemap) {
include/linux/fs.h +2 -0
@@ -1759,6 +1759,8 @@ int fiemap_fill_next_extent(struct fiemap_extent_info *info, u64 logical, u64 phys, u64 len, u32 flags);int fiemap_check_flags (struct fiemap_extent_info *fieinfo,u32 fs_flags); +int fiemap_check_ranges (struct super_block *sb,u64 start,u64 len, +u64 *new_len);/* * This is the "filldir" function type, used by readdir() to let * the kernel specify what kind of dirent layout it wants to have.
Signature · 1 line
2.21.0
PATCH 4/5 overlayfs: Check for range bounds before calling i_op->fiemap()
In reply to Ritesh HarjaniUnderlying fs may not be able to handle the length in fiemap beyond sb->s_maxbytes. So similar to how VFS ioctl does it, add fiemap_check_ranges() check in ovl_fiemap() as well before calling underlying fs i_op->fiemap() call.
--- fs/overlayfs/inode.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
fs/overlayfs/inode.c +6 -1
@@ -455,16 +455,21 @@ static int ovl_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,int err;struct inode *realinode =ovl_inode_real (inode);const struct cred *old_cred; +u64 length;if (!realinode->i_op->fiemap)return -EOPNOTSUPP ; + err =fiemap_check_ranges (realinode->i_sb, start, len, &length); +if (err) +return err; + old_cred =ovl_override_creds (inode->i_sb);if (fieinfo->fi_flags &FIEMAP_FLAG_SYNC )filemap_write_and_wait (realinode->i_mapping); - err = realinode->i_op->fiemap (realinode, fieinfo, start, len); + err = realinode->i_op->fiemap (realinode, fieinfo, start, length);revert_creds (old_cred);return err;
Signature · 1 line
2.21.0
PATCH 5/5 ext4: Get rid of ext4_fiemap_check_ranges
In reply to Ritesh HarjaniNow that fiemap_check_ranges() is available for other filesystems to use, so get rid of ext4's private version.
--- fs/ext4/ioctl.c | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-)
fs/ext4/ioctl.c +1 -24
@@ -733,29 +733,6 @@ static void ext4_fill_fsxattr(struct inode *inode, struct fsxattr *fa) fa->fsx_projid =from_kprojid (&init_user_ns, ei->i_projid); } -/* copied from fs/ioctl.c */ -static int ext4_fiemap_check_ranges (struct super_block *sb, -u64 start,u64 len,u64 *new_len) -{ -u64 maxbytes = (u64 ) sb->s_maxbytes; - - *new_len = len; - -if (len ==0 ) -return -EINVAL ; - -if (start > maxbytes) -return -EFBIG ; - -/* -* Shrink request scope to what the fs can actually handle. -*/ -if (len > maxbytes || (maxbytes - len) < start) - *new_len = maxbytes - start; - -return 0 ; -} -/* So that the fiemap access checks can't overflow on 32 bit machines. */ #define FIEMAP_MAX_EXTENTS (UINT_MAX / sizeof(struct fiemap_extent))
@@ -775,7 +752,7 @@ static int ext4_ioctl_get_es_cache(struct file *filp, unsigned long arg)if (fiemap.fm_extent_count >FIEMAP_MAX_EXTENTS )return -EINVAL ; - error =ext4_fiemap_check_ranges (sb, fiemap.fm_start, fiemap.fm_length, + error =fiemap_check_ranges (sb, fiemap.fm_start, fiemap.fm_length, &len);if (error)return error;
Signature · 1 line
2.21.0
Re: [PATCH 1/5] ext4: Fix EXT4_MAX_LOGICAL_BLOCK macro
In reply to Ritesh HarjaniQuoted 10 lines · Ritesh Harjani
ext4 supports max number of logical blocks in a file to be
0xffffffff. (This is since ext4_extent'see_blockis__le32).
This means thatEXT4_MAX_LOGICAL_BLOCKshould be0xfffffffe(starting from 0 logical offset). This patch fixes this.The issue was seen when ext4 moved to
iomap_fiemapAPI and when overlayfs was mounted on top of ext4. Since overlayfs was missingfilemap_check_ranges(), so it could pass a arbitrary huge length which lead to overflow of map.m_len logic.
Quoted 5 lines
This patch fixes that.
Fixes d3b6f23f7167 ("ext4: move ext4_fiemap to use iomap framework")Reported-by [email protected]Signed-off-by Ritesh Harjani <[email protected]>
The patch looks good to me. You can add:
Honza
Quoted 20 lines
--- fs/ext4/ext4.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)fs/ext4/ext4.h +1
-1@@ -722,7 +722,7 @@ enum {#define EXT4_MAX_BLOCK_FILE_PHYS 0xFFFFFFFF/* Max logical block we can support */ -#define EXT4_MAX_LOGICAL_BLOCK 0xFFFFFFFF +#define EXT4_MAX_LOGICAL_BLOCK 0xFFFFFFFE/* * Structure of an inode on the disk Signature · 1 line
2.21.0
Signature · 2 lines
Jan Kara <[email protected]> SUSE Labs, CR
Re: [PATCH 2/5] ext4: Rename fiemap_check_ranges() to make it ext4 specific
In reply to Ritesh HarjaniQuoted 9 lines · Ritesh Harjani
This renames the
fiemap_check_ranges()copy of function withinext4/ioctl.cto becomeext4_fiemap_check_ranges(). This is required so that we can finally get rid of this duplicate version.
Since overlayfs anyways need to use this in it'sovl_fiemap()function, so later patches make it available for use by others viaEXPORT_SYMBOL.Signed-off-by Ritesh Harjani <[email protected]>
Looks good. You can add:
Honza
Quoted 29 lines
--- fs/ext4/ioctl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)fs/ext4/ioctl.c +2
-2@@ -734,7 +734,7 @@ static void ext4_fill_fsxattr(struct inode *inode, struct fsxattr *fa) }/* copied from fs/ioctl.c */ -static int fiemap_check_ranges (struct super_block *sb, +static int ext4_fiemap_check_ranges (struct super_block *sb,u64 start,u64 len,u64 *new_len) {u64 maxbytes = (u64 ) sb->s_maxbytes;@@ -775,7 +775,7 @@ static int ext4_ioctl_get_es_cache(struct file *filp, unsigned long arg)if (fiemap.fm_extent_count >FIEMAP_MAX_EXTENTS )return -EINVAL ; - error =fiemap_check_ranges (sb, fiemap.fm_start, fiemap.fm_length, + error =ext4_fiemap_check_ranges (sb, fiemap.fm_start, fiemap.fm_length, &len);if (error)return error;Signature · 1 line
2.21.0
Signature · 2 lines
Jan Kara <[email protected]> SUSE Labs, CR
Re: [PATCH 3/5] vfs: EXPORT_SYMBOL for fiemap_check_ranges()
In reply to Ritesh HarjaniQuoted 8 lines · Ritesh Harjani
1.
fiemap_check_ranges()is needed byovl_fiemap()to check for ranges before calling underlying inode's ->fiemap() call.
2. With this change even ext4 can use genericfiemap_check_ranges()instead of having a duplicate copy of it.So make this
EXPORT_SYMBOLfor use by overlayfs.Signed-off-by Ritesh Harjani <[email protected]>
Looks good to me. You can add:
Honza
Quoted 44 lines
--- fs/ioctl.c | 5 +++-- include/linux/fs.h | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-)fs/ioctl.c +3
-2@@ -166,8 +166,8 @@ int fiemap_check_flags(struct fiemap_extent_info *fieinfo, u32 fs_flags) }EXPORT_SYMBOL (fiemap_check_flags); -static int fiemap_check_ranges (struct super_block *sb, -u64 start,u64 len,u64 *new_len) +int fiemap_check_ranges (struct super_block *sb,u64 start,u64 len, +u64 *new_len) {u64 maxbytes = (u64 ) sb->s_maxbytes;@@ -187,6 +187,7 @@ static int fiemap_check_ranges(struct super_block *sb,return 0 ; } +EXPORT_SYMBOL (fiemap_check_ranges);static int ioctl_fiemap (struct file *filp,struct fiemap __user *ufiemap) {include/linux/fs.h +2
-0@@ -1759,6 +1759,8 @@ int fiemap_fill_next_extent(struct fiemap_extent_info *info, u64 logical, u64 phys, u64 len, u32 flags);int fiemap_check_flags (struct fiemap_extent_info *fieinfo,u32 fs_flags); +int fiemap_check_ranges (struct super_block *sb,u64 start,u64 len, +u64 *new_len);/* * This is the "filldir" function type, used by readdir() to let * the kernel specify what kind of dirent layout it wants to have. Signature · 1 line
2.21.0
Signature · 2 lines
Jan Kara <[email protected]> SUSE Labs, CR
Re: [PATCH 4/5] overlayfs: Check for range bounds before calling i_op->fiemap()
In reply to Ritesh HarjaniQuoted 9 lines · Ritesh Harjani
Underlying fs may not be able to handle the length in fiemap beyond
sb->s_maxbytes. So similar to how VFS ioctl does it, addfiemap_check_ranges()check inovl_fiemap()as well before calling underlying fsi_op->fiemap()call.Signed-off-by Ritesh Harjani <[email protected]>--- fs/overlayfs/inode.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
Yeah, makes sense. You can add:
Honza
Quoted 31 lines
fs/overlayfs/inode.c +6
-1@@ -455,16 +455,21 @@ static int ovl_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,int err;struct inode *realinode =ovl_inode_real (inode);const struct cred *old_cred; +u64 length;if (!realinode->i_op->fiemap)return -EOPNOTSUPP ; + err =fiemap_check_ranges (realinode->i_sb, start, len, &length); +if (err) +return err; + old_cred =ovl_override_creds (inode->i_sb);if (fieinfo->fi_flags &FIEMAP_FLAG_SYNC )filemap_write_and_wait (realinode->i_mapping); - err = realinode->i_op->fiemap (realinode, fieinfo, start, len); + err = realinode->i_op->fiemap (realinode, fieinfo, start, length);revert_creds (old_cred);return err;Signature · 1 line
2.21.0
Signature · 2 lines
Jan Kara <[email protected]> SUSE Labs, CR
Re: [PATCH 5/5] ext4: Get rid of ext4_fiemap_check_ranges
In reply to Ritesh HarjaniQuoted 4 lines · Ritesh Harjani
Now that
fiemap_check_ranges()is available for other filesystems to use, so get rid of ext4's private version.Signed-off-by Ritesh Harjani <[email protected]>
Nice. You can add:
Honza
Quoted 50 lines
--- fs/ext4/ioctl.c | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-)fs/ext4/ioctl.c +1
-24@@ -733,29 +733,6 @@ static void ext4_fill_fsxattr(struct inode *inode, struct fsxattr *fa) fa->fsx_projid =from_kprojid (&init_user_ns, ei->i_projid); } -/* copied from fs/ioctl.c */ -static int ext4_fiemap_check_ranges (struct super_block *sb, -u64 start,u64 len,u64 *new_len) -{ -u64 maxbytes = (u64 ) sb->s_maxbytes; - - *new_len = len; - -if (len ==0 ) -return -EINVAL ; - -if (start > maxbytes) -return -EFBIG ; - -/* -* Shrink request scope to what the fs can actually handle. -*/ -if (len > maxbytes || (maxbytes - len) < start) - *new_len = maxbytes - start; - -return 0 ; -} -/* So that the fiemap access checks can't overflow on 32 bit machines. */ #define FIEMAP_MAX_EXTENTS (UINT_MAX / sizeof(struct fiemap_extent))@@ -775,7 +752,7 @@ static int ext4_ioctl_get_es_cache(struct file *filp, unsigned long arg)if (fiemap.fm_extent_count >FIEMAP_MAX_EXTENTS )return -EINVAL ; - error =ext4_fiemap_check_ranges (sb, fiemap.fm_start, fiemap.fm_length, + error =fiemap_check_ranges (sb, fiemap.fm_start, fiemap.fm_length, &len);if (error)return error;Signature · 1 line
2.21.0
Signature · 2 lines
Jan Kara <[email protected]> SUSE Labs, CR
I think the right fix is to move fiemap_check_ranges into all the ->fiemap instances (we only have a few actual implementation minus the wrappers around iomap/generic). Then add a version if iomap_fiemap that can pass in maxbytes explicitly for ext4, similar to what we've done with various other generic helpers.
The idea of validating input against file systems specific paramaters before we call into the fs is just bound to cause problems.
Hello Christoph,
Thanks for your review comments.
Quoted 1 line · Christoph Hellwig
I think the right fix is to move
fiemap_check_rangesinto all the ->fiemap
I do welcome your suggestion here. But I am not sure of what you are
suggesting should be done as a 1st round of changes for the immediate
reported problem.
So currently these patches take the same approach on overlayfs on how VFS does it. So as a fix to the overlayfs over ext4 reported problems in thread [1] & [2]. I think these patches are doing the right thing.
Also maybe I am biased in some way because as I see these are the right fixes with minimal changes only at places which does have a direct problem.
But I do agree that in the second round (as a right approach for the long term), we could just get rid of fiemap_check_ranges() from ioctl_fiemap() & ovl_fiemap(), and better add those in all filesystem specific implementations of ->fiemap() call.
(e.g. ext4_fiemap(), f2fs_fiemap() etc.).
Quoted 3 lines
instances (we only have a few actual implementation minus the wrappers around iomap/generic).
Ok, got it. So for filesystem specific ->fiemap implementations, we should add fiemap_check_ranges() in there implementations. And for those FS which are calling iomap_fiemap() or generic_block_fiemap(), what you are suggesting it to add fiemap_check_ranges() in iomap_fiemap() & generic_block_fiemap(). Is this understanding correct?
Quoted 3 lines
Then add a version if
iomap_fiemapthat can pass
in maxbytes explicitly for ext4, similar to what we've done with various other generic helpers.
Sorry I am not sure if I followed it correctly. Help me understand pls. Also some e.g about "what we've done with various other generic helpers"
iomap_fiemap(), will already get a FS specific inode from which we can calculate inode->i_sb->s_maxbytes. So why pass maxbytes explicitly?
Quoted 4 lines
The idea of validating input against file systems specific paramaters before we call into the fs is just bound to cause problems.
Sure, but as I was saying. The changes you are suggesting will have changes in all filesystem's individual ->fiemap() implementations. But as a fix for the reported problem of [1] & [2], I think these patches could be taken. Once those are merged, I can work on the changes that you are suggesting.
Does that sound ok to you?
[1]: https://lkml.org/lkml/2020/4/11/46
[2]: https://patchwork.ozlabs.org/project/linux-ext4/patch/[email protected]/
-ritesh
Re: [PATCH 4/5] overlayfs: Check for range bounds before calling i_op->fiemap()
In reply to Ritesh HarjaniQuoted 16 lines · Ritesh Harjani
Underlying fs may not be able to handle the length in fiemap beyond
sb->s_maxbytes. So similar to how VFS ioctl does it, addfiemap_check_ranges()check inovl_fiemap()as well before calling underlying fsi_op->fiemap()call.Signed-off-by Ritesh Harjani <[email protected]>--- fs/overlayfs/inode.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)fs/overlayfs/inode.c +0
-0
fs/overlayfs/inode.c static int ovl_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, · line 458
Quoted 4 lines
fs/overlayfs/inode.c +1
-0@@ -455,16 +455,21 @@ static int ovl_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,int err;struct inode *realinode =ovl_inode_real (inode);const struct cred *old_cred; +u64 length;
To be more clear, I would call that reallen, but apart from that, you may add:
Thanks,
Amir.
Amir Goldstein
maintainerQuoted 15 lines · Ritesh Harjani
Hello Christoph,
Thanks for your review comments.
Quoted 1 line · Christoph Hellwig
I think the right fix is to move
fiemap_check_rangesinto all the ->fiemapI do welcome your suggestion here. But I am not sure of what you are suggesting should be done as a 1st round of changes for the immediate reported problem.
So currently these patches take the same approach on overlayfs on how VFS does it. So as a fix to the overlayfs over ext4 reported problems in thread [1] & [2]. I think these patches are doing the right thing.
Quoted 4 lines
Also maybe I am biased in some way because as I see these are the right fixes with minimal changes only at places which does have a direct problem.
FWIW, I agree with you.
And seems like Jan does as well, since he ACKed all your patches. Current patches would be easier to backport to stable kernels.
Plus, if we are going to cleanup the fiemap interface, need to look into FIEMAP_FLAG_SYNC handling.
Does it makes sense to handle this flag in vfs ioctl code and other flags by filesystem code?
See, iomap_fiemap() takes care of FIEMAP_FLAG_SYNC in addition to ioctl_fiemap(), so I would think that FIEMAP_FLAG_SYNC should probably be removed from ioctl_fiemap() and handled by generic_block_fiemap() and other filesystem specific implementation.
Thanks,
Amir.
Quoted 3 lines · Amir Goldstein
FWIW, I agree with you.
And seems like Jan does as well, since he ACKed all your patches. Current patches would be easier to backport to stable kernels.
Honestly, the proper fix is pretty much trivial. I wrote it up this morning over coffee:
http://git.infradead.org/users/hch/misc.git/shortlog/refs/heads/fiemap-fix
Still needs more testing, though.
Quoted 25 lines · Amir Goldstein
Quoted 15 lines · Ritesh Harjani
Hello Christoph,
Thanks for your review comments.
Quoted 1 line · Christoph Hellwig
I think the right fix is to move
fiemap_check_rangesinto all the ->fiemapI do welcome your suggestion here. But I am not sure of what you are suggesting should be done as a 1st round of changes for the immediate reported problem.
So currently these patches take the same approach on overlayfs on how VFS does it. So as a fix to the overlayfs over ext4 reported problems in thread [1] & [2]. I think these patches are doing the right thing.Quoted 4 lines
Also maybe I am biased in some way because as I see these are the right fixes with minimal changes only at places which does have a direct problem.
FWIW, I agree with you.
And seems like Jan does as well, since he ACKed all your patches. Current patches would be easier to backport to stable kernels.
Quoted 8 lines
Plus, if we are going to cleanup the fiemap interface, need to look into
FIEMAP_FLAG_SYNChandling.
Does it makes sense to handle this flag in vfs ioctl code and other flags by filesystem code?
See,iomap_fiemap()takes care ofFIEMAP_FLAG_SYNCin addition toioctl_fiemap(), so I would think thatFIEMAP_FLAG_SYNCshould probably be removed fromioctl_fiemap()and handled bygeneric_block_fiemap()and other filesystem specific implementation.
Yes, and that too. I too wanted to re-look on the above mentioned part. Thanks for penning it down.
-ritesh
Amir Goldstein
maintainerQuoted 6 lines · Christoph Hellwig
Quoted 3 lines · Amir Goldstein
FWIW, I agree with you.
And seems like Jan does as well, since he ACKed all your patches. Current patches would be easier to backport to stable kernels.
Quoted 6 lines
Honestly, the proper fix is pretty much trivial. I wrote it up this morning over coffee:
http://git.infradead.org/users/hch/misc.git/shortlog/refs/heads/fiemap-fix
Still needs more testing, though.
Very slick!
I still think Ritesh's patches are easier for backporting because they are mostly contained within the ext4/overlayfs subsystems and your patch can follow up as interface cleanup.
I would use as generic helper name generic_fiemap_checks() akin to generic_write_checks() and generic_remap_file_range_prep() => generic_remap_checks().
Thanks,
Amir.
Quoted 16 lines · Amir Goldstein
Quoted 6 lines · Christoph Hellwig
Quoted 3 lines · Amir Goldstein
FWIW, I agree with you.
And seems like Jan does as well, since he ACKed all your patches. Current patches would be easier to backport to stable kernels.Quoted 6 lines
Honestly, the proper fix is pretty much trivial. I wrote it up this morning over coffee:
http://git.infradead.org/users/hch/misc.git/shortlog/refs/heads/fiemap-fix
Still needs more testing, though.
Very slick!
Quoted 7 lines
I still think Ritesh's patches are easier for backporting because they are mostly contained within the ext4/overlayfs subsystems and your patch can follow up as interface cleanup.
I would use as generic helper name
generic_fiemap_checks()akin togeneric_write_checks()andgeneric_remap_file_range_prep()=>generic_remap_checks().
If it's ok, I will be happy to do this cleanup in the 2nd round.
-ritesh
Quoted 6 lines · Christoph Hellwig
Quoted 3 lines · Amir Goldstein
FWIW, I agree with you.
And seems like Jan does as well, since he ACKed all your patches. Current patches would be easier to backport to stable kernels.
Quoted 6 lines
Honestly, the proper fix is pretty much trivial. I wrote it up this morning over coffee:
http://git.infradead.org/users/hch/misc.git/shortlog/refs/heads/fiemap-fix
Still needs more testing, though.
The "maxbytes" value should be passed in from the caller, since this may be different per inode (for ext4 at least).
Cheers, Andreas
Quoted 3 lines · Amir Goldstein
I would use as generic helper name
generic_fiemap_checks()akin togeneric_write_checks()andgeneric_remap_file_range_prep()=>generic_remap_checks().
None of the other fiemap helpers use the redundant generic_ prefix.
Quoted 10 lines · Andreas Dilger
Quoted 9 lines · Christoph Hellwig
Quoted 3 lines · Amir Goldstein
FWIW, I agree with you.
And seems like Jan does as well, since he ACKed all your patches. Current patches would be easier to backport to stable kernels.Honestly, the proper fix is pretty much trivial. I wrote it up this morning over coffee:
Quoted 6 lines
Quoted 3 lines
http://git.infradead.org/users/hch/misc.git/shortlog/refs/heads/fiemap-fix
Still needs more testing, though.
The "maxbytes" value should be passed in from the caller, since this may be different per inode (for ext4 at least).
We should handle it, but not burden everyone else who has saner limits.
Amir Goldstein
maintainerQuoted 7 lines · Christoph Hellwig
Quoted 3 lines · Amir Goldstein
I would use as generic helper name
generic_fiemap_checks()akin togeneric_write_checks()andgeneric_remap_file_range_prep()=>generic_remap_checks().None of the other fiemap helpers use the redundant
generic_prefix.
Fine. I still don't like the name _validate() so much because it implies yes or no, not length truncating.
What's more, if we decide that FIEMAP_FLAG_SYNC handling should be done inside this generic helper, we would definitely need to rename it again. So how about going for something a bit more abstract like fiemap_prep() or whatever.
What is your take about FIEMAP_FLAG_SYNC handling btw?
Thanks,
Amir.
Quoted 9 lines · Amir Goldstein
Quoted 7 lines · Christoph Hellwig
Quoted 3 lines · Amir Goldstein
I would use as generic helper name
generic_fiemap_checks()akin togeneric_write_checks()andgeneric_remap_file_range_prep()=>generic_remap_checks().None of the other fiemap helpers use the redundant
generic_prefix.
Quoted 7 lines
Fine. I still don't like the name
_validate()so much because it implies yes or no, not length truncating.What's more, if we decide that
FIEMAP_FLAG_SYNChandling should be done inside this generic helper, we would definitely need to rename it again. So how about going for something a bit more abstract likefiemap_prep()or whatever.
Ok, I'll rename it to fiemap_prep.
Quoted 2 lines
What is your take about
FIEMAP_FLAG_SYNChandling btw?
Oh, I hadn't really noticed that mess. Taking it into fiemap_prep might make most sense, so that it nominally is under fs control for e.g. locking purposes.
Quoted 9 lines · Ritesh Harjani
Hello All,
Here are some changes, which as I understand, takes the right approach in fixing the offset/length bounds check problem reported in threads [1]-[2]. These warnings in iomap_apply/ext4 path are reported after
ext4_fiemap()was moved to use iomap framework and when overlayfs is mounted on top of ext4. Though the issues were identified after ext4 moved to iomap framework, but these changes tries to fix the problem which are anyways present in current code irrespective of ext4 using iomap framework for fiemap or not.
Ping?
Quoted 53 lines
Patch 1 & 4 commit msg may give more details of the problem.
Tests done
==========
1. Tested xfstest-suite with "-g quick" & "-overlay -g quick" configuration on a 4k blocksize on x86 & Power. There were no new failures reported due to these changes.
2. Tested syzcaller reported problem with this change. [1]
3. Tested below change which was reported by Murphy. [2]
The minimal reproducer is:
-------------------------------------
fallocate -l 256M test.img
mkfs.ext4 -Fq -b 4096 -I 256 test.img
mkdir -p test
mount -o loop test.img test || exit
pushd test
rm -rf l u w m
mkdir -p l u w m
mount -t overlay -o lowerdir=l,upperdir=u,workdir=w overlay m || exitxfs_io-f -c "pwrite 0 4096" -c "fiemap" m/tf
umount m
rm -rf l u w m
popd
umount -d test
rm -rf test test.img
-------------------------------------Comments/feedback are much welcome!!
References
==========
[1]: https://lkml.org/lkml/2020/4/11/46
[2]: https://patchwork.ozlabs.org/project/linux-ext4/patch/[email protected]/Ritesh Harjani (5):
ext4: FixEXT4_MAX_LOGICAL_BLOCKmacro
ext4: Renamefiemap_check_ranges()to make it ext4 specific
vfs:EXPORT_SYMBOLforfiemap_check_ranges()
overlayfs: Check for range bounds before callingi_op->fiemap()
ext4: Get rid ofext4_fiemap_check_rangesfs/ext4/ext4.h | 2 +- fs/ext4/ioctl.c | 23 ----------------------- fs/ioctl.c | 5 +++-- fs/overlayfs/inode.c | 7 ++++++- include/linux/fs.h | 2 ++ 5 files changed, 12 insertions(+), 27 deletions(-)Signature · 1 line
2.21.0
Signature · 1 line
Murphy
Hello Murphy,
Quoted 11 lines · Murphy Zhou
Quoted 9 lines · Ritesh Harjani
Hello All,
Here are some changes, which as I understand, takes the right approach in fixing the offset/length bounds check problem reported in threads [1]-[2]. These warnings in iomap_apply/ext4 path are reported after
ext4_fiemap()was moved to use iomap framework and when overlayfs is mounted on top of ext4. Though the issues were identified after ext4 moved to iomap framework, but these changes tries to fix the problem which are anyways present in current code irrespective of ext4 using iomap framework for fiemap or not.
Quoted 1 line
Ping?
It's superseded by below mentioned patch series.
Please follow below thread.
https://lore.kernel.org/linux-ext4/[email protected]/T/#t
-ritesh
Hi Ritesh,
Quoted 14 lines · Ritesh Harjani
Hello Murphy,
Quoted 11 lines · Murphy Zhou
Quoted 9 lines · Ritesh Harjani
Hello All,
Here are some changes, which as I understand, takes the right approach in fixing the offset/length bounds check problem reported in threads [1]-[2]. These warnings in iomap_apply/ext4 path are reported after
ext4_fiemap()was moved to use iomap framework and when overlayfs is mounted on top of ext4. Though the issues were identified after ext4 moved to iomap framework, but these changes tries to fix the problem which are anyways present in current code irrespective of ext4 using iomap framework for fiemap or not.
Quoted 5 lines
Quoted 1 line
Ping?
It's superseded by below mentioned patch series.
Please follow below thread.
https://lore.kernel.org/linux-ext4/[email protected]/T/#t
Great. Thanks for the info!
Quoted 2 lines
-ritesh
Signature · 1 line
Murphy