lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <Yjn7V3whEZ3UmJlF@iweiny-desk3>
Date:   Tue, 22 Mar 2022 09:37:43 -0700
From:   Ira Weiny <ira.weiny@...el.com>
To:     Tadeusz Struk <tadeusz.struk@...aro.org>
Cc:     tytso@....edu, Andreas Dilger <adilger.kernel@...ger.ca>,
        Ritesh Harjani <riteshh@...ux.ibm.com>,
        linux-ext4@...r.kernel.org, stable@...r.kernel.org,
        linux-kernel@...r.kernel.org,
        syzbot+7a806094edd5d07ba029@...kaller.appspotmail.com
Subject: Re: [PATCH v2] ext4: check if offset+length is valid in fallocate

On Tue, Mar 15, 2022 at 02:54:39PM -0700, Tadeusz Struk wrote:
> 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 disk size,
> and trigger a BUG in ext4_ind_remove_space() [3].
> According to the comment doc in ext4_ind_remove_space() the 'end' block
> parameter needs to be one block after the last block to remove.
> In the case when the BUG is triggered it points to the last block on
> a 4GB virtual disk image. This is calculated in
> ext4_ind_remove_space() in [4].
> This patch adds a check that ensure the length + offest to be
> within the valid range and returns -ENOSPC error code in case
> it is invalid.

Why is the check in vfs_fallocate() not working for this?

https://elixir.bootlin.com/linux/v5.17-rc8/source/fs/open.c#L300

Also why do other file systems not fail?  Is it because ext4 is special due to
the end block needing to be one block after the last.  That seems to imply the
last block can't be used or there is some off by one issue somewhere?

Ira

> 
> LINK: [1] https://syzkaller.appspot.com/bug?id=b80bd9cf348aac724a4f4dff251800106d721331
> LINK: [2] https://syzkaller.appspot.com/text?tag=ReproC&x=14ba0238700000
> LINK: [3] https://elixir.bootlin.com/linux/v5.17-rc8/source/fs/ext4/indirect.c#L1244
> LINK: [4] https://elixir.bootlin.com/linux/v5.17-rc8/source/fs/ext4/indirect.c#L1234
> 
> Cc: Theodore Ts'o <tytso@....edu>
> Cc: Andreas Dilger <adilger.kernel@...ger.ca>
> Cc: Ritesh Harjani <riteshh@...ux.ibm.com>
> Cc: <linux-ext4@...r.kernel.org>
> Cc: <stable@...r.kernel.org>
> Cc: <linux-kernel@...r.kernel.org>
> 
> Fixes: a4bb6b64e39a ("ext4: enable "punch hole" functionality")
> Reported-by: syzbot+7a806094edd5d07ba029@...kaller.appspotmail.com
> Signed-off-by: Tadeusz Struk <tadeusz.struk@...aro.org>
> --
> v2: Change sbi->s_blocksize to inode->i_sb->s_blocksize in maxlength
>  computation.
> ---
>  fs/ext4/inode.c | 13 ++++++++++++-
>  1 file changed, 12 insertions(+), 1 deletion(-)
> 
> diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
> index 01c9e4f743ba..355384007d11 100644
> --- a/fs/ext4/inode.c
> +++ b/fs/ext4/inode.c
> @@ -3924,7 +3924,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, ret2 = 0;
> @@ -3967,6 +3968,16 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
>  		   offset;
>  	}
>  
> +	/*
> +	 * For punch hole the length + offset needs to be at least within
> +	 * one block before last
> +	 */
> +	max_length = sbi->s_bitmap_maxbytes - inode->i_sb->s_blocksize;
> +	if (offset + length >= max_length) {
> +		ret = -ENOSPC;
> +		goto out_mutex;
> +	}
> +
>  	if (offset & (sb->s_blocksize - 1) ||
>  	    (offset + length) & (sb->s_blocksize - 1)) {
>  		/*
> -- 
> 2.35.1
> 

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ