Commit b2d9f2dc authored by Filipe Manana's avatar Filipe Manana Committed by David Sterba

btrfs: deal with unexpected extent type during reflinking

Smatch complains about a possible dereference of a pointer that was not
initialized:

    CC [M]  fs/btrfs/reflink.o
    CHECK   fs/btrfs/reflink.c
  fs/btrfs/reflink.c:533 btrfs_clone() error: potentially dereferencing uninitialized 'trans'.

This is because we are not dealing with the case where the type of a file
extent has an unexpected value (not regular, not prealloc and not inline),
in which case the transaction handle pointer is not initialized.

Such unexpected type should be impossible, except in case of some memory
corruption caused either by bad hardware or some software bug causing
something like a buffer overrun.

So ASSERT that if the extent type is neither regular nor prealloc, then
it must be inline. Bail out with -EUCLEAN and a warning in case it is
not. This silences smatch.
Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 1f4613cd
...@@ -494,7 +494,8 @@ static int btrfs_clone(struct inode *src, struct inode *inode, ...@@ -494,7 +494,8 @@ static int btrfs_clone(struct inode *src, struct inode *inode,
&clone_info, &trans); &clone_info, &trans);
if (ret) if (ret)
goto out; goto out;
} else if (type == BTRFS_FILE_EXTENT_INLINE) { } else {
ASSERT(type == BTRFS_FILE_EXTENT_INLINE);
/* /*
* Inline extents always have to start at file offset 0 * Inline extents always have to start at file offset 0
* and can never be bigger then the sector size. We can * and can never be bigger then the sector size. We can
...@@ -505,7 +506,8 @@ static int btrfs_clone(struct inode *src, struct inode *inode, ...@@ -505,7 +506,8 @@ static int btrfs_clone(struct inode *src, struct inode *inode,
*/ */
ASSERT(key.offset == 0); ASSERT(key.offset == 0);
ASSERT(datal <= fs_info->sectorsize); ASSERT(datal <= fs_info->sectorsize);
if (WARN_ON(key.offset != 0) || if (WARN_ON(type != BTRFS_FILE_EXTENT_INLINE) ||
WARN_ON(key.offset != 0) ||
WARN_ON(datal > fs_info->sectorsize)) { WARN_ON(datal > fs_info->sectorsize)) {
ret = -EUCLEAN; ret = -EUCLEAN;
goto out; goto out;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment