diff mbox series

[oe,meta-oe,scarthgap,v3,03/11] hdf5: fix CVE-2025-6857

Message ID 20260417082520.3451816-1-libo.chen.cn@windriver.com
State Not Applicable, archived
Delegated to: Yoann Congal
Headers show
Series None | expand

Commit Message

Chen, Libo (CN) April 17, 2026, 8:25 a.m. UTC
From: Libo Chen <libo.chen.cn@windriver.com>

According to [1], A vulnerability has been found in HDF5 1.14.6 and
classified as problematic. Affected by this vulnerability is the function
H5G__node_cmp3 of the file src/H5Gnode.c. The manipulation leads to
stack-based buffer overflow. It is possible to launch the attack on the
local host. The exploit has been disclosed to the public and may be used.

Backport patch [2] from upstream to fix CVE-2025-6857

[1] https://nvd.nist.gov/vuln/detail/CVE-2025-6857
[2] https://github.com/HDFGroup/hdf5/commit/a8ceb1d95bb997f548c1129363dad53c18540096

Signed-off-by: Libo Chen <libo.chen.cn@windriver.com>
---
 .../hdf5/files/CVE-2025-6857.patch            | 255 ++++++++++++++++++
 meta-oe/recipes-support/hdf5/hdf5_1.14.4-3.bb |   1 +
 2 files changed, 256 insertions(+)
 create mode 100644 meta-oe/recipes-support/hdf5/files/CVE-2025-6857.patch

Comments

patchtest@automation.yoctoproject.org April 17, 2026, 8:45 a.m. UTC | #1
Thank you for your submission. Patchtest identified one
or more issues with the patch. Please see the log below for
more information:

---
Testing patch /home/patchtest/share/mboxes/oe-meta-oe-scarthgap-v3-03-11-hdf5-fix-CVE-2025-6857.patch

FAIL: test target mailing list: Series sent to the wrong mailing list or some patches from the series correspond to different mailing lists (test_mbox.TestMbox.test_target_mailing_list)

PASS: test CVE tag format (test_patch.TestPatch.test_cve_tag_format)
PASS: test Signed-off-by presence (test_mbox.TestMbox.test_signed_off_by_presence)
PASS: test Signed-off-by presence (test_patch.TestPatch.test_signed_off_by_presence)
PASS: test Upstream-Status presence (test_patch.TestPatch.test_upstream_status_presence_format)
PASS: test author valid (test_mbox.TestMbox.test_author_valid)
PASS: test commit message presence (test_mbox.TestMbox.test_commit_message_presence)
PASS: test commit message user tags (test_mbox.TestMbox.test_commit_message_user_tags)
PASS: test mbox format (test_mbox.TestMbox.test_mbox_format)
PASS: test non-AUH upgrade (test_mbox.TestMbox.test_non_auh_upgrade)
PASS: test shortlog format (test_mbox.TestMbox.test_shortlog_format)
PASS: test shortlog length (test_mbox.TestMbox.test_shortlog_length)

SKIP: pretest pylint: No python related patches, skipping test (test_python_pylint.PyLint.pretest_pylint)
SKIP: test bugzilla entry format: No bug ID found (test_mbox.TestMbox.test_bugzilla_entry_format)
SKIP: test pylint: No python related patches, skipping test (test_python_pylint.PyLint.test_pylint)
SKIP: test series merge on head: Merge test is disabled for now (test_mbox.TestMbox.test_series_merge_on_head)

---

Please address the issues identified and
submit a new revision of the patch, or alternatively, reply to this
email with an explanation of why the patch should be accepted. If you
believe these results are due to an error in patchtest, please submit a
bug at https://bugzilla.yoctoproject.org/ (use the 'Patchtest' category
under 'Yocto Project Subprojects'). For more information on specific
failures, see: https://wiki.yoctoproject.org/wiki/Patchtest. Thank
you!
diff mbox series

Patch

diff --git a/meta-oe/recipes-support/hdf5/files/CVE-2025-6857.patch b/meta-oe/recipes-support/hdf5/files/CVE-2025-6857.patch
new file mode 100644
index 0000000000..cc1301fb94
--- /dev/null
+++ b/meta-oe/recipes-support/hdf5/files/CVE-2025-6857.patch
@@ -0,0 +1,255 @@ 
+From eb3af284cc0ac8c758c65f492fc693ed50539592 Mon Sep 17 00:00:00 2001
+From: Libo Chen <libo.chen.cn@windriver.com>
+Date: Thu, 29 Jan 2026 13:59:39 +0800
+Subject: [PATCH] Fix CVE-2025-6857
+
+Add additional checks for v1 B-tree corruption
+
+An HDF5 file had a corrupted v1 B-tree that would result in a stack overflow when performing a lookup on it. This has been fixed with additional integrity checks.
+
+CVE: CVE-2025-6857
+
+Upstream-Status: Backport [https://github.com/HDFGroup/hdf5/commit/a8ceb1d95bb997f548c1129363dad53c18540096]
+
+In addition to the upstream backport, this patch includes two adaptation 
+changes for HDF5 1.14.4. First, the H5B_UNKNOWN_NODELEVEL macro and the 
+exp_level field are introduced in H5Bpkg.h, as these do not exist in 1.14.4 
+due to differences with the 2.0.0 codebase. Second, the 
+"cache_udata.exp_level = H5B_UNKNOWN_NODELEVEL" statements are added in H5B_* 
+functions to initialize the new field.
+
+Signed-off-by: Libo Chen <libo.chen.cn@windriver.com>
+---
+ src/H5B.c    | 92 +++++++++++++++++++++++++++++++++++++++++++---------
+ src/H5Bpkg.h |  6 ++++
+ 2 files changed, 83 insertions(+), 15 deletions(-)
+
+diff --git a/src/H5B.c b/src/H5B.c
+index 5a7a238..4efa679 100644
+--- a/src/H5B.c
++++ b/src/H5B.c
+@@ -140,6 +140,8 @@ typedef struct H5B_ins_ud_t {
+ /********************/
+ /* Local Prototypes */
+ /********************/
++static herr_t    H5B_find_helper(H5F_t *f, const H5B_class_t *type, haddr_t addr, int exp_level, bool *found,
++                                 void *udata);
+ static H5B_ins_t H5B__insert_helper(H5F_t *f, H5B_ins_ud_t *bt_ud, const H5B_class_t *type, uint8_t *lt_key,
+                                     bool *lt_key_changed, uint8_t *md_key, void *udata, uint8_t *rt_key,
+                                     bool *rt_key_changed, H5B_ins_ud_t *split_bt_ud /*out*/);
+@@ -252,26 +254,67 @@ done:
+ } /* end H5B_create() */
+ 
+ /*-------------------------------------------------------------------------
+- * Function:	H5B_find
++ * Function:    H5B_find
+  *
+- * Purpose:	Locate the specified information in a B-tree and return
+- *		that information by filling in fields of the caller-supplied
+- *		UDATA pointer depending on the type of leaf node
+- *		requested.  The UDATA can point to additional data passed
+- *		to the key comparison function.
++ * Purpose:     Locate the specified information in a B-tree and return
++ *              that information by filling in fields of the
++ *              caller-supplied UDATA pointer depending on the type of leaf
++ *              node requested.  The UDATA can point to additional data
++ *              passed to the key comparison function.
+  *
+- * Note:	This function does not follow the left/right sibling
+- *		pointers since it assumes that all nodes can be reached
+- *		from the parent node.
++ * Note:        This function does not follow the left/right sibling
++ *              pointers since it assumes that all nodes can be reached
++ *              from the parent node.
+  *
+- * Return:	Non-negative (true/false) on success (if found, values returned
+- *              through the UDATA argument). Negative on failure (if not found,
+- *              UDATA is undefined).
++ * Return:      Non-negative (true/false) on success (if found, values
++ *              returned through the UDATA argument). Negative on failure
++ *              (if not found, UDATA is undefined).
+  *
+  *-------------------------------------------------------------------------
+  */
+ herr_t
+ H5B_find(H5F_t *f, const H5B_class_t *type, haddr_t addr, bool *found, void *udata)
++{
++    herr_t ret_value = SUCCEED;
++
++    FUNC_ENTER_NOAPI(FAIL)
++
++    /*
++     * Check arguments.
++     */
++    assert(f);
++    assert(type);
++    assert(type->decode);
++    assert(type->cmp3);
++    assert(type->found);
++    assert(H5_addr_defined(addr));
++
++    if ((ret_value = H5B_find_helper(f, type, addr, H5B_UNKNOWN_NODELEVEL, found, udata)) < 0)
++        HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "can't lookup key");
++
++done:
++    FUNC_LEAVE_NOAPI(ret_value)
++} /* end H5B_find() */
++
++/*-------------------------------------------------------------------------
++ * Function:    H5B_find_helper
++ *
++ * Purpose:     Recursive helper routine for H5B_find used to track node
++ *              levels and attempt to detect B-tree corruption during
++ *              lookups.
++ *
++ * Note:        This function does not follow the left/right sibling
++ *              pointers since it assumes that all nodes can be reached
++ *              from the parent node.
++ *
++ * Return:      Non-negative on success (if found, values returned through
++ *              the UDATA argument). Negative on failure (if not found,
++ *              UDATA is undefined).
++ *
++ *-------------------------------------------------------------------------
++ */
++static herr_t
++H5B_find_helper(H5F_t *f, const H5B_class_t *type, haddr_t addr, int exp_level, bool *found, void *udata)
+ {
+     H5B_t         *bt = NULL;
+     H5UC_t        *rc_shared;           /* Ref-counted shared info */
+@@ -281,7 +324,7 @@ H5B_find(H5F_t *f, const H5B_class_t *type, haddr_t addr, bool *found, void *uda
+     int            cmp       = 1;       /* Key comparison value */
+     herr_t         ret_value = SUCCEED; /* Return value */
+ 
+-    FUNC_ENTER_NOAPI(FAIL)
++    FUNC_ENTER_NOAPI_NOINIT
+ 
+     /*
+      * Check arguments.
+@@ -306,6 +349,7 @@ H5B_find(H5F_t *f, const H5B_class_t *type, haddr_t addr, bool *found, void *uda
+     cache_udata.f         = f;
+     cache_udata.type      = type;
+     cache_udata.rc_shared = rc_shared;
++    cache_udata.exp_level = exp_level;
+     if (NULL == (bt = (H5B_t *)H5AC_protect(f, H5AC_BT, addr, &cache_udata, H5AC__READ_ONLY_FLAG)))
+         HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree node");
+ 
+@@ -329,7 +373,17 @@ H5B_find(H5F_t *f, const H5B_class_t *type, haddr_t addr, bool *found, void *uda
+         assert(idx < bt->nchildren);
+ 
+         if (bt->level > 0) {
+-            if ((ret_value = H5B_find(f, type, bt->child[idx], found, udata)) < 0)
++            /* Sanity check to catch the case where the current node points to
++             * itself and the current node was loaded with an expected node level
++             * of H5B_UNKNOWN_NODELEVEL, thus bypassing the expected node level
++             * check during deserialization and in the future if the node was
++             * cached.
++             */
++            if (bt->child[idx] == addr)
++                HGOTO_ERROR(H5E_BTREE, H5E_BADVALUE, FAIL, "cyclic B-tree detected");
++
++            if ((ret_value = H5B_find_helper(f, type, bt->child[idx], (int)(bt->level - 1), found, udata)) <
++                0)
+                 HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "can't lookup key in subtree");
+         } /* end if */
+         else {
+@@ -343,7 +397,7 @@ done:
+         HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release node");
+ 
+     FUNC_LEAVE_NOAPI(ret_value)
+-} /* end H5B_find() */
++} /* end H5B_find_helper() */
+ 
+ /*-------------------------------------------------------------------------
+  * Function:	H5B__split
+@@ -425,6 +479,7 @@ H5B__split(H5F_t *f, H5B_ins_ud_t *bt_ud, unsigned idx, void *udata, H5B_ins_ud_
+     cache_udata.f         = f;
+     cache_udata.type      = shared->type;
+     cache_udata.rc_shared = bt_ud->bt->rc_shared;
++    cache_udata.exp_level = H5B_UNKNOWN_NODELEVEL;
+     if (NULL == (split_bt_ud->bt =
+                      (H5B_t *)H5AC_protect(f, H5AC_BT, split_bt_ud->addr, &cache_udata, H5AC__NO_FLAGS_SET)))
+         HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree");
+@@ -532,6 +587,7 @@ H5B_insert(H5F_t *f, const H5B_class_t *type, haddr_t addr, void *udata)
+     cache_udata.f         = f;
+     cache_udata.type      = type;
+     cache_udata.rc_shared = rc_shared;
++    cache_udata.exp_level = H5B_UNKNOWN_NODELEVEL;
+     bt_ud.addr            = addr;
+     if (NULL == (bt_ud.bt = (H5B_t *)H5AC_protect(f, H5AC_BT, addr, &cache_udata, H5AC__NO_FLAGS_SET)))
+         HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to locate root of B-tree");
+@@ -789,6 +845,7 @@ H5B__insert_helper(H5F_t *f, H5B_ins_ud_t *bt_ud, const H5B_class_t *type, uint8
+     cache_udata.f         = f;
+     cache_udata.type      = type;
+     cache_udata.rc_shared = rc_shared;
++    cache_udata.exp_level = H5B_UNKNOWN_NODELEVEL;
+ 
+     if (0 == bt->nchildren) {
+         /*
+@@ -1077,6 +1134,7 @@ H5B__iterate_helper(H5F_t *f, const H5B_class_t *type, haddr_t addr, H5B_operato
+     cache_udata.f         = f;
+     cache_udata.type      = type;
+     cache_udata.rc_shared = rc_shared;
++    cache_udata.exp_level = H5B_UNKNOWN_NODELEVEL;
+     if (NULL == (bt = (H5B_t *)H5AC_protect(f, H5AC_BT, addr, &cache_udata, H5AC__READ_ONLY_FLAG)))
+         HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, H5_ITER_ERROR, "unable to load B-tree node");
+ 
+@@ -1190,6 +1248,7 @@ H5B__remove_helper(H5F_t *f, haddr_t addr, const H5B_class_t *type, int level, u
+     cache_udata.f         = f;
+     cache_udata.type      = type;
+     cache_udata.rc_shared = rc_shared;
++    cache_udata.exp_level = H5B_UNKNOWN_NODELEVEL;
+     if (NULL == (bt = (H5B_t *)H5AC_protect(f, H5AC_BT, addr, &cache_udata, H5AC__NO_FLAGS_SET)))
+         HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, H5B_INS_ERROR, "unable to load B-tree node");
+ 
+@@ -1542,6 +1601,7 @@ H5B_delete(H5F_t *f, const H5B_class_t *type, haddr_t addr, void *udata)
+     cache_udata.f         = f;
+     cache_udata.type      = type;
+     cache_udata.rc_shared = rc_shared;
++    cache_udata.exp_level = H5B_UNKNOWN_NODELEVEL;
+     if (NULL == (bt = (H5B_t *)H5AC_protect(f, H5AC_BT, addr, &cache_udata, H5AC__NO_FLAGS_SET)))
+         HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree node");
+ 
+@@ -1782,6 +1842,7 @@ H5B__get_info_helper(H5F_t *f, const H5B_class_t *type, haddr_t addr, const H5B_
+     cache_udata.f         = f;
+     cache_udata.type      = type;
+     cache_udata.rc_shared = rc_shared;
++    cache_udata.exp_level = H5B_UNKNOWN_NODELEVEL;
+     if (NULL == (bt = (H5B_t *)H5AC_protect(f, H5AC_BT, addr, &cache_udata, H5AC__READ_ONLY_FLAG)))
+         HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree node");
+ 
+@@ -1923,6 +1984,7 @@ H5B_valid(H5F_t *f, const H5B_class_t *type, haddr_t addr)
+     cache_udata.f         = f;
+     cache_udata.type      = type;
+     cache_udata.rc_shared = rc_shared;
++    cache_udata.exp_level = H5B_UNKNOWN_NODELEVEL;
+     if (NULL == (bt = (H5B_t *)H5AC_protect(f, H5AC_BT, addr, &cache_udata, H5AC__READ_ONLY_FLAG)))
+         HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree node");
+ 
+diff --git a/src/H5Bpkg.h b/src/H5Bpkg.h
+index d1ad647..f75e857 100644
+--- a/src/H5Bpkg.h
++++ b/src/H5Bpkg.h
+@@ -39,6 +39,11 @@
+ /* # of bits for node level: 1 byte */
+ #define LEVEL_BITS 8
+ 
++/* Indicates that the level of the current node is unknown.  When the level
++ * is known, it can be used to detect corrupted level during decoding
++ */
++#define H5B_UNKNOWN_NODELEVEL -1
++
+ /****************************/
+ /* Package Private Typedefs */
+ /****************************/
+@@ -60,6 +65,7 @@ typedef struct H5B_t {
+ typedef struct H5B_cache_ud_t {
+     H5F_t                    *f;         /* File that B-tree node is within */
+     const struct H5B_class_t *type;      /* Type of tree */
++    int                       exp_level; /* Expected level of the current node */
+     H5UC_t                   *rc_shared; /* Ref-counted shared info */
+ } H5B_cache_ud_t;
+ 
+-- 
+2.34.1
+
diff --git a/meta-oe/recipes-support/hdf5/hdf5_1.14.4-3.bb b/meta-oe/recipes-support/hdf5/hdf5_1.14.4-3.bb
index b31a8d8cfa..816bd752a1 100644
--- a/meta-oe/recipes-support/hdf5/hdf5_1.14.4-3.bb
+++ b/meta-oe/recipes-support/hdf5/hdf5_1.14.4-3.bb
@@ -29,6 +29,7 @@  SRC_URI = " \
     file://CVE-2025-44905.patch \
     file://CVE-2025-2309.patch \
     file://CVE-2025-2308.patch \
+    file://CVE-2025-6857.patch \
 "
 SRC_URI[sha256sum] = "019ac451d9e1cf89c0482ba2a06f07a46166caf23f60fea5ef3c37724a318e03"