From bd3568dcfc9cc74114524ce72583545ce3bedea2 Mon Sep 17 00:00:00 2001 From: starlet-dx <15929766099@163.com> Date: Tue, 28 Mar 2023 19:56:11 +0800 Subject: [PATCH] Fix CVE-2018-13867,CVE-2018-14031,CVE-2018-16438,CVE-2019-8396,CVE-2020-10812 and CVE-2021-37501 --- CVE-2018-13867.patch | 96 ++++++++++++++++++++++++++++++++++++++++++++ CVE-2018-14031.patch | 35 ++++++++++++++++ CVE-2018-16438.patch | 34 ++++++++++++++++ CVE-2019-8396.patch | 92 ++++++++++++++++++++++++++++++++++++++++++ CVE-2020-10812.patch | 43 ++++++++++++++++++++ CVE-2021-37501.patch | 66 ++++++++++++++++++++++++++++++ hdf5.spec | 11 ++++- 7 files changed, 376 insertions(+), 1 deletion(-) create mode 100644 CVE-2018-13867.patch create mode 100644 CVE-2018-14031.patch create mode 100644 CVE-2018-16438.patch create mode 100644 CVE-2019-8396.patch create mode 100644 CVE-2020-10812.patch create mode 100644 CVE-2021-37501.patch diff --git a/CVE-2018-13867.patch b/CVE-2018-13867.patch new file mode 100644 index 0000000..26fe5a2 --- /dev/null +++ b/CVE-2018-13867.patch @@ -0,0 +1,96 @@ +From: Egbert Eich +Date: Mon Oct 10 08:43:44 2022 +0200 +Subject: Validate location (offset) of the accumulated metadata when comparing +Patch-mainline: Not yet +Git-repo: ssh://eich@192.168.122.1:/home/eich/sources/HPC/hdf5 +Git-commit: 2cf9918ae66f023a2b6d44eb591ee2ac479a6e53 +References: + +Initially, the accumulated metadata location is initialized to HADDR_UNDEF +- the highest available address. Bogus input files may provide a location +or size matching this value. Comparing this address against such bogus +values may provide false positives. This make sure, the value has been +initilized or fail the comparison early and let other parts of the +code deal with the bogus address/size. +Note: To avoid unnecessary checks, we have assumed that if the 'dirty' +member in the same structure is true the location is valid. + +This fixes CVE-2018-13867. + +Signed-off-by: Egbert Eich +Signed-off-by: Egbert Eich +--- + src/H5Faccum.c | 19 +++++++++++++------ + 1 file changed, 13 insertions(+), 6 deletions(-) +diff --git a/src/H5Faccum.c b/src/H5Faccum.c +index aed5812e63..73bd4b811e 100644 +--- a/src/H5Faccum.c ++++ b/src/H5Faccum.c +@@ -48,6 +48,7 @@ + #define H5F_ACCUM_THROTTLE 8 + #define H5F_ACCUM_THRESHOLD 2048 + #define H5F_ACCUM_MAX_SIZE (1024 * 1024) /* Max. accum. buf size (max. I/Os will be 1/2 this size) */ ++#define H5F_LOC_VALID(x) (x != HADDR_UNDEF) + + /******************/ + /* Local Typedefs */ +@@ -126,8 +127,9 @@ H5F__accum_read(H5F_shared_t *f_sh, H5FD_mem_t map_type, haddr_t addr, size_t si + HDassert(!accum->buf || (accum->alloc_size >= accum->size)); + + /* Current read adjoins or overlaps with metadata accumulator */ +- if (H5F_addr_overlap(addr, size, accum->loc, accum->size) || ((addr + size) == accum->loc) || +- (accum->loc + accum->size) == addr) { ++ if (H5F_LOC_VALID(accum->loc) && ++ (H5F_addr_overlap(addr, size, accum->loc, accum->size) || ((addr + size) == accum->loc) || ++ (accum->loc + accum->size) == addr)) { + size_t amount_before; /* Amount to read before current accumulator */ + haddr_t new_addr; /* New address of the accumulator buffer */ + size_t new_size; /* New size of the accumulator buffer */ +@@ -439,7 +441,8 @@ H5F__accum_write(H5F_shared_t *f_sh, H5FD_mem_t map_type, haddr_t addr, size_t s + /* Check if there is already metadata in the accumulator */ + if (accum->size > 0) { + /* Check if the new metadata adjoins the beginning of the current accumulator */ +- if ((addr + size) == accum->loc) { ++ if (H5F_LOC_VALID(accum->loc) ++ && (addr + size) == accum->loc) { + /* Check if we need to adjust accumulator size */ + if (H5F__accum_adjust(accum, file, H5F_ACCUM_PREPEND, size) < 0) + HGOTO_ERROR(H5E_IO, H5E_CANTRESIZE, FAIL, "can't adjust metadata accumulator") +@@ -464,7 +467,8 @@ H5F__accum_write(H5F_shared_t *f_sh, H5FD_mem_t map_type, haddr_t addr, size_t s + accum->dirty_off = 0; + } /* end if */ + /* Check if the new metadata adjoins the end of the current accumulator */ +- else if (addr == (accum->loc + accum->size)) { ++ else if (H5F_LOC_VALID(accum->loc) && ++ addr == (accum->loc + accum->size)) { + /* Check if we need to adjust accumulator size */ + if (H5F__accum_adjust(accum, file, H5F_ACCUM_APPEND, size) < 0) + HGOTO_ERROR(H5E_IO, H5E_CANTRESIZE, FAIL, "can't adjust metadata accumulator") +@@ -485,7 +489,8 @@ H5F__accum_write(H5F_shared_t *f_sh, H5FD_mem_t map_type, haddr_t addr, size_t s + accum->size += size; + } /* end if */ + /* Check if the piece of metadata being written overlaps the metadata accumulator */ +- else if (H5F_addr_overlap(addr, size, accum->loc, accum->size)) { ++ else if (H5F_LOC_VALID(accum->loc) && ++ H5F_addr_overlap(addr, size, accum->loc, accum->size)) { + size_t add_size; /* New size of the accumulator buffer */ + + /* Check if the new metadata is entirely within the current accumulator */ +@@ -745,7 +750,8 @@ H5F__accum_write(H5F_shared_t *f_sh, H5FD_mem_t map_type, haddr_t addr, size_t s + /* (Note that this could be improved by updating the accumulator + * with [some of] the information just read in. -QAK) + */ +- if (H5F_addr_overlap(addr, size, accum->loc, accum->size)) { ++ if (H5F_LOC_VALID(accum->loc) && ++ H5F_addr_overlap(addr, size, accum->loc, accum->size)) { + /* Check for write starting before beginning of accumulator */ + if (H5F_addr_le(addr, accum->loc)) { + /* Check for write ending within accumulator */ +@@ -868,6 +874,7 @@ H5F__accum_free(H5F_shared_t *f_sh, H5FD_mem_t H5_ATTR_UNUSED type, haddr_t addr + + /* Adjust the metadata accumulator to remove the freed block, if it overlaps */ + if ((f_sh->feature_flags & H5FD_FEAT_ACCUMULATE_METADATA) && ++ H5F_LOC_VALID(accum->loc) && + H5F_addr_overlap(addr, size, accum->loc, accum->size)) { + size_t overlap_size; /* Size of overlap with accumulator */ + diff --git a/CVE-2018-14031.patch b/CVE-2018-14031.patch new file mode 100644 index 0000000..be28038 --- /dev/null +++ b/CVE-2018-14031.patch @@ -0,0 +1,35 @@ +From: Egbert Eich +Date: Wed Sep 28 14:54:58 2022 +0200 +Subject: H5O_dtype_decode_helper: Parent of enum needs to have same size as enum itself +Patch-mainline: Not yet +Git-repo: ssh://eich@192.168.122.1:/home/eich/sources/HPC/hdf5 +Git-commit: d39a27113ef75058f236b0606a74b4af5767c4e7 +References: + +The size of the enumeration values is determined by the size of the parent. +Functions accessing the enumeration values use the size of the enumartion +to determine the size of each element and how much data to copy. Thus the +size of the enumeration and its parent need to match. +Check here to avoid unpleasant surprises later. + +This fixes CVE-2018-14031. + +Signed-off-by: Egbert Eich +Signed-off-by: Egbert Eich +--- + src/H5Odtype.c | 3 +++ + 1 file changed, 3 insertions(+) +diff --git a/src/H5Odtype.c b/src/H5Odtype.c +index 9af79f4e9a..dc2b904362 100644 +--- a/src/H5Odtype.c ++++ b/src/H5Odtype.c +@@ -472,6 +472,9 @@ H5O__dtype_decode_helper(unsigned *ioflags /*in,out*/, const uint8_t **pp, H5T_t + if (H5O__dtype_decode_helper(ioflags, pp, dt->shared->parent) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "unable to decode parent datatype") + ++ if (dt->shared->parent->shared->size != dt->shared->size) ++ HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "ENUM size does not match parent") ++ + /* Check if the parent of this enum has a version greater than the + * enum itself. */ + H5O_DTYPE_CHECK_VERSION(dt, version, dt->shared->parent->shared->version, ioflags, "enum", FAIL) diff --git a/CVE-2018-16438.patch b/CVE-2018-16438.patch new file mode 100644 index 0000000..85504b6 --- /dev/null +++ b/CVE-2018-16438.patch @@ -0,0 +1,34 @@ +From: Egbert Eich +Date: Sun Oct 9 08:07:23 2022 +0200 +Subject: Make sure info block for external links has at least 3 bytes +Patch-mainline: Not yet +Git-repo: ssh://eich@192.168.122.1:/home/eich/sources/HPC/hdf5 +Git-commit: 082bfe392b04b1137da9eabd1ecac76c212ab385 +References: + +According to the specification, the information block for external links +contains 1 byte of version/flag information and two 0 terminated strings +for the object linked to and the full path. +Although not very useful, the minimum string length for each would be one +byte. + +This fixes CVE-2018-16438. + +Signed-off-by: Egbert Eich +Signed-off-by: Egbert Eich +--- + src/H5Olink.c | 2 ++ + 1 file changed, 2 insertions(+) +diff --git a/src/H5Olink.c b/src/H5Olink.c +index 51c44a36b0..074744b022 100644 +--- a/src/H5Olink.c ++++ b/src/H5Olink.c +@@ -241,6 +241,8 @@ H5O__link_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh, unsigned H5_ATTR_UNUSE + /* A UD link. Get the user-supplied data */ + UINT16DECODE(p, len) + lnk->u.ud.size = len; ++ if (lnk->type == H5L_TYPE_EXTERNAL && len < 3) ++ HGOTO_ERROR(H5E_OHDR, H5E_OVERFLOW, NULL, "external link information lenght < 3") + if (len > 0) { + /* Make sure that length doesn't exceed buffer size, which could + occur when the file is corrupted */ diff --git a/CVE-2019-8396.patch b/CVE-2019-8396.patch new file mode 100644 index 0000000..8cba0d6 --- /dev/null +++ b/CVE-2019-8396.patch @@ -0,0 +1,92 @@ +From 8e5d36c7465699671b89023f752a378f5ee8b7cb Mon Sep 17 00:00:00 2001 +From: starlet-dx <15929766099@163.com> +Date: Tue, 28 Mar 2023 17:31:29 +0800 +Subject: [PATCH 1/1] H5O__pline_decode() Make more resilient to out-of-bounds read (#2210) + +Malformed hdf5 files may have trunkated content which does not match the expected size. When this function attempts to decode these it may read past the end of the allocated space leading to heap overflows as bounds checking is incomplete. +Make sure each element is within bounds before reading. + +This fixes CVE-2019-8396 / HDFFV-10712 / github bug #2209. + +Signed-off-by: Egbert Eich + +Signed-off-by: Egbert Eich +--- + src/H5Opline.c | 17 +++++++++++++++-- + src/H5private.h | 3 +++ + 2 files changed, 18 insertions(+), 2 deletions(-) + +diff --git a/src/H5Opline.c b/src/H5Opline.c +index 4b76da9..eacf81a 100644 +--- a/src/H5Opline.c ++++ b/src/H5Opline.c +@@ -110,6 +110,7 @@ H5FL_DEFINE(H5O_pline_t); + * + *------------------------------------------------------------------------- + */ ++ + static void * + H5O__pline_decode(H5F_t H5_ATTR_UNUSED *f, H5O_t H5_ATTR_UNUSED *open_oh, unsigned H5_ATTR_UNUSED mesg_flags, + unsigned H5_ATTR_UNUSED *ioflags, size_t p_size, const uint8_t *p) +@@ -131,6 +132,9 @@ H5O__pline_decode(H5F_t H5_ATTR_UNUSED *f, H5O_t H5_ATTR_UNUSED *open_oh, unsign + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* Version */ ++ if (p + 4 - 1 > p_end) /* 4 byte is minimum for all versions */ ++ HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, NULL, "ran off the end of the buffer: current p = %p, p_end = %p", ++ p + 4, p_end) + pline->version = *p++; + if (pline->version < H5O_PLINE_VERSION_1 || pline->version > H5O_PLINE_VERSION_LATEST) + HGOTO_ERROR(H5E_PLINE, H5E_CANTLOAD, NULL, "bad version number for filter pipeline message") +@@ -159,6 +163,9 @@ H5O__pline_decode(H5F_t H5_ATTR_UNUSED *f, H5O_t H5_ATTR_UNUSED *open_oh, unsign + /* Decode filters */ + for (i = 0, filter = &pline->filter[0]; i < pline->nused; i++, filter++) { + /* Filter ID */ ++ if (p + 6 - 1 > p_end) /* 6 bytes minimum */ ++ HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, NULL, ++ "ran off the end of the buffer: current p = %p, p_end = %p", p + 6, p_end) + UINT16DECODE(p, filter->id); + + /* Length of filter name */ +@@ -168,6 +175,9 @@ H5O__pline_decode(H5F_t H5_ATTR_UNUSED *f, H5O_t H5_ATTR_UNUSED *open_oh, unsign + UINT16DECODE(p, name_length); + if (pline->version == H5O_PLINE_VERSION_1 && name_length % 8) + HGOTO_ERROR(H5E_PLINE, H5E_CANTLOAD, NULL, "filter name length is not a multiple of eight") ++ if (p + 4 - 1 > p_end) /* with name_length 4 bytes to go */ ++ HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, NULL, ++ "ran off the end of the buffer: current p = %p, p_end = %p", p + 4, p_end) + } /* end if */ + + /* Filter flags */ +@@ -179,9 +189,12 @@ H5O__pline_decode(H5F_t H5_ATTR_UNUSED *f, H5O_t H5_ATTR_UNUSED *open_oh, unsign + /* Filter name, if there is one */ + if (name_length) { + size_t actual_name_length; /* Actual length of name */ +- ++ size_t len = (size_t)(p_end - p + 1); + /* Determine actual name length (without padding, but with null terminator) */ +- actual_name_length = HDstrlen((const char *)p) + 1; ++ actual_name_length = HDstrnlen((const char *)p, len); ++ if (actual_name_length == len) ++ HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, NULL, "filter name not null terminated") ++ actual_name_length += 1; /* include \0 byte */ + HDassert(actual_name_length <= name_length); + + /* Allocate space for the filter name, or use the internal buffer */ +diff --git a/src/H5private.h b/src/H5private.h +index 56ded14..58ccfef 100644 +--- a/src/H5private.h ++++ b/src/H5private.h +@@ -1444,6 +1444,9 @@ H5_DLL void HDsrand(unsigned int seed); + #ifndef HDstrlen + #define HDstrlen(S) strlen(S) + #endif /* HDstrlen */ ++#ifndef HDstrnlen ++#define HDstrnlen(S, L) strnlen(S, L) ++#endif + #ifndef HDstrncat + #define HDstrncat(X, Y, Z) strncat(X, Y, Z) + #endif /* HDstrncat */ +-- +2.30.0 + diff --git a/CVE-2020-10812.patch b/CVE-2020-10812.patch new file mode 100644 index 0000000..f3ad1fe --- /dev/null +++ b/CVE-2020-10812.patch @@ -0,0 +1,43 @@ +From: Egbert Eich +Date: Wed Oct 5 09:44:02 2022 +0200 +Subject: Hot fix for CVE-2020-10812 +Patch-mainline: Not yet +Git-repo: ssh://eich@192.168.122.1:/home/eich/sources/HPC/hdf5 +Git-commit: 2465fc41d208d57eb0d7d025286a81664148fbaf +References: + +CVE-2020-10812 unveils a more fundamental design flaw in H5F__dest(): +this function returns FAIL if one of multiple operations fail (in this +case H5AC_prep_for_file_close()) while it still proceeds to prepare the +close operation, free the 'shared' member in struct H5F_t and ulimately +deallocate the structure itself. +When H5F__dest() signals back FAIL to the caller, the caller itself +(H5F_try_close() in this case) will fail. This failure is signalled +up the stack, thus the file will not be considered closed and another +attempt will be made to close it - latest in the exit handler. +The next attempt to close will however need the already deallocated +H5F_t structure and the H5T_shared_t structure in its 'shared' member, +however. +This fix papers over the failure of H5AC_prep_for_file_close() by not +changing the return status of H5F__dest() to fail. There are numerous +other opportunities where this will happen. +This may call for a more fundamental solution. + +Signed-off-by: Egbert Eich +Signed-off-by: Egbert Eich +--- + src/H5Fint.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) +diff --git a/src/H5Fint.c b/src/H5Fint.c +index 9b5613972f..01faf33495 100644 +--- a/src/H5Fint.c ++++ b/src/H5Fint.c +@@ -1413,7 +1413,7 @@ H5F__dest(H5F_t *f, hbool_t flush) + */ + if (H5AC_prep_for_file_close(f) < 0) + /* Push error, but keep going */ +- HDONE_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "metadata cache prep for close failed") ++ HDONE_ERROR(H5E_FILE, H5E_CANTFLUSH, ret_value, "metadata cache prep for close failed") + + /* Flush at this point since the file will be closed (phase 2). + * Only try to flush the file if it was opened with write access, and if diff --git a/CVE-2021-37501.patch b/CVE-2021-37501.patch new file mode 100644 index 0000000..11ac938 --- /dev/null +++ b/CVE-2021-37501.patch @@ -0,0 +1,66 @@ +From: Egbert Eich +Date: Sat Feb 11 13:54:17 2023 +0100 +Subject: Check for overflow when calculating on-disk attribute data size (#2459) +Patch-mainline: Not yet +Git-repo: https://github.com/HDFGroup/hdf5 +Git-commit: 0d026daa13a81be72495872f651c036fdc84ae5e +References: + +A bogus hdf5 file may contain dataspace messages with sizes +which lead to the on-disk data sizes to exceed what is addressable. +When calculating the size, make sure, the multiplication does not +overflow. +The test case was crafted in a way that the overflow caused the +size to be 0. + +This fixes CVE-2021-37501 / Bug #2458. + +Signed-off-by: Egbert Eich +Signed-off-by: Egbert Eich +--- + src/H5Oattr.c | 3 +++ + src/H5private.h | 18 ++++++++++++++++++ + 2 files changed, 21 insertions(+) +diff --git a/src/H5Oattr.c b/src/H5Oattr.c +index 4dee7aa187..3ef0b99aa4 100644 +--- a/src/H5Oattr.c ++++ b/src/H5Oattr.c +@@ -235,6 +235,9 @@ H5O_attr_decode(H5F_t *f, H5O_t *open_oh, unsigned H5_ATTR_UNUSED mesg_flags, un + + /* Compute the size of the data */ + H5_CHECKED_ASSIGN(attr->shared->data_size, size_t, ds_size * (hsize_t)dt_size, hsize_t); ++ H5_CHECK_MUL_OVERFLOW(attr->shared->data_size, ds_size, dt_size, ++ HGOTO_ERROR(H5E_RESOURCE, H5E_OVERFLOW, NULL, ++ "data size exceeds addressable range")) + + /* Go get the data */ + if (attr->shared->data_size) { +diff --git a/src/H5private.h b/src/H5private.h +index 931d7b9046..a115aee1a4 100644 +--- a/src/H5private.h ++++ b/src/H5private.h +@@ -1605,6 +1605,24 @@ H5_DLL int HDvasprintf(char **bufp, const char *fmt, va_list _ap); + #define H5_CHECK_OVERFLOW(var, vartype, casttype) + #endif /* NDEBUG */ + ++/* ++ * A macro for checking whether a multiplication has overflown ++ * r is assumed to be the result of a prior multiplication of a and b ++ */ ++#define H5_CHECK_MUL_OVERFLOW(r, a, b, err) \ ++ { \ ++ bool mul_overflow = false; \ ++ if (r != 0) { \ ++ if (r / a != b) \ ++ mul_overflow = true; \ ++ } else { \ ++ if (a != 0 && b != 0) \ ++ mul_overflow = true; \ ++ } \ ++ if (mul_overflow) \ ++ err \ ++ } ++ + /* + * A macro for detecting over/under-flow when assigning between types + */ diff --git a/hdf5.spec b/hdf5.spec index 49e3ca2..5bffe04 100644 --- a/hdf5.spec +++ b/hdf5.spec @@ -11,7 +11,7 @@ Name: hdf5 Version: 1.12.1 -Release: 1 +Release: 2 Summary: A data model, library, and file format for storing and managing data License: GPL-2.0-or-later @@ -22,6 +22,12 @@ Patch0: hdf5-LD_LIBRARY_PATH.patch Patch1: hdf5-gfortran12.patch Patch2: hdf5-build.patch Patch3: hdf5-wrappers.patch +Patch4: CVE-2018-13867.patch +Patch5: CVE-2018-14031.patch +Patch6: CVE-2018-16438.patch +Patch7: CVE-2019-8396.patch +Patch8: CVE-2020-10812.patch +Patch9: CVE-2021-37501.patch BuildRequires: gcc, gcc-c++ BuildRequires: krb5-devel, openssl-devel, zlib-devel, gcc-gfortran, time @@ -375,6 +381,9 @@ make %{?_smp_mflags} -C build check %endif %changelog +* Tue Mar 28 2023 yaoxin - 1.12.1-2 +- Fix CVE-2018-13867,CVE-2018-14031,CVE-2018-16438,CVE-2019-8396,CVE-2020-10812 and CVE-2021-37501 + * Thu Jun 23 2022 wulei - 1.12.1-1 - Upgrade to 1.12.1 -- Gitee