mirror of
https://github.com/openembedded/meta-openembedded.git
synced 2026-11-13 15:47:23 +00:00
hdf5: patch CVE-2026-120754 and CVE-2026-120755
Details: https://nvd.nist.gov/vuln/detail/cve-2026-120754 https://nvd.nist.gov/vuln/detail/cve-2026-120755 Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com> Signed-off-by: Khem Raj <khem.raj@oss.qualcomm.com>
This commit is contained in:
1 parent
08221d912d
commit
6254a354d6
2 files changed
+173
No files matched your search
@@ -0,0 +1,172 @@
|
||||
From 78672660618de8cca7c804f465886af02a89e79b Mon Sep 17 00:00:00 2001
|
||||
From: Matt L <124107509+mattjala@users.noreply.github.com>
|
||||
Date: Wed, 21 Oct 2026 13:52:39 -0500
|
||||
Subject: [PATCH] Bound filter header reads to the stored chunk length (#6585)
|
||||
|
||||
* bound scaleoffset and fletcher32 reads to the chunk buffer
|
||||
|
||||
* Bound filter header reads to the stored chunk length
|
||||
|
||||
This PR is an expansion of #6579.
|
||||
|
||||
The scaleoffset bounds checks measured against *buf_size, the size of the
|
||||
chunk buffer, rather than nbytes, the number of bytes the pipeline read from
|
||||
the file. H5D__chunk_lock() sizes a filtered chunk buffer to MAX(stored size,
|
||||
unfiltered size) so filters have room to expand into, and fills only the
|
||||
stored bytes, so the buffer is routinely longer than the data in it. A
|
||||
truncated chunk therefore passed the header check and decompressed out of the
|
||||
uninitialized remainder of the allocation, returning unrelated heap contents
|
||||
as dataset data. Because the reads stay inside the allocation, the address
|
||||
sanitizer does not see them.
|
||||
|
||||
This PR switches every read-side check in H5Z__filter_scaleoffset()
|
||||
to bound against nbytes and pass the stored length to
|
||||
H5Z__scaleoffset_decompress().
|
||||
|
||||
Similar short-chunk checks are added to szip and fletcher32.
|
||||
|
||||
The direct chunk test has been extended to cover a chunk whose unfiltered size is
|
||||
larger than the bytes stored for it, and to cover szip.
|
||||
|
||||
* Correct potential invalid pointer usage
|
||||
|
||||
* update CHANGELOG
|
||||
|
||||
* Update CHANGELOG comment
|
||||
|
||||
* Guard scaleoffset output size against multiplication overflow
|
||||
|
||||
---------
|
||||
|
||||
Co-authored-by: Nayyar <nayyar@bugqore.com>
|
||||
Co-authored-by: Larry Knox <lrknox@hdfgroup.org>
|
||||
|
||||
CVE: CVE-2026-120754 CVE-2026-120755
|
||||
Upstream-Status: Backport [https://github.com/HDFGroup/hdf5/commit/cdb13c4de9c7edbbae180f384e2e610a3b3cf185]
|
||||
|
||||
Dropped changes to the test and CHANGELOG file.
|
||||
|
||||
Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com>
|
||||
---
|
||||
src/H5Zfletcher32.c | 13 +++++++------
|
||||
src/H5Zscaleoffset.c | 15 +++++++++++----
|
||||
src/H5Zszip.c | 18 ++++++++++++++----
|
||||
3 files changed, 32 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/src/H5Zfletcher32.c b/src/H5Zfletcher32.c
|
||||
index b89724ad0a3..5ef3b04cbcf 100644
|
||||
--- a/src/H5Zfletcher32.c
|
||||
+++ b/src/H5Zfletcher32.c
|
||||
@@ -62,13 +62,14 @@ H5Z__filter_fletcher32(unsigned flags, size_t H5_ATTR_UNUSED cd_nelmts,
|
||||
assert(sizeof(uint32_t) >= 4);
|
||||
|
||||
if (flags & H5Z_FLAG_REVERSE) { /* Read */
|
||||
- /* A Fletcher32-filtered buffer must contain at least the trailing
|
||||
- * checksum. Reject anything smaller to avoid a size_t underflow
|
||||
- * when computing the data length.
|
||||
+ /* The checksum is stored at the end of the chunk, so anything shorter
|
||||
+ * than the checksum itself makes the length arithmetic below wrap. A
|
||||
+ * chunk of exactly FLETCHER_LEN bytes holds no data and would return a
|
||||
+ * filtered size of zero, which the pipeline reports as a filter failure,
|
||||
+ * so reject it here where the reason can be stated.
|
||||
*/
|
||||
- if (nbytes < FLETCHER_LEN)
|
||||
- HGOTO_ERROR(H5E_STORAGE, H5E_OVERFLOW, 0,
|
||||
- "fletcher32 filter input buffer too small to contain checksum");
|
||||
+ if (nbytes <= FLETCHER_LEN)
|
||||
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "buffer too short");
|
||||
|
||||
/* Do checksum if it's enabled for read; otherwise skip it
|
||||
* to save performance. */
|
||||
diff --git a/src/H5Zscaleoffset.c b/src/H5Zscaleoffset.c
|
||||
index d39b4f40403..d506e5203a0 100644
|
||||
--- a/src/H5Zscaleoffset.c
|
||||
+++ b/src/H5Zscaleoffset.c
|
||||
@@ -1205,10 +1205,18 @@ H5Z__filter_scaleoffset(unsigned flags, size_t cd_nelmts, const unsigned cd_valu
|
||||
unsigned long long minval_mask = 0;
|
||||
unsigned minval_size = 0;
|
||||
|
||||
- minbits = 0;
|
||||
- if (H5_IS_BUFFER_OVERFLOW((unsigned char *)*buf, 5, (unsigned char *)*buf + *buf_size - 1))
|
||||
+ /* Bound every read below by nbytes rather than *buf_size. The caller may
|
||||
+ * provide a buffer larger than the data it holds, so restrict the read
|
||||
+ * to the valid nbytes.
|
||||
+ */
|
||||
+ /* The minbits and minval-size fields are the first five bytes of the
|
||||
+ * stream, so validate that length before deriving an end-of-buffer
|
||||
+ * pointer from nbytes
|
||||
+ */
|
||||
+ if (nbytes < 5)
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "buffer too short");
|
||||
|
||||
+ minbits = 0;
|
||||
for (i = 0; i < 4; i++) {
|
||||
minbits_mask = ((unsigned char *)*buf)[i];
|
||||
minbits_mask <<= i * 8;
|
||||
@@ -1224,8 +1232,7 @@ H5Z__filter_scaleoffset(unsigned flags, size_t cd_nelmts, const unsigned cd_valu
|
||||
minval_size = sizeof(unsigned long long) <= ((unsigned char *)*buf)[4] ? sizeof(unsigned long long)
|
||||
: ((unsigned char *)*buf)[4];
|
||||
minval = 0;
|
||||
- if (H5_IS_BUFFER_OVERFLOW((unsigned char *)*buf, 5 + minval_size,
|
||||
- (unsigned char *)*buf + *buf_size - 1))
|
||||
+ if (H5_IS_BUFFER_OVERFLOW((unsigned char *)*buf, 5 + minval_size, (unsigned char *)*buf + nbytes - 1))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "buffer too short");
|
||||
for (i = 0; i < minval_size; i++) {
|
||||
minval_mask = ((unsigned char *)*buf)[5 + i];
|
||||
diff --git a/src/H5Zszip.c b/src/H5Zszip.c
|
||||
index 9b37035374f..dd6c3619873 100644
|
||||
--- a/src/H5Zszip.c
|
||||
+++ b/src/H5Zszip.c
|
||||
@@ -28,6 +28,9 @@
|
||||
#include "szlib.h"
|
||||
#endif
|
||||
|
||||
+/* Size of the uncompressed-length header stored in front of the szip stream */
|
||||
+#define SZIP_HEADER_LEN 4
|
||||
+
|
||||
/* Local function prototypes */
|
||||
static htri_t H5Z__can_apply_szip(hid_t dcpl_id, hid_t type_id, hid_t space_id);
|
||||
static herr_t H5Z__set_local_szip(hid_t dcpl_id, hid_t type_id, hid_t space_id);
|
||||
@@ -284,6 +287,13 @@ H5Z__filter_szip(unsigned flags, size_t cd_nelmts, const unsigned cd_values[], s
|
||||
uint32_t stored_nalloc; /* Number of bytes the compressed block will expand into */
|
||||
size_t nalloc; /* Number of bytes the compressed block will expand into */
|
||||
|
||||
+ /* The uncompressed length is stored in front of the compressed stream, so
|
||||
+ * a chunk shorter than that header makes the length arithmetic below wrap.
|
||||
+ * A chunk of exactly SZIP_HEADER_LEN bytes holds no compressed data.
|
||||
+ */
|
||||
+ if (nbytes <= SZIP_HEADER_LEN)
|
||||
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "buffer too short");
|
||||
+
|
||||
/* Get the size of the uncompressed buffer */
|
||||
newbuf = (unsigned char *)(*buf);
|
||||
UINT32DECODE(newbuf, stored_nalloc);
|
||||
@@ -295,7 +305,7 @@ H5Z__filter_szip(unsigned flags, size_t cd_nelmts, const unsigned cd_values[], s
|
||||
|
||||
/* Decompress the buffer */
|
||||
size_out = nalloc;
|
||||
- if (SZ_BufftoBuffDecompress(outbuf, &size_out, newbuf, nbytes - 4, &sz_param) != SZ_OK)
|
||||
+ if (SZ_BufftoBuffDecompress(outbuf, &size_out, newbuf, nbytes - SZIP_HEADER_LEN, &sz_param) != SZ_OK)
|
||||
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "szip_filter: decompression failed");
|
||||
assert(size_out == nalloc);
|
||||
|
||||
@@ -313,7 +323,7 @@ H5Z__filter_szip(unsigned flags, size_t cd_nelmts, const unsigned cd_values[], s
|
||||
unsigned char *dst = NULL; /* Temporary pointer to new output buffer */
|
||||
|
||||
/* Allocate space for the compressed buffer & header (assume data won't get bigger) */
|
||||
- if (NULL == (dst = outbuf = (unsigned char *)H5MM_malloc(nbytes + 4)))
|
||||
+ if (NULL == (dst = outbuf = (unsigned char *)H5MM_malloc(nbytes + SZIP_HEADER_LEN)))
|
||||
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "unable to allocate szip destination buffer");
|
||||
|
||||
/* Encode the uncompressed length */
|
||||
@@ -332,8 +342,8 @@ H5Z__filter_szip(unsigned flags, size_t cd_nelmts, const unsigned cd_values[], s
|
||||
/* Set return values */
|
||||
*buf = outbuf;
|
||||
outbuf = NULL;
|
||||
- *buf_size = nbytes + 4;
|
||||
- ret_value = size_out + 4;
|
||||
+ *buf_size = nbytes + SZIP_HEADER_LEN;
|
||||
+ ret_value = size_out + SZIP_HEADER_LEN;
|
||||
}
|
||||
|
||||
done:
|
||||
@@ -25,6 +25,7 @@ SRC_URI = "https://support.hdfgroup.org/releases/hdf5/v2_0/v2_0_0/downloads/${BP
|
||||
file://CVE-2026-19026-CVE-2026-19027-CVE-2026-19028.patch \
|
||||
file://CVE-2026-19023-CVE-2026-19024.patch \
|
||||
file://CVE-2026-120689.patch \
|
||||
file://CVE-2026-120754-CVE-2026-120755.patch \
|
||||
"
|
||||
SRC_URI[sha256sum] = "f4c2edc5668fb846627182708dbe1e16c60c467e63177a75b0b9f12c19d7efed"
|
||||
|
||||
|
||||
Reference in new issue
Block a user