From efac84e790c6d5aefa4947d9d16bd03fd3c14b9e Mon Sep 17 00:00:00 2001 From: Rob Gill Date: Wed, 13 Feb 2019 15:30:02 +1000 Subject: [PATCH] btrfs return errors on panic, add memory deleter to ReadAt() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Additional return BAD_DATA after error conditions encountered when attempting to decompress BTRFS extents. * MemoryDeleter for extent_data added to ReadAt() preventing double-free after error. Change-Id: Ib9f8e9723d3fb6aaff8e69dbb66cd279e86f226b Reviewed-on: https://review.haiku-os.org/c/1045 Reviewed-by: Stephan Aßmus --- src/add-ons/kernel/file_systems/btrfs/Inode.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/add-ons/kernel/file_systems/btrfs/Inode.cpp b/src/add-ons/kernel/file_systems/btrfs/Inode.cpp index 72676ffd51..e2474c46b7 100644 --- a/src/add-ons/kernel/file_systems/btrfs/Inode.cpp +++ b/src/add-ons/kernel/file_systems/btrfs/Inode.cpp @@ -240,27 +240,31 @@ Inode::ReadAt(off_t pos, uint8* buffer, size_t* _length) "\n", status); return status; } + MemoryDeleter deleter(extent_data); + uint8 compression = extent_data->Compression(); if (FileCache() != NULL && extent_data->Type() == BTRFS_EXTENT_DATA_REGULAR) { TRACE("inode %" B_PRIdINO ": ReadAt cache (pos %" B_PRIdOFF ", length %lu)\n", ID(), pos, length); - free(extent_data); if (compression == BTRFS_EXTENT_COMPRESS_NONE) return file_cache_read(FileCache(), NULL, pos, buffer, _length); else if (compression == BTRFS_EXTENT_COMPRESS_ZLIB) panic("zlib isn't unsupported for regular extent\n"); else panic("unknown extent compression; %d\n", compression); + return B_BAD_DATA; } TRACE("Inode::ReadAt(%" B_PRIdINO ") key.Offset() %" B_PRId64 "\n", ID(), search_key.Offset()); off_t diff = pos - search_key.Offset(); - if (extent_data->Type() != BTRFS_EXTENT_DATA_INLINE) + if (extent_data->Type() != BTRFS_EXTENT_DATA_INLINE) { panic("unknown extent type; %d\n", extent_data->Type()); + return B_BAD_DATA; + } *_length = min_c(extent_data->Size() - diff, *_length); if (compression == BTRFS_EXTENT_COMPRESS_NONE) @@ -313,7 +317,6 @@ Inode::ReadAt(off_t pos, uint8* buffer, size_t* _length) status = inflateInit2(&zStream, 15); if (status != Z_OK) { - free(extent_data); return B_ERROR; } } @@ -335,14 +338,15 @@ Inode::ReadAt(off_t pos, uint8* buffer, size_t* _length) if (status != Z_STREAM_END) { TRACE("Inode::ReadAt() inflating failed: %d!\n", status); - free(extent_data); return B_BAD_DATA; } *_length = zStream.total_out; - } else + } else { panic("unknown extent compression; %d\n", compression); + return B_BAD_DATA; + } free(extent_data); return B_OK;