-
-
Notifications
You must be signed in to change notification settings - Fork 308
Description
Affected Projects
hdf5 v1.14.6 (https://github.com/HDFGroup/hdf5)
Problem Type
CWE-122: Heap-based Buffer Overflow
Description
Summary
A heap-buffer-overflow vulnerability was discovered in the H5F__accum_free
function within the HDF5 Library. This issue occurs when processing certain files, leading to an out-of-bounds read and potential application crash.
Details
The vulnerability arises in the H5F__accum_free
function defined in src/H5Faccum.c
at line 885
. The function failed to correctly check the value of overlap_size
(which may be a large value) and buffer boundaries, resulting in buffer overflow and read operations exceeding allocated memory when calling function memmove
.
herr_t
H5F__accum_free(H5F_shared_t *f_sh, H5FD_mem_t H5_ATTR_UNUSED type, haddr_t addr, hsize_t size)
{
H5F_meta_accum_t *accum; /* Alias for file's metadata accumulator */
H5FD_t *file; /* File driver pointer */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
/* check arguments */
assert(f_sh);
/* Set up alias for file's metadata accumulator info */
accum = &f_sh->accum;
/* Translate to file driver pointer */
file = f_sh->lf;
/* Adjust the metadata accumulator to remove the freed block, if it overlaps */
if ((f_sh->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && H5_addr_defined(accum->loc) &&
H5_addr_overlap(addr, size, accum->loc, accum->size)) {
size_t overlap_size; /* Size of overlap with accumulator */
/* Sanity check */
/* (The metadata accumulator should not intersect w/raw data */
assert(H5FD_MEM_DRAW != type);
assert(H5FD_MEM_GHEAP != type); /* (global heap data is being treated as raw data currently) */
/* Check for overlapping the beginning of the accumulator */
if (H5_addr_le(addr, accum->loc)) {
/* Check for completely overlapping the accumulator */
if (H5_addr_ge(addr + size, accum->loc + accum->size)) {
/* Reset the accumulator, but don't free buffer */
accum->loc = HADDR_UNDEF;
accum->size = 0;
accum->dirty = false;
} /* end if */
/* Block to free must end within the accumulator */
else {
size_t new_accum_size; /* Size of new accumulator buffer */
/* Calculate the size of the overlap with the accumulator, etc. */
H5_CHECKED_ASSIGN(overlap_size, size_t, (addr + size) - accum->loc, haddr_t);
new_accum_size = accum->size - overlap_size;
/* Move the accumulator buffer information to eliminate the freed block */
memmove(accum->buf, accum->buf + overlap_size, new_accum_size); //heap-buffer-overflow
/* Adjust the accumulator information */
accum->loc += overlap_size;
accum->size = new_accum_size;
/* ... other code */
} /* end else */
} /* end if */
/* ...other code */
} /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F__accum_free() */
PoC
Steps to reproduce:
- Clone the hdf5 repository and build it using the following commands :
export CC='clang'
export CXX='clang++'
export CFLAGS='-fsanitize=address -g'
export CXXFLAGS='-fsanitize=address -g'
export LDFLAGS="${CFLAGS}"
export CMAKE_C_FLAGS="${CC} ${CFLAGS}"
export CMAKE_CXX_FLAGS="${CXX} ${CXXFLAGS}"
mkdir build-dir
cd build-dir
cmake -G "Unix Makefiles" \
-DCMAKE_BUILD_TYPE:STRING=Release \
-DBUILD_SHARED_LIBS:BOOL=OFF \
-DBUILD_TESTING:BOOL=OFF \
-DCMAKE_VERBOSE_MAKEFILES:BOOL=ON \
-DHDF5_BUILD_EXAMPLES:BOOL=OFF \
-DHDF5_BUILD_TOOLS:BOOL=OFF \
-DHDF5_ENABLE_SANITIZERS:BOOL=ON \
-DHDF5_ENABLE_Z_LIB_SUPPORT:BOOL=ON \
..
cmake --build . --verbose --config Release -j$(nproc)
- Compile the fuzzer:
- harness h5_extended_fuzzer.c from oss-fuzz:
#include "hdf5.h"
#include <unistd.h>
extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
char filename[256];
sprintf(filename, "/tmp/libfuzzer.%d", getpid());
FILE *fp = fopen(filename, "wb");
if (!fp) {
return 0;
}
fwrite(data, size, 1, fp);
fclose(fp);
hid_t fuzz_h5_id = H5Fopen(filename, H5F_ACC_RDWR, H5P_DEFAULT);
if (fuzz_h5_id != H5I_INVALID_HID) {
hid_t dataset_id = H5Dopen2(fuzz_h5_id, "dsetname", H5P_DEFAULT);
if (dataset_id != H5I_INVALID_HID) {
hid_t attribute_id = H5Aopen_name(dataset_id, "theattr");
if (attribute_id != H5I_INVALID_HID) {
H5Aclose(attribute_id);
}
H5Dclose(dataset_id);
}
H5Fclose(fuzz_h5_id);
}
return 0;
}
export LIB_FUZZING_ENGINE='-fsanitize=fuzzer'
$CC $CFLAGS -std=c99 -c \
-I$SRC/hdf5/src -I$SRC/hdf5/build-dir/src -I./src/H5FDsubfiling/ \
$SRC/h5_extended_fuzzer.c
$CXX $CXXFLAGS $LIB_FUZZING_ENGINE h5_extended_fuzzer.o ./build-dir/bin/libhdf5.a -lz -o $OUT/h5_extended_fuzzer
- Run the fuzzer to trigger the segmentation fault:
./h5_extended_fuzzer ./H5F__accum_free-hbo
The invalid read access will cause AddressSanitizer to report a segmentation fault during the execution of the post-processing logic.
Report
Running: ./H5F__accum_free-hbo
HDF5-DIAG: Error detected in HDF5 (2.0.0):
#000: /fuzz/project/hdf5/src/H5D.c line 401 in H5Dopen2(): unable to synchronously open dataset
major: Dataset
minor: Can't open object
#001: /fuzz/project/hdf5/src/H5D.c line 363 in H5D__open_api_common(): unable to open dataset
major: Dataset
minor: Can't open object
#002: /fuzz/project/hdf5/src/H5VLcallback.c line 2090 in H5VL_dataset_open(): dataset open failed
major: Virtual Object Layer
minor: Can't open object
#003: /fuzz/project/hdf5/src/H5VLcallback.c line 2057 in H5VL__dataset_open(): dataset open failed
major: Virtual Object Layer
minor: Can't open object
#004: /fuzz/project/hdf5/src/H5VLnative_dataset.c line 332 in H5VL__native_dataset_open(): unable to open dataset
major: Dataset
minor: Can't open object
#005: /fuzz/project/hdf5/src/H5Dint.c line 1472 in H5D__open_name(): not found
major: Dataset
minor: Object not found
#006: /fuzz/project/hdf5/src/H5Gloc.c line 424 in H5G_loc_find(): can't find object
major: Symbol table
minor: Object not found
#007: /fuzz/project/hdf5/src/H5Gtraverse.c line 846 in H5G_traverse(): internal path traversal failed
major: Symbol table
minor: Object not found
#008: /fuzz/project/hdf5/src/H5Gtraverse.c line 573 in H5G__traverse_real(): can't look up component
major: Symbol table
minor: Object not found
#009: /fuzz/project/hdf5/src/H5Gobj.c line 1070 in H5G__obj_lookup(): can't check for link info message
major: Symbol table
minor: Can't get value
#010: /fuzz/project/hdf5/src/H5Gobj.c line 310 in H5G__obj_get_linfo(): unable to read object header
major: Symbol table
minor: Can't get value
#011: /fuzz/project/hdf5/src/H5Omessage.c line 788 in H5O_msg_exists(): unable to protect object header
major: Object header
minor: Unable to protect metadata
#012: /fuzz/project/hdf5/src/H5Oint.c line 1015 in H5O_protect(): unable to load object header
major: Object header
minor: Unable to protect metadata
#013: /fuzz/project/hdf5/src/H5AC.c line 1303 in H5AC_protect(): H5C_protect() failed
major: Object cache
minor: Unable to protect metadata
#014: /fuzz/project/hdf5/src/H5Centry.c line 3107 in H5C_protect(): can't load entry
major: Object cache
minor: Unable to load metadata into cache
#015: /fuzz/project/hdf5/src/H5Centry.c line 1181 in H5C__load_entry(): incorrect metadata checksum after all read attempts
major: Object cache
minor: Read failed
#016: /fuzz/project/hdf5/src/H5Ocache.c line 185 in H5O__cache_get_final_load_size(): can't deserialize object header prefix
major: Object header
minor: Unable to decode value
#017: /fuzz/project/hdf5/src/H5Ocache.c line 1100 in H5O__prefix_deserialize(): bad object header version number
major: Object header
minor: Wrong version number
=================================================================
==169==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x612000035297 at pc 0x58f8a738a39f bp 0x7ffdd32475c0 sp 0x7ffdd3246d90
READ of size 201 at 0x612000035297 thread T0
#0 0x58f8a738a39e in __asan_memmove (/fuzz/fuzzers/cs/h5_extended_fuzzer+0x2c839e) (BuildId: 4f0aadfc2da7074efe3c033dd7d4d5301b6fc3b1)
#1 0x58f8a7ddee05 in H5F__accum_free /fuzz/project/hdf5/src/H5Faccum.c:885:17
#2 0x58f8a7690e88 in H5MF_xfree /fuzz/project/hdf5/src/H5MF.c:1093:13
#3 0x58f8a769f6e5 in H5MF__aggr_reset /fuzz/project/hdf5/src/H5MFaggr.c:725:21
#4 0x58f8a769f6e5 in H5MF_free_aggrs /fuzz/project/hdf5/src/H5MFaggr.c:789:13
#5 0x58f8a7693b04 in H5MF__close_aggrfs /fuzz/project/hdf5/src/H5MF.c:1725:9
#6 0x58f8a7693b04 in H5MF_close /fuzz/project/hdf5/src/H5MF.c:1512:26
#7 0x58f8a753646a in H5F__dest /fuzz/project/hdf5/src/H5Fint.c:1488:21
#8 0x58f8a7538fc8 in H5F_try_close /fuzz/project/hdf5/src/H5Fint.c:2680:9
#9 0x58f8a75389a5 in H5F__close /fuzz/project/hdf5/src/H5Fint.c:2482:9
#10 0x58f8a7cadf8b in H5VL__native_file_close /fuzz/project/hdf5/src/H5VLnative_file.c:777:13
#11 0x58f8a7c7aa47 in H5VL__file_close /fuzz/project/hdf5/src/H5VLcallback.c:4326:25
#12 0x58f8a7c7a575 in H5VL_file_close /fuzz/project/hdf5/src/H5VLcallback.c:4360:9
#13 0x58f8a753fb7d in H5F__close_cb /fuzz/project/hdf5/src/H5Fint.c:249:9
#14 0x58f8a76806ba in H5I__dec_ref /fuzz/project/hdf5/src/H5Iint.c:1076:30
#15 0x58f8a7680afc in H5I__dec_app_ref /fuzz/project/hdf5/src/H5Iint.c:1156:22
#16 0x58f8a76809e9 in H5I_dec_app_ref /fuzz/project/hdf5/src/H5Iint.c:1201:22
#17 0x58f8a7515c0f in H5Fclose /fuzz/project/hdf5/src/H5F.c:1040:9
#18 0x58f8a73c81e8 in LLVMFuzzerTestOneInput /fuzz/project/h5_extended_fuzzer.c:39:7
#19 0x58f8a72ee5a3 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/fuzz/fuzzers/cs/h5_extended_fuzzer+0x22c5a3) (BuildId: 4f0aadfc2da7074efe3c033dd7d4d5301b6fc3b1)
#20 0x58f8a72d831f in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) (/fuzz/fuzzers/cs/h5_extended_fuzzer+0x21631f) (BuildId: 4f0aadfc2da7074efe3c033dd7d4d5301b6fc3b1)
#21 0x58f8a72de076 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/fuzz/fuzzers/cs/h5_extended_fuzzer+0x21c076) (BuildId: 4f0aadfc2da7074efe3c033dd7d4d5301b6fc3b1)
#22 0x58f8a7307e92 in main (/fuzz/fuzzers/cs/h5_extended_fuzzer+0x245e92) (BuildId: 4f0aadfc2da7074efe3c033dd7d4d5301b6fc3b1)
#23 0x72c74515bd8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#24 0x72c74515be3f in __libc_start_main csu/../csu/libc-start.c:392:3
#25 0x58f8a72d2be4 in _start (/fuzz/fuzzers/cs/h5_extended_fuzzer+0x210be4) (BuildId: 4f0aadfc2da7074efe3c033dd7d4d5301b6fc3b1)
0x612000035297 is located 41 bytes to the left of 264-byte region [0x6120000352c0,0x6120000353c8)
allocated by thread T0 here:
#0 0x58f8a738ac1e in malloc (/fuzz/fuzzers/cs/h5_extended_fuzzer+0x2c8c1e) (BuildId: 4f0aadfc2da7074efe3c033dd7d4d5301b6fc3b1)
#1 0x58f8a75c028c in H5FL__malloc /fuzz/project/hdf5/src/H5FL.c:211:30
#2 0x58f8a75c028c in H5FL_blk_malloc /fuzz/project/hdf5/src/H5FL.c:773:48
SUMMARY: AddressSanitizer: heap-buffer-overflow (/fuzz/fuzzers/cs/h5_extended_fuzzer+0x2c839e) (BuildId: 4f0aadfc2da7074efe3c033dd7d4d5301b6fc3b1) in __asan_memmove
Shadow bytes around the buggy address:
0x0c247fffea00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c247fffea10: 00 00 00 00 00 00 00 00 00 fa fa fa fa fa fa fa
0x0c247fffea20: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
0x0c247fffea30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c247fffea40: 00 00 00 00 00 00 00 00 00 fa fa fa fa fa fa fa
=>0x0c247fffea50: fa fa[fa]fa fa fa fa fa 00 00 00 00 00 00 00 00
0x0c247fffea60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c247fffea70: 00 00 00 00 00 00 00 00 00 fa fa fa fa fa fa fa
0x0c247fffea80: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
0x0c247fffea90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c247fffeaa0: 00 00 00 00 00 00 00 00 00 00 00 fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==169==ABORTING
Metadata
Metadata
Assignees
Labels
Type
Projects
Status