hdf5
hdf5 copied to clipboard
[BUG, CVE-2021-46242] Heap use after free in H5AC_unpin_entry()
Describe the bug The reproducer of CVE-2021-46242 exposes a heap use after free error on version 1.10.8 which makes the application crash. This crash can no longer be reproduced on 1.13 - presumably due to commit aa688c68c447c. This commit, however, seems to be unrelated to the issue that causes the crash and I believe the analysis below remain valid regardless: The use-after-free occurs in
H5AC_unpin_entry(void *thing)
{
...
entry_ptr = (H5AC_info_t *)thing;
cache_ptr = entry_ptr->cache_ptr;
...
if (cache_ptr != NULL && cache_ptr->log_info != NULL)
if (cache_ptr->log_info->logging)
--> if (cache_ptr->log_info->logging)
...
}
called from:
herr_t
H5F__dest(H5F_t *f, hbool_t flush)
{
...
if (f->shared->drvinfo)
if (H5AC_unpin_entry(f->shared->drvinfo) < 0)
...
}
Valgrind reveals that f->shared->drvinfo
was freed in
H5F__super_read(..)
{
...
if (ret_value < 0) {
/* Unpin and discard drvinfo cache entry */
if (f->shared->drvinfo) {
if (H5AC_unpin_entry(f->shared->drvinfo) < 0)
HDONE_ERROR(H5E_FILE, H5E_CANTUNPIN, FAIL, "unable to unpin driver info")
/* Evict the driver info block from the cache */
--> if (sblock && H5AC_expunge_entry(f, H5AC_DRVRINFO, sblock->driver_addr, H5AC__NO_FLAGS_SET) < 0)
HDONE_ERROR(H5E_FILE, H5E_CANTEXPUNGE, FAIL, "unable to expunge driver info block")
} /* end if */
...
}
...
}
Since H5C_expunge_entry()
(called from H5AC_expunge_entry()
) sets the H5C__FLUSH_INVALIDATE_FLAG
, the entry is destroyed (ie. deallocated). The pointer f->shared->drvinfo
is however not NULLed. When H5AC_unpin_entry()
is called again from
H5F__dest()
a use-after-free occurs.
Expected behavior
f->shared->drvinfo
should be NULLed, after the call to H5AC_expunge_entry()
. In the same vein f->shared->sblock
should probably also be NULLed after the call to H5AC_expunge_entry(..,H5AC_SUPERBLOCK,..)
. In other parts of the code, these pointers are checked already. These checks will ensure that these pointers are dereferenced only when initialized.
Platform
- 1.10.8 and earlier
- openSUSE Leap 15.4/ SLE 15 SP4 / openSUSE Tumbleweed
- gcc7
- Autotools
- config --enable-fortran --enable-unsupported --enable-hl --enable-shared --enable-threadsafe --enable-build-mode=production --enable-cxx --with-pthread