Message ID | 20220509140054.39626-2-paolo.pisati@canonical.com |
---|---|
State | New |
Headers | show |
Series | ext4: limit length to bitmap_maxbytes | expand |
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
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
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)) { > /*
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)) { > /*
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)) { > /*
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)) { >> /*
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)) { >> /*
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 >
Applied to xenial and trusty master-next branches. Cascardo.
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)) { /*