Skip to content

Commit 959f758

Browse files
Christoph Hellwigtytso
authored andcommitted
ext4: fix fiemap size checks for bitmap files
Add an extra validation of the len parameter, as for ext4 some files might have smaller file size limits than others. This also means the redundant size check in ext4_ioctl_get_es_cache can go away, as all size checking is done in the shared fiemap handler. Signed-off-by: Christoph Hellwig <[email protected]> Reviewed-by: Ritesh Harjani <[email protected]> Reviewed-by: Jan Kara <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Theodore Ts'o <[email protected]>
1 parent 9f44eda commit 959f758

File tree

2 files changed

+33
-31
lines changed

2 files changed

+33
-31
lines changed

fs/ext4/extents.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4832,6 +4832,28 @@ static const struct iomap_ops ext4_iomap_xattr_ops = {
48324832
.iomap_begin = ext4_iomap_xattr_begin,
48334833
};
48344834

4835+
static int ext4_fiemap_check_ranges(struct inode *inode, u64 start, u64 *len)
4836+
{
4837+
u64 maxbytes;
4838+
4839+
if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
4840+
maxbytes = inode->i_sb->s_maxbytes;
4841+
else
4842+
maxbytes = EXT4_SB(inode->i_sb)->s_bitmap_maxbytes;
4843+
4844+
if (*len == 0)
4845+
return -EINVAL;
4846+
if (start > maxbytes)
4847+
return -EFBIG;
4848+
4849+
/*
4850+
* Shrink request scope to what the fs can actually handle.
4851+
*/
4852+
if (*len > maxbytes || (maxbytes - *len) < start)
4853+
*len = maxbytes - start;
4854+
return 0;
4855+
}
4856+
48354857
static int _ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
48364858
__u64 start, __u64 len, bool from_es_cache)
48374859
{
@@ -4852,6 +4874,15 @@ static int _ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
48524874
if (fiemap_check_flags(fieinfo, ext4_fiemap_flags))
48534875
return -EBADR;
48544876

4877+
/*
4878+
* For bitmap files the maximum size limit could be smaller than
4879+
* s_maxbytes, so check len here manually instead of just relying on the
4880+
* generic check.
4881+
*/
4882+
error = ext4_fiemap_check_ranges(inode, start, &len);
4883+
if (error)
4884+
return error;
4885+
48554886
if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) {
48564887
fieinfo->fi_flags &= ~FIEMAP_FLAG_XATTR;
48574888
error = iomap_fiemap(inode, fieinfo, start, len,

fs/ext4/ioctl.c

Lines changed: 2 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -733,29 +733,6 @@ static void ext4_fill_fsxattr(struct inode *inode, struct fsxattr *fa)
733733
fa->fsx_projid = from_kprojid(&init_user_ns, ei->i_projid);
734734
}
735735

736-
/* copied from fs/ioctl.c */
737-
static int fiemap_check_ranges(struct super_block *sb,
738-
u64 start, u64 len, u64 *new_len)
739-
{
740-
u64 maxbytes = (u64) sb->s_maxbytes;
741-
742-
*new_len = len;
743-
744-
if (len == 0)
745-
return -EINVAL;
746-
747-
if (start > maxbytes)
748-
return -EFBIG;
749-
750-
/*
751-
* Shrink request scope to what the fs can actually handle.
752-
*/
753-
if (len > maxbytes || (maxbytes - len) < start)
754-
*new_len = maxbytes - start;
755-
756-
return 0;
757-
}
758-
759736
/* So that the fiemap access checks can't overflow on 32 bit machines. */
760737
#define FIEMAP_MAX_EXTENTS (UINT_MAX / sizeof(struct fiemap_extent))
761738

@@ -765,8 +742,6 @@ static int ext4_ioctl_get_es_cache(struct file *filp, unsigned long arg)
765742
struct fiemap __user *ufiemap = (struct fiemap __user *) arg;
766743
struct fiemap_extent_info fieinfo = { 0, };
767744
struct inode *inode = file_inode(filp);
768-
struct super_block *sb = inode->i_sb;
769-
u64 len;
770745
int error;
771746

772747
if (copy_from_user(&fiemap, ufiemap, sizeof(fiemap)))
@@ -775,11 +750,6 @@ static int ext4_ioctl_get_es_cache(struct file *filp, unsigned long arg)
775750
if (fiemap.fm_extent_count > FIEMAP_MAX_EXTENTS)
776751
return -EINVAL;
777752

778-
error = fiemap_check_ranges(sb, fiemap.fm_start, fiemap.fm_length,
779-
&len);
780-
if (error)
781-
return error;
782-
783753
fieinfo.fi_flags = fiemap.fm_flags;
784754
fieinfo.fi_extents_max = fiemap.fm_extent_count;
785755
fieinfo.fi_extents_start = ufiemap->fm_extents;
@@ -792,7 +762,8 @@ static int ext4_ioctl_get_es_cache(struct file *filp, unsigned long arg)
792762
if (fieinfo.fi_flags & FIEMAP_FLAG_SYNC)
793763
filemap_write_and_wait(inode->i_mapping);
794764

795-
error = ext4_get_es_cache(inode, &fieinfo, fiemap.fm_start, len);
765+
error = ext4_get_es_cache(inode, &fieinfo, fiemap.fm_start,
766+
fiemap.fm_length);
796767
fiemap.fm_flags = fieinfo.fi_flags;
797768
fiemap.fm_mapped_extents = fieinfo.fi_extents_mapped;
798769
if (copy_to_user(ufiemap, &fiemap, sizeof(fiemap)))

0 commit comments

Comments
 (0)