diff mbox series

[1/1] ext4: limit length to bitmap_maxbytes - blocksize in punch_hole

Message ID 20220509140054.39626-2-paolo.pisati@canonical.com
State New
Headers show
Series ext4: limit length to bitmap_maxbytes | expand

Commit Message

Paolo Pisati May 9, 2022, 2 p.m. UTC
From: Tadeusz Struk <tadeusz.struk@linaro.org>

BugLink: https://bugs.launchpad.net/bugs/196947

Syzbot found an issue [1] in ext4_fallocate().
The C reproducer [2] calls fallocate(), passing size 0xffeffeff000ul,
and offset 0x1000000ul, which, when added together exceed the
bitmap_maxbytes for the inode. This triggers a BUG in
ext4_ind_remove_space(). According to the comments in this function
the 'end' parameter needs to be one block after the last block to be
removed. In the case when the BUG is triggered it points to the last
block. Modify the ext4_punch_hole() function and add constraint that
caps the length to satisfy the one before laster block requirement.

LINK: [1] https://syzkaller.appspot.com/bug?id=b80bd9cf348aac724a4f4dff251800106d721331
LINK: [2] https://syzkaller.appspot.com/text?tag=ReproC&x=14ba0238700000

Fixes: a4bb6b64e39a ("ext4: enable "punch hole" functionality")
Reported-by: syzbot+7a806094edd5d07ba029@syzkaller.appspotmail.com
Signed-off-by: Tadeusz Struk <tadeusz.struk@linaro.org>
Link: https://lore.kernel.org/r/20220331200515.153214-1-tadeusz.struk@linaro.org
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Cc: stable@kernel.org
(cherry picked from commit 2da376228a2427501feb9d15815a45dbdbdd753e)
Reported-by: Colin King <colin.i.king@gmail.com>
Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
---
 fs/ext4/inode.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

Comments

Andrea Righi May 9, 2022, 2:06 p.m. UTC | #1
On Mon, May 09, 2022 at 04:00:54PM +0200, Paolo Pisati wrote:
> From: Tadeusz Struk <tadeusz.struk@linaro.org>
> 
> BugLink: https://bugs.launchpad.net/bugs/196947

Buglink seems to point to the wrong bug.

Even the one in the cover letter seems wrong... it's pointing to the
tracking bug for 5.18.0-1.1. Maybe we should create a separate bug for
this issue.

Apart than that fix looks good.

Acked-by: Andrea Righi <andrea.righi@canonical.com>

> 
> Syzbot found an issue [1] in ext4_fallocate().
> The C reproducer [2] calls fallocate(), passing size 0xffeffeff000ul,
> and offset 0x1000000ul, which, when added together exceed the
> bitmap_maxbytes for the inode. This triggers a BUG in
> ext4_ind_remove_space(). According to the comments in this function
> the 'end' parameter needs to be one block after the last block to be
> removed. In the case when the BUG is triggered it points to the last
> block. Modify the ext4_punch_hole() function and add constraint that
> caps the length to satisfy the one before laster block requirement.
> 
> LINK: [1] https://syzkaller.appspot.com/bug?id=b80bd9cf348aac724a4f4dff251800106d721331
> LINK: [2] https://syzkaller.appspot.com/text?tag=ReproC&x=14ba0238700000
> 
> Fixes: a4bb6b64e39a ("ext4: enable "punch hole" functionality")
> Reported-by: syzbot+7a806094edd5d07ba029@syzkaller.appspotmail.com
> Signed-off-by: Tadeusz Struk <tadeusz.struk@linaro.org>
> Link: https://lore.kernel.org/r/20220331200515.153214-1-tadeusz.struk@linaro.org
> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
> Cc: stable@kernel.org
> (cherry picked from commit 2da376228a2427501feb9d15815a45dbdbdd753e)
> Reported-by: Colin King <colin.i.king@gmail.com>
> Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
> ---
>  fs/ext4/inode.c | 11 ++++++++++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
> index 54d8bdd46b9f..d22b2a522ef1 100644
> --- a/fs/ext4/inode.c
> +++ b/fs/ext4/inode.c
> @@ -4314,7 +4314,8 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
>  	struct super_block *sb = inode->i_sb;
>  	ext4_lblk_t first_block, stop_block;
>  	struct address_space *mapping = inode->i_mapping;
> -	loff_t first_block_offset, last_block_offset;
> +	loff_t first_block_offset, last_block_offset, max_length;
> +	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
>  	handle_t *handle;
>  	unsigned int credits;
>  	int ret = 0;
> @@ -4360,6 +4361,14 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
>  		   offset;
>  	}
>  
> +	/*
> +	 * For punch hole the length + offset needs to be within one block
> +	 * before last range. Adjust the length if it goes beyond that limit.
> +	 */
> +	max_length = sbi->s_bitmap_maxbytes - inode->i_sb->s_blocksize;
> +	if (offset + length > max_length)
> +		length = max_length - offset;
> +
>  	if (offset & (sb->s_blocksize - 1) ||
>  	    (offset + length) & (sb->s_blocksize - 1)) {
>  		/*
> -- 
> 2.25.1
> 
> 
> -- 
> kernel-team mailing list
> kernel-team@lists.ubuntu.com
> https://lists.ubuntu.com/mailman/listinfo/kernel-team
Paolo Pisati May 9, 2022, 2:09 p.m. UTC | #2
On Mon, May 9, 2022 at 4:06 PM Andrea Righi <andrea.righi@canonical.com>
wrote:

> On Mon, May 09, 2022 at 04:00:54PM +0200, Paolo Pisati wrote:
> > From: Tadeusz Struk <tadeusz.struk@linaro.org>
> >
> > BugLink: https://bugs.launchpad.net/bugs/196947
>
> Buglink seems to point to the wrong bug.
>
>
Correct buglink:

BugLink: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1972281
Stefan Bader May 9, 2022, 2:37 p.m. UTC | #3
On 09.05.22 16:00, Paolo Pisati wrote:
> From: Tadeusz Struk <tadeusz.struk@linaro.org>
> 
> BugLink: https://bugs.launchpad.net/bugs/196947
> 
> Syzbot found an issue [1] in ext4_fallocate().
> The C reproducer [2] calls fallocate(), passing size 0xffeffeff000ul,
> and offset 0x1000000ul, which, when added together exceed the
> bitmap_maxbytes for the inode. This triggers a BUG in
> ext4_ind_remove_space(). According to the comments in this function
> the 'end' parameter needs to be one block after the last block to be
> removed. In the case when the BUG is triggered it points to the last
> block. Modify the ext4_punch_hole() function and add constraint that
> caps the length to satisfy the one before laster block requirement.
> 
> LINK: [1] https://syzkaller.appspot.com/bug?id=b80bd9cf348aac724a4f4dff251800106d721331
> LINK: [2] https://syzkaller.appspot.com/text?tag=ReproC&x=14ba0238700000
> 
> Fixes: a4bb6b64e39a ("ext4: enable "punch hole" functionality")
> Reported-by: syzbot+7a806094edd5d07ba029@syzkaller.appspotmail.com
> Signed-off-by: Tadeusz Struk <tadeusz.struk@linaro.org>
> Link: https://lore.kernel.org/r/20220331200515.153214-1-tadeusz.struk@linaro.org
> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
> Cc: stable@kernel.org
> (cherry picked from commit 2da376228a2427501feb9d15815a45dbdbdd753e)
> Reported-by: Colin King <colin.i.king@gmail.com>
> Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
Acked-by: Stefan Bader <stefan.bader@canonical.com>
> ---
>   fs/ext4/inode.c | 11 ++++++++++-
>   1 file changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
> index 54d8bdd46b9f..d22b2a522ef1 100644
> --- a/fs/ext4/inode.c
> +++ b/fs/ext4/inode.c
> @@ -4314,7 +4314,8 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
>   	struct super_block *sb = inode->i_sb;
>   	ext4_lblk_t first_block, stop_block;
>   	struct address_space *mapping = inode->i_mapping;
> -	loff_t first_block_offset, last_block_offset;
> +	loff_t first_block_offset, last_block_offset, max_length;
> +	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
>   	handle_t *handle;
>   	unsigned int credits;
>   	int ret = 0;
> @@ -4360,6 +4361,14 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
>   		   offset;
>   	}
>   
> +	/*
> +	 * For punch hole the length + offset needs to be within one block
> +	 * before last range. Adjust the length if it goes beyond that limit.
> +	 */
> +	max_length = sbi->s_bitmap_maxbytes - inode->i_sb->s_blocksize;
> +	if (offset + length > max_length)
> +		length = max_length - offset;
> +
>   	if (offset & (sb->s_blocksize - 1) ||
>   	    (offset + length) & (sb->s_blocksize - 1)) {
>   		/*
Stefan Bader May 9, 2022, 4:04 p.m. UTC | #4
On 09.05.22 16:00, Paolo Pisati wrote:
> From: Tadeusz Struk <tadeusz.struk@linaro.org>
> 
> BugLink: https://bugs.launchpad.net/bugs/196947
> 
> Syzbot found an issue [1] in ext4_fallocate().
> The C reproducer [2] calls fallocate(), passing size 0xffeffeff000ul,
> and offset 0x1000000ul, which, when added together exceed the
> bitmap_maxbytes for the inode. This triggers a BUG in
> ext4_ind_remove_space(). According to the comments in this function
> the 'end' parameter needs to be one block after the last block to be
> removed. In the case when the BUG is triggered it points to the last
> block. Modify the ext4_punch_hole() function and add constraint that
> caps the length to satisfy the one before laster block requirement.
> 
> LINK: [1] https://syzkaller.appspot.com/bug?id=b80bd9cf348aac724a4f4dff251800106d721331
> LINK: [2] https://syzkaller.appspot.com/text?tag=ReproC&x=14ba0238700000
> 
> Fixes: a4bb6b64e39a ("ext4: enable "punch hole" functionality")
> Reported-by: syzbot+7a806094edd5d07ba029@syzkaller.appspotmail.com
> Signed-off-by: Tadeusz Struk <tadeusz.struk@linaro.org>
> Link: https://lore.kernel.org/r/20220331200515.153214-1-tadeusz.struk@linaro.org
> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
> Cc: stable@kernel.org
> (cherry picked from commit 2da376228a2427501feb9d15815a45dbdbdd753e)
> Reported-by: Colin King <colin.i.king@gmail.com>
> Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
> ---

Applied to jammy,focal:linux/master-next (with fuzz). Thanks.

-Stefan

>   fs/ext4/inode.c | 11 ++++++++++-
>   1 file changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
> index 54d8bdd46b9f..d22b2a522ef1 100644
> --- a/fs/ext4/inode.c
> +++ b/fs/ext4/inode.c
> @@ -4314,7 +4314,8 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
>   	struct super_block *sb = inode->i_sb;
>   	ext4_lblk_t first_block, stop_block;
>   	struct address_space *mapping = inode->i_mapping;
> -	loff_t first_block_offset, last_block_offset;
> +	loff_t first_block_offset, last_block_offset, max_length;
> +	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
>   	handle_t *handle;
>   	unsigned int credits;
>   	int ret = 0;
> @@ -4360,6 +4361,14 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
>   		   offset;
>   	}
>   
> +	/*
> +	 * For punch hole the length + offset needs to be within one block
> +	 * before last range. Adjust the length if it goes beyond that limit.
> +	 */
> +	max_length = sbi->s_bitmap_maxbytes - inode->i_sb->s_blocksize;
> +	if (offset + length > max_length)
> +		length = max_length - offset;
> +
>   	if (offset & (sb->s_blocksize - 1) ||
>   	    (offset + length) & (sb->s_blocksize - 1)) {
>   		/*
Kleber Souza May 9, 2022, 4:29 p.m. UTC | #5
On 09.05.22 16:00, Paolo Pisati wrote:
> From: Tadeusz Struk <tadeusz.struk@linaro.org>
> 
> BugLink: https://bugs.launchpad.net/bugs/196947
> 
> Syzbot found an issue [1] in ext4_fallocate().
> The C reproducer [2] calls fallocate(), passing size 0xffeffeff000ul,
> and offset 0x1000000ul, which, when added together exceed the
> bitmap_maxbytes for the inode. This triggers a BUG in
> ext4_ind_remove_space(). According to the comments in this function
> the 'end' parameter needs to be one block after the last block to be
> removed. In the case when the BUG is triggered it points to the last
> block. Modify the ext4_punch_hole() function and add constraint that
> caps the length to satisfy the one before laster block requirement.
> 
> LINK: [1] https://syzkaller.appspot.com/bug?id=b80bd9cf348aac724a4f4dff251800106d721331
> LINK: [2] https://syzkaller.appspot.com/text?tag=ReproC&x=14ba0238700000
> 
> Fixes: a4bb6b64e39a ("ext4: enable "punch hole" functionality")
> Reported-by: syzbot+7a806094edd5d07ba029@syzkaller.appspotmail.com
> Signed-off-by: Tadeusz Struk <tadeusz.struk@linaro.org>
> Link: https://lore.kernel.org/r/20220331200515.153214-1-tadeusz.struk@linaro.org
> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
> Cc: stable@kernel.org
> (cherry picked from commit 2da376228a2427501feb9d15815a45dbdbdd753e)
> Reported-by: Colin King <colin.i.king@gmail.com>
> Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>

Applied to impish:linux with some fuzz.

Thanks,
Kleber

> ---
>   fs/ext4/inode.c | 11 ++++++++++-
>   1 file changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
> index 54d8bdd46b9f..d22b2a522ef1 100644
> --- a/fs/ext4/inode.c
> +++ b/fs/ext4/inode.c
> @@ -4314,7 +4314,8 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
>   	struct super_block *sb = inode->i_sb;
>   	ext4_lblk_t first_block, stop_block;
>   	struct address_space *mapping = inode->i_mapping;
> -	loff_t first_block_offset, last_block_offset;
> +	loff_t first_block_offset, last_block_offset, max_length;
> +	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
>   	handle_t *handle;
>   	unsigned int credits;
>   	int ret = 0;
> @@ -4360,6 +4361,14 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
>   		   offset;
>   	}
>   
> +	/*
> +	 * For punch hole the length + offset needs to be within one block
> +	 * before last range. Adjust the length if it goes beyond that limit.
> +	 */
> +	max_length = sbi->s_bitmap_maxbytes - inode->i_sb->s_blocksize;
> +	if (offset + length > max_length)
> +		length = max_length - offset;
> +
>   	if (offset & (sb->s_blocksize - 1) ||
>   	    (offset + length) & (sb->s_blocksize - 1)) {
>   		/*
Kleber Souza May 9, 2022, 4:30 p.m. UTC | #6
The subject should obviously have been "Impish" instead of "Jammy".

On 09.05.22 18:29, Kleber Souza wrote:
> 
> 
> On 09.05.22 16:00, Paolo Pisati wrote:
>> From: Tadeusz Struk <tadeusz.struk@linaro.org>
>>
>> BugLink: https://bugs.launchpad.net/bugs/196947
>>
>> Syzbot found an issue [1] in ext4_fallocate().
>> The C reproducer [2] calls fallocate(), passing size 0xffeffeff000ul,
>> and offset 0x1000000ul, which, when added together exceed the
>> bitmap_maxbytes for the inode. This triggers a BUG in
>> ext4_ind_remove_space(). According to the comments in this function
>> the 'end' parameter needs to be one block after the last block to be
>> removed. In the case when the BUG is triggered it points to the last
>> block. Modify the ext4_punch_hole() function and add constraint that
>> caps the length to satisfy the one before laster block requirement.
>>
>> LINK: [1] https://syzkaller.appspot.com/bug?id=b80bd9cf348aac724a4f4dff251800106d721331
>> LINK: [2] https://syzkaller.appspot.com/text?tag=ReproC&x=14ba0238700000
>>
>> Fixes: a4bb6b64e39a ("ext4: enable "punch hole" functionality")
>> Reported-by: syzbot+7a806094edd5d07ba029@syzkaller.appspotmail.com
>> Signed-off-by: Tadeusz Struk <tadeusz.struk@linaro.org>
>> Link: https://lore.kernel.org/r/20220331200515.153214-1-tadeusz.struk@linaro.org
>> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
>> Cc: stable@kernel.org
>> (cherry picked from commit 2da376228a2427501feb9d15815a45dbdbdd753e)
>> Reported-by: Colin King <colin.i.king@gmail.com>
>> Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
> 
> Applied to impish:linux with some fuzz.
> 
> Thanks,
> Kleber
> 
>> ---
>>    fs/ext4/inode.c | 11 ++++++++++-
>>    1 file changed, 10 insertions(+), 1 deletion(-)
>>
>> diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
>> index 54d8bdd46b9f..d22b2a522ef1 100644
>> --- a/fs/ext4/inode.c
>> +++ b/fs/ext4/inode.c
>> @@ -4314,7 +4314,8 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
>>    	struct super_block *sb = inode->i_sb;
>>    	ext4_lblk_t first_block, stop_block;
>>    	struct address_space *mapping = inode->i_mapping;
>> -	loff_t first_block_offset, last_block_offset;
>> +	loff_t first_block_offset, last_block_offset, max_length;
>> +	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
>>    	handle_t *handle;
>>    	unsigned int credits;
>>    	int ret = 0;
>> @@ -4360,6 +4361,14 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
>>    		   offset;
>>    	}
>>    
>> +	/*
>> +	 * For punch hole the length + offset needs to be within one block
>> +	 * before last range. Adjust the length if it goes beyond that limit.
>> +	 */
>> +	max_length = sbi->s_bitmap_maxbytes - inode->i_sb->s_blocksize;
>> +	if (offset + length > max_length)
>> +		length = max_length - offset;
>> +
>>    	if (offset & (sb->s_blocksize - 1) ||
>>    	    (offset + length) & (sb->s_blocksize - 1)) {
>>    		/*
Colin Ian King May 9, 2022, 4:33 p.m. UTC | #7
Thanks for handling this so promptly!

On 09/05/2022 17:29, Kleber Souza wrote:
> 
> 
> On 09.05.22 16:00, Paolo Pisati wrote:
>> From: Tadeusz Struk <tadeusz.struk@linaro.org>
>>
>> BugLink: https://bugs.launchpad.net/bugs/196947
>>
>> Syzbot found an issue [1] in ext4_fallocate().
>> The C reproducer [2] calls fallocate(), passing size 0xffeffeff000ul,
>> and offset 0x1000000ul, which, when added together exceed the
>> bitmap_maxbytes for the inode. This triggers a BUG in
>> ext4_ind_remove_space(). According to the comments in this function
>> the 'end' parameter needs to be one block after the last block to be
>> removed. In the case when the BUG is triggered it points to the last
>> block. Modify the ext4_punch_hole() function and add constraint that
>> caps the length to satisfy the one before laster block requirement.
>>
>> LINK: [1] 
>> https://syzkaller.appspot.com/bug?id=b80bd9cf348aac724a4f4dff251800106d721331 
>>
>> LINK: [2] https://syzkaller.appspot.com/text?tag=ReproC&x=14ba0238700000
>>
>> Fixes: a4bb6b64e39a ("ext4: enable "punch hole" functionality")
>> Reported-by: syzbot+7a806094edd5d07ba029@syzkaller.appspotmail.com
>> Signed-off-by: Tadeusz Struk <tadeusz.struk@linaro.org>
>> Link: 
>> https://lore.kernel.org/r/20220331200515.153214-1-tadeusz.struk@linaro.org 
>>
>> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
>> Cc: stable@kernel.org
>> (cherry picked from commit 2da376228a2427501feb9d15815a45dbdbdd753e)
>> Reported-by: Colin King <colin.i.king@gmail.com>
>> Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
> 
> Applied to impish:linux with some fuzz.
> 
> Thanks,
> Kleber
> 
>> ---
>>   fs/ext4/inode.c | 11 ++++++++++-
>>   1 file changed, 10 insertions(+), 1 deletion(-)
>>
>> diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
>> index 54d8bdd46b9f..d22b2a522ef1 100644
>> --- a/fs/ext4/inode.c
>> +++ b/fs/ext4/inode.c
>> @@ -4314,7 +4314,8 @@ int ext4_punch_hole(struct inode *inode, loff_t 
>> offset, loff_t length)
>>       struct super_block *sb = inode->i_sb;
>>       ext4_lblk_t first_block, stop_block;
>>       struct address_space *mapping = inode->i_mapping;
>> -    loff_t first_block_offset, last_block_offset;
>> +    loff_t first_block_offset, last_block_offset, max_length;
>> +    struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
>>       handle_t *handle;
>>       unsigned int credits;
>>       int ret = 0;
>> @@ -4360,6 +4361,14 @@ int ext4_punch_hole(struct inode *inode, loff_t 
>> offset, loff_t length)
>>              offset;
>>       }
>> +    /*
>> +     * For punch hole the length + offset needs to be within one block
>> +     * before last range. Adjust the length if it goes beyond that 
>> limit.
>> +     */
>> +    max_length = sbi->s_bitmap_maxbytes - inode->i_sb->s_blocksize;
>> +    if (offset + length > max_length)
>> +        length = max_length - offset;
>> +
>>       if (offset & (sb->s_blocksize - 1) ||
>>           (offset + length) & (sb->s_blocksize - 1)) {
>>           /*
Luke Nowakowski-Krijger May 9, 2022, 6:36 p.m. UTC | #8
Applied to bionic/linux master-next

Thanks!

- Luke

On Mon, May 9, 2022 at 7:01 AM Paolo Pisati <paolo.pisati@canonical.com>
wrote:

> From: Tadeusz Struk <tadeusz.struk@linaro.org>
>
> BugLink: https://bugs.launchpad.net/bugs/196947
>
> Syzbot found an issue [1] in ext4_fallocate().
> The C reproducer [2] calls fallocate(), passing size 0xffeffeff000ul,
> and offset 0x1000000ul, which, when added together exceed the
> bitmap_maxbytes for the inode. This triggers a BUG in
> ext4_ind_remove_space(). According to the comments in this function
> the 'end' parameter needs to be one block after the last block to be
> removed. In the case when the BUG is triggered it points to the last
> block. Modify the ext4_punch_hole() function and add constraint that
> caps the length to satisfy the one before laster block requirement.
>
> LINK: [1]
> https://syzkaller.appspot.com/bug?id=b80bd9cf348aac724a4f4dff251800106d721331
> LINK: [2] https://syzkaller.appspot.com/text?tag=ReproC&x=14ba0238700000
>
> Fixes: a4bb6b64e39a ("ext4: enable "punch hole" functionality")
> Reported-by: syzbot+7a806094edd5d07ba029@syzkaller.appspotmail.com
> Signed-off-by: Tadeusz Struk <tadeusz.struk@linaro.org>
> Link:
> https://lore.kernel.org/r/20220331200515.153214-1-tadeusz.struk@linaro.org
> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
> Cc: stable@kernel.org
> (cherry picked from commit 2da376228a2427501feb9d15815a45dbdbdd753e)
> Reported-by: Colin King <colin.i.king@gmail.com>
> Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
> ---
>  fs/ext4/inode.c | 11 ++++++++++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
>
> diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
> index 54d8bdd46b9f..d22b2a522ef1 100644
> --- a/fs/ext4/inode.c
> +++ b/fs/ext4/inode.c
> @@ -4314,7 +4314,8 @@ int ext4_punch_hole(struct inode *inode, loff_t
> offset, loff_t length)
>         struct super_block *sb = inode->i_sb;
>         ext4_lblk_t first_block, stop_block;
>         struct address_space *mapping = inode->i_mapping;
> -       loff_t first_block_offset, last_block_offset;
> +       loff_t first_block_offset, last_block_offset, max_length;
> +       struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
>         handle_t *handle;
>         unsigned int credits;
>         int ret = 0;
> @@ -4360,6 +4361,14 @@ int ext4_punch_hole(struct inode *inode, loff_t
> offset, loff_t length)
>                    offset;
>         }
>
> +       /*
> +        * For punch hole the length + offset needs to be within one block
> +        * before last range. Adjust the length if it goes beyond that
> limit.
> +        */
> +       max_length = sbi->s_bitmap_maxbytes - inode->i_sb->s_blocksize;
> +       if (offset + length > max_length)
> +               length = max_length - offset;
> +
>         if (offset & (sb->s_blocksize - 1) ||
>             (offset + length) & (sb->s_blocksize - 1)) {
>                 /*
> --
> 2.25.1
>
>
> --
> kernel-team mailing list
> kernel-team@lists.ubuntu.com
> https://lists.ubuntu.com/mailman/listinfo/kernel-team
>
Thadeu Lima de Souza Cascardo May 18, 2022, 12:13 p.m. UTC | #9
Applied to xenial and trusty master-next branches.

Cascardo.
diff mbox series

Patch

diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 54d8bdd46b9f..d22b2a522ef1 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -4314,7 +4314,8 @@  int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
 	struct super_block *sb = inode->i_sb;
 	ext4_lblk_t first_block, stop_block;
 	struct address_space *mapping = inode->i_mapping;
-	loff_t first_block_offset, last_block_offset;
+	loff_t first_block_offset, last_block_offset, max_length;
+	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
 	handle_t *handle;
 	unsigned int credits;
 	int ret = 0;
@@ -4360,6 +4361,14 @@  int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
 		   offset;
 	}
 
+	/*
+	 * For punch hole the length + offset needs to be within one block
+	 * before last range. Adjust the length if it goes beyond that limit.
+	 */
+	max_length = sbi->s_bitmap_maxbytes - inode->i_sb->s_blocksize;
+	if (offset + length > max_length)
+		length = max_length - offset;
+
 	if (offset & (sb->s_blocksize - 1) ||
 	    (offset + length) & (sb->s_blocksize - 1)) {
 		/*