From 88e458ac435340f327f252b82ad9b6c1c1f4f618 Mon Sep 17 00:00:00 2001 From: Binh-Minh Ribler Date: Wed, 22 Jul 2020 16:13:26 -0500 Subject: [PATCH] Fix HDFFV-11120 and HDFFV-11121 (CVE-2018-13870 and CVE-2018-13869) Description: When a buffer overflow occurred because a name length was corrupted and became very large, h5dump produced a segfault on one file and a memcpy parameter overlap on another file. This commit added checks that detect a read pass the end of the buffer to prevent these error conditions. Platforms tested: Linux/64 (jelly) SunOS 5.11 (emu) --- release_docs/RELEASE.txt | 11 +++++++++++ src/H5Olink.c | 19 ++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index 84f339a28f..ba8eabedd7 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -656,6 +656,17 @@ Bug Fixes since HDF5-1.10.3 release Library ------- + - Fixed issues CVE-2018-13870 and CVE-2018-13869 + + When a buffer overflow occurred because a name length was corrupted + and became very large, h5dump crashed on memory access violation. + + A check for reading pass the end of the buffer was added to multiple + locations to prevent the crashes and h5dump now simply fails with an + error message when this error condition occurs. + + (BMR - 2020/7/22, HDFFV-11120 and HDFFV-11121) + - Fixed the segmentation fault when reading attributes with multiple threads It was reported that the reading of attributes with variable length string diff --git a/src/H5Olink.c b/src/H5Olink.c index 1f0c6c7710..8aaf2d282c 100644 --- a/src/H5Olink.c +++ b/src/H5Olink.c @@ -119,11 +119,12 @@ H5FL_DEFINE_STATIC(H5O_link_t); static void * H5O__link_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh, unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags, - size_t H5_ATTR_UNUSED p_size, const uint8_t *p) + size_t p_size, const uint8_t *p) { H5O_link_t *lnk = NULL; /* Pointer to link message */ size_t len = 0; /* Length of a string in the message */ unsigned char link_flags; /* Flags for encoding link info */ + const uint8_t *p_end = p + p_size; /* End of the p buffer */ void *ret_value = NULL; /* Return value */ FUNC_ENTER_STATIC @@ -199,6 +200,11 @@ H5O__link_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh, if(len == 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "invalid name length") + /* Make sure that length doesn't exceed buffer size, which could occur + when the file is corrupted */ + if(p + len > p_end) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "name length causes read pass end of buffer") + /* Get the link's name */ if(NULL == (lnk->name = (char *)H5MM_malloc(len + 1))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") @@ -218,6 +224,12 @@ H5O__link_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh, UINT16DECODE(p, len) if(len == 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "invalid link length") + + /* Make sure that length doesn't exceed buffer size, which could occur + when the file is corrupted */ + if(p + len > p_end) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "name length causes read pass end of buffer") + if(NULL == (lnk->u.soft.name = (char *)H5MM_malloc((size_t)len + 1))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") H5MM_memcpy(lnk->u.soft.name, p, len); @@ -238,6 +250,11 @@ H5O__link_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh, lnk->u.ud.size = len; if(len > 0) { + /* Make sure that length doesn't exceed buffer size, which could + occur when the file is corrupted */ + if(p + len > p_end) + HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "name length causes read pass end of buffer") + if(NULL == (lnk->u.ud.udata = H5MM_malloc((size_t)len))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") H5MM_memcpy(lnk->u.ud.udata, p, len);