Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 125 additions & 0 deletions SPECS/hdf5/CVE-2025-44904.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
From d069f15269509d14f86479f760b2edc62c0c6e9b Mon Sep 17 00:00:00 2001
From: Neil Fortner <fortnern@gmail.com>
Date: Mon, 2 Feb 2026 16:10:04 -0600
Subject: [PATCH] Fix CVE-2025-44904 (#6179)

Fix potential buffer overflow due to invalid chunk size reported by chunk index
(CVE-2025-44904)

Upstream Patch reference: https://github.com/HDFGroup/hdf5/commit/d069f15269509d14f86479f760b2edc62c0c6e9b.patch
---
src/H5Dchunk.c | 48 ++++++++++++++++++++++++++++++++----------------
1 file changed, 32 insertions(+), 16 deletions(-)

diff --git a/src/H5Dchunk.c b/src/H5Dchunk.c
index 5cba7c5..93ee9df 100644
--- a/src/H5Dchunk.c
+++ b/src/H5Dchunk.c
@@ -4453,12 +4453,12 @@ H5D__chunk_lock(const H5D_io_info_t H5_ATTR_NDEBUG_UNUSED *io_info, const H5D_ds
} /* end if */
} /* end if */
else {
- haddr_t chunk_addr; /* Address of chunk on disk */
- hsize_t chunk_alloc; /* Length of chunk on disk */
+ haddr_t chunk_addr; /* Address of chunk on disk */
+ hsize_t chunk_disk_size; /* Length of chunk on disk */

/* Save the chunk info so the cache stays consistent */
- chunk_addr = udata->chunk_block.offset;
- chunk_alloc = udata->chunk_block.length;
+ chunk_addr = udata->chunk_block.offset;
+ chunk_disk_size = udata->chunk_block.length;

/* Check if we should disable filters on this chunk */
if (pline->nused) {
@@ -4490,6 +4490,12 @@ H5D__chunk_lock(const H5D_io_info_t H5_ATTR_NDEBUG_UNUSED *io_info, const H5D_ds
} /* end if */
} /* end if */

+ /* If the chunk on disk is unfiltered, verify the index returned the correct size for the chunk */
+ if (H5_UNLIKELY((chunk_disk_size != (hsize_t)chunk_size) && H5_addr_defined(chunk_addr) &&
+ (!old_pline || !old_pline->nused)))
+ HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, NULL,
+ "incorrect chunk size returned from index for unfiltered chunk");
+
if (relax) {
/*
* Not in the cache, but we're about to overwrite the whole thing
@@ -4514,19 +4520,29 @@ H5D__chunk_lock(const H5D_io_info_t H5_ATTR_NDEBUG_UNUSED *io_info, const H5D_ds

/* Check if the chunk exists on disk */
if (H5_addr_defined(chunk_addr)) {
- size_t my_chunk_alloc = chunk_alloc; /* Allocated buffer size */
- size_t buf_alloc = chunk_alloc; /* [Re-]allocated buffer size */
+ size_t chunk_nbytes; /* Length of the chunk in memory */
+ size_t buf_alloc; /* [Re-]allocated chunk buffer size */
+
+ /* Assign above variables and check for overflow */
+ H5_CHECKED_ASSIGN(chunk_nbytes, size_t, chunk_disk_size, hsize_t);
+ H5_CHECKED_ASSIGN(buf_alloc, size_t, chunk_disk_size, hsize_t);
+
+ /* Ideally we should allocate a buffer at least as large as chunk_size, to give the filter the
+ * opportunity to avoid doing a realloc when uncompressing. This causes problems now, however,
+ * and needs more investigation. -NAF */

- /* Chunk size on disk isn't [likely] the same size as the final chunk
- * size in memory, so allocate memory big enough. */
- if (NULL == (chunk = H5D__chunk_mem_alloc(my_chunk_alloc,
- (udata->new_unfilt_chunk ? old_pline : pline))))
+ /* Allocate chunk buffer */
+ if (NULL ==
+ (chunk = H5D__chunk_mem_alloc(buf_alloc, (udata->new_unfilt_chunk ? old_pline : pline))))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL,
"memory allocation failed for raw data chunk");
+
+ /* Read chunk from disk */
if (H5F_shared_block_read(H5F_SHARED(dset->oloc.file), H5FD_MEM_DRAW, chunk_addr,
- my_chunk_alloc, chunk) < 0)
+ chunk_disk_size, chunk) < 0)
HGOTO_ERROR(H5E_IO, H5E_READERROR, NULL, "unable to read raw data chunk");

+ /* Unfilter chunk */
if (old_pline && old_pline->nused) {
H5Z_EDC_t err_detect; /* Error detection info */
H5Z_cb_t filter_cb; /* I/O filter callback function */
@@ -4537,15 +4553,16 @@ H5D__chunk_lock(const H5D_io_info_t H5_ATTR_NDEBUG_UNUSED *io_info, const H5D_ds
if (H5CX_get_filter_cb(&filter_cb) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, NULL, "can't get I/O filter callback function");

+ /* Perform filter pipeline */
if (H5Z_pipeline(old_pline, H5Z_FLAG_REVERSE, &(udata->filter_mask), err_detect,
- filter_cb, &my_chunk_alloc, &buf_alloc, &chunk) < 0)
+ filter_cb, &chunk_nbytes, &buf_alloc, &chunk) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTFILTER, NULL, "data pipeline read failed");

/* Reallocate chunk if necessary */
if (udata->new_unfilt_chunk) {
void *tmp_chunk = chunk;

- if (NULL == (chunk = H5D__chunk_mem_alloc(my_chunk_alloc, pline))) {
+ if (NULL == (chunk = H5D__chunk_mem_alloc(chunk_nbytes, pline))) {
(void)H5D__chunk_mem_xfree(tmp_chunk, old_pline);
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL,
"memory allocation failed for raw data chunk");
@@ -4564,8 +4581,7 @@ H5D__chunk_lock(const H5D_io_info_t H5_ATTR_NDEBUG_UNUSED *io_info, const H5D_ds
/* Sanity check */
assert(fill->alloc_time != H5D_ALLOC_TIME_EARLY);

- /* Chunk size on disk isn't [likely] the same size as the final chunk
- * size in memory, so allocate memory big enough. */
+ /* Allocate chunk buffer large enough to hold an unfiltered (in cache) chunk */
if (NULL == (chunk = H5D__chunk_mem_alloc(chunk_size, pline)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL,
"memory allocation failed for raw data chunk");
@@ -4629,7 +4645,7 @@ H5D__chunk_lock(const H5D_io_info_t H5_ATTR_NDEBUG_UNUSED *io_info, const H5D_ds

/* Initialize the new entry */
ent->chunk_block.offset = chunk_addr;
- ent->chunk_block.length = chunk_alloc;
+ ent->chunk_block.length = chunk_disk_size;
ent->chunk_idx = udata->chunk_idx;
H5MM_memcpy(ent->scaled, udata->common.scaled, sizeof(hsize_t) * layout->u.chunk.ndims);
H5_CHECKED_ASSIGN(ent->rd_count, uint32_t, chunk_size, size_t);
--
2.43.0

6 changes: 5 additions & 1 deletion SPECS/hdf5/hdf5.spec
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
Summary: A general purpose library and file format for storing scientific data
Name: hdf5
Version: 1.14.6
Release: 2%{?dist}
Release: 3%{?dist}
License: BSD
Vendor: Microsoft Corporation
Distribution: Azure Linux
Expand All @@ -39,6 +39,7 @@ Patch13: CVE-2025-6858.patch
Patch14: CVE-2025-7067.patch
Patch15: CVE-2025-7068.patch
Patch16: CVE-2025-2915.patch
Patch17: CVE-2025-44904.patch

# For patches/rpath
BuildRequires: automake
Expand Down Expand Up @@ -410,6 +411,9 @@ done


%changelog
* Fri Jul 10 2026 Azure Linux Security Servicing Account <azurelinux-security@microsoft.com> - 1.14.6-3
- Patch for CVE-2025-44904

* Tue Jan 20 2026 Aditya Singh <v-aditysing@microsoft.com> - 1.14.6-2
- Patch for CVE-2025-2915
- Skipping failing test cases after applying this patch.
Expand Down
Loading