Re: [PATCH] fs/nilfs2: Fix potential underflow in call to crc32_le

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

I have a few comments.  Please see the inline comments below.

On Fri, 17 Jun 2016 10:06:45 +0200, Torsten Hilbrich wrote:
> The value bytes comes from the filesystem which is about to be
> mounted. We cannot trust that the value is always in the range
> we expect it to be.
> 
> Check its value before using it to calculate the length for the
> crc32_le call. It value must be larger (or equal) sumoff + 4 and
> smaller than the remaining space in the block where the superblock
> is stored (BLOCK_SIZE - sumoff - 4).
> 

> This fixes a problem where the accidential mounting of an encrypted
> volume caused a kernel panic. It had the correct magic value 0x3434
> at offset 0x406 by chance and the following 2 bytes were 0x01, 0x00
> (interpreted as s_bytes value with value 1).

Could you improve the description on the problem a bit ?

The true issue looks a "memory access overrun" on the superblock
buffer that can occur when "s_bytes - sumoff - 4" underflows and
crc32_le() receives an uninteded large byte count.

The reason why a "kernel panic" occurs, is unclear in the comment.

Even if a non-nilfs volume is mistakenly mounted as a nilfs volume, it
usually will return an error.  Kernel panic should never occur just by
an accidental mount.  If it happens except the overrun issue, it is
another bug.

> 
> Signed-off-by: Torsten Hilbrich <torsten.hilbrich@xxxxxxxxxxx>
> Tested-by: Torsten Hilbrich <torsten.hilbrich@xxxxxxxxxxx>
> ---
>  fs/nilfs2/the_nilfs.c | 7 ++++---
>  1 file changed, 4 insertions(+), 3 deletions(-)
> 
> diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c
> index 69bd801..21f6b23 100644
> --- a/fs/nilfs2/the_nilfs.c
> +++ b/fs/nilfs2/the_nilfs.c
> @@ -438,18 +438,19 @@ static int nilfs_valid_sb(struct nilfs_super_block *sbp)
>  	static unsigned char sum[4];
>  	const int sumoff = offsetof(struct nilfs_super_block, s_sum);
>  	size_t bytes;
> +	size_t crc_offset = sumoff + 4;

The name "crc_offset" is confusing.  This just means the offset of the
latter part of the region that the crc function will verify.
In addition, it should be defined with a "const" qualifier.

>  	u32 crc;
>  
>  	if (!sbp || le16_to_cpu(sbp->s_magic) != NILFS_SUPER_MAGIC)
>  		return 0;
>  	bytes = le16_to_cpu(sbp->s_bytes);
> -	if (bytes > BLOCK_SIZE)

> +	if (bytes < crc_offset || bytes > BLOCK_SIZE - crc_offset)

The latter part of this test should be "bytes > BLOCK_SIZE".
Why do you subtract crc_offset here ?

Regards,
Ryusuke Konishi

>  		return 0;
>  	crc = crc32_le(le32_to_cpu(sbp->s_crc_seed), (unsigned char *)sbp,
>  		       sumoff);
>  	crc = crc32_le(crc, sum, 4);
> -	crc = crc32_le(crc, (unsigned char *)sbp + sumoff + 4,
> -		       bytes - sumoff - 4);
> +	crc = crc32_le(crc, (unsigned char *)sbp + crc_offset,
> +		       bytes - crc_offset);
>  	return crc == le32_to_cpu(sbp->s_sum);
>  }
>  
> -- 
> 2.1.4
> --
> To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Filesystem Development]     [Linux BTRFS]     [Linux CIFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux