Fix CVE-2018-13867,CVE-2018-14031,CVE-2018-16438,CVE-2019-8396,CVE-2020-10812 and CVE-2021-37501

This commit is contained in:
starlet-dx 2023-03-28 19:56:11 +08:00
parent 5863ec5cff
commit bd3568dcfc
7 changed files with 376 additions and 1 deletions

96
CVE-2018-13867.patch Normal file
View File

@ -0,0 +1,96 @@
From: Egbert Eich <eich@suse.com>
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 <eich@suse.com>
Signed-off-by: Egbert Eich <eich@suse.de>
---
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 */

35
CVE-2018-14031.patch Normal file
View File

@ -0,0 +1,35 @@
From: Egbert Eich <eich@suse.com>
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 <eich@suse.com>
Signed-off-by: Egbert Eich <eich@suse.de>
---
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)

34
CVE-2018-16438.patch Normal file
View File

@ -0,0 +1,34 @@
From: Egbert Eich <eich@suse.com>
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 <eich@suse.com>
Signed-off-by: Egbert Eich <eich@suse.de>
---
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 */

92
CVE-2019-8396.patch Normal file
View File

@ -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 <eich@suse.com>
Signed-off-by: Egbert Eich <eich@suse.com>
---
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

43
CVE-2020-10812.patch Normal file
View File

@ -0,0 +1,43 @@
From: Egbert Eich <eich@suse.com>
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 <eich@suse.com>
Signed-off-by: Egbert Eich <eich@suse.de>
---
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

66
CVE-2021-37501.patch Normal file
View File

@ -0,0 +1,66 @@
From: Egbert Eich <eich@suse.com>
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 <eich@suse.com>
Signed-off-by: Egbert Eich <eich@suse.de>
---
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
*/

View File

@ -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 <yaoxin30@h-partners.com> - 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 <wulei80@h-partners.com> - 1.12.1-1
- Upgrade to 1.12.1