Version in base suite: 2023.01+dfsg-2+deb12u2 Base version: u-boot_2023.01+dfsg-2+deb12u2 Target version: u-boot_2023.01+dfsg-2+deb12u3 Base file: /srv/ftp-master.debian.org/ftp/pool/main/u/u-boot/u-boot_2023.01+dfsg-2+deb12u2.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/u/u-boot/u-boot_2023.01+dfsg-2+deb12u3.dsc changelog | 12 + control | 2 patches/CVE-2024-42040.patch | 48 +++++ patches/CVE-2026-46728-1.patch | 51 +++++ patches/CVE-2026-46728-2.patch | 360 +++++++++++++++++++++++++++++++++++++++++ patches/CVE-2026-46728-3.patch | 134 +++++++++++++++ patches/series | 16 - targets.mk | 7 8 files changed, 610 insertions(+), 20 deletions(-) dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpem4xvrw6/u-boot_2023.01+dfsg-2+deb12u2.dsc: no acceptable signature found dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpem4xvrw6/u-boot_2023.01+dfsg-2+deb12u3.dsc: no acceptable signature found diff -Nru u-boot-2023.01+dfsg/debian/changelog u-boot-2023.01+dfsg/debian/changelog --- u-boot-2023.01+dfsg/debian/changelog 2025-10-01 00:06:28.000000000 +0000 +++ u-boot-2023.01+dfsg/debian/changelog 2026-06-22 08:38:07.000000000 +0000 @@ -1,3 +1,15 @@ +u-boot (2023.01+dfsg-2+deb12u3) bookworm-security; urgency=high + + * Non-maintainer upload by the LTS Team. + * CVE-2024-42040: buffer overread vulnerability in the DHCP implementation. + (Closes: #1081557) + * CVE-2026-46728: mishandles use of unit addresses in a FIT. + (Closes: #1136954) + * Remove avr32 arch support removed in dpkg 1.22.0 (Closes: #1056750) + - now also leads to dak rejecting uploads even for older suites + + -- Andreas Henriksson Mon, 22 Jun 2026 10:38:07 +0200 + u-boot (2023.01+dfsg-2+deb12u2) bookworm; urgency=medium * Non-maintainer upload by the Debian LTS team. diff -Nru u-boot-2023.01+dfsg/debian/control u-boot-2023.01+dfsg/debian/control --- u-boot-2023.01+dfsg/debian/control 2025-10-01 00:06:28.000000000 +0000 +++ u-boot-2023.01+dfsg/debian/control 2026-06-22 08:37:38.000000000 +0000 @@ -44,7 +44,7 @@ Vcs-Git: https://salsa.debian.org/debian/u-boot.git Package: u-boot -Architecture: armel avr32 sh4 +Architecture: armel sh4 Multi-Arch: same Depends: ${misc:Depends}, Description: A boot loader for embedded systems diff -Nru u-boot-2023.01+dfsg/debian/patches/CVE-2024-42040.patch u-boot-2023.01+dfsg/debian/patches/CVE-2024-42040.patch --- u-boot-2023.01+dfsg/debian/patches/CVE-2024-42040.patch 1970-01-01 00:00:00.000000000 +0000 +++ u-boot-2023.01+dfsg/debian/patches/CVE-2024-42040.patch 2026-06-22 08:36:22.000000000 +0000 @@ -0,0 +1,48 @@ +From: Paul HENRYS +Date: Thu, 9 Oct 2025 17:43:28 +0200 +Subject: net: bootp: Prevent buffer overflow to avoid leaking the RAM content + +CVE-2024-42040 describes a possible buffer overflow when calling +bootp_process_vendor() in bootp_handler() since the total length +of the packet is passed to bootp_process_vendor() without being +reduced to len-(offsetof(struct bootp_hdr,bp_vend)+4). + +The packet length is also checked against its minimum size to avoid +reading data from struct bootp_hdr outside of the packet length. + +Signed-off-by: Paul HENRYS +Signed-off-by: Philippe Reynes +(cherry picked from commit 81e5708cc2c865df606e49aed5415adb2a662171) +--- + net/bootp.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/net/bootp.c b/net/bootp.c +index 7ac0093..ddb4983 100644 +--- a/net/bootp.c ++++ b/net/bootp.c +@@ -364,6 +364,14 @@ static void bootp_handler(uchar *pkt, unsigned dest, struct in_addr sip, + debug("got BOOTP packet (src=%d, dst=%d, len=%d want_len=%zu)\n", + src, dest, len, sizeof(struct bootp_hdr)); + ++ /* Check the minimum size of a BOOTP packet is respected. ++ * A BOOTP packet is between 300 bytes and 576 bytes big ++ */ ++ if (len < offsetof(struct bootp_hdr, bp_vend) + 64) { ++ printf("Error: got an invalid BOOTP packet (len=%u)\n", len); ++ return; ++ } ++ + bp = (struct bootp_hdr *)pkt; + + /* Filter out pkts we don't want */ +@@ -381,7 +389,8 @@ static void bootp_handler(uchar *pkt, unsigned dest, struct in_addr sip, + + /* Retrieve extended information (we must parse the vendor area) */ + if (net_read_u32((u32 *)&bp->bp_vend[0]) == htonl(BOOTP_VENDOR_MAGIC)) +- bootp_process_vendor((uchar *)&bp->bp_vend[4], len); ++ bootp_process_vendor((uchar *)&bp->bp_vend[4], len - ++ (offsetof(struct bootp_hdr, bp_vend) + 4)); + + net_set_timeout_handler(0, (thand_f *)0); + bootstage_mark_name(BOOTSTAGE_ID_BOOTP_STOP, "bootp_stop"); diff -Nru u-boot-2023.01+dfsg/debian/patches/CVE-2026-46728-1.patch u-boot-2023.01+dfsg/debian/patches/CVE-2026-46728-1.patch --- u-boot-2023.01+dfsg/debian/patches/CVE-2026-46728-1.patch 1970-01-01 00:00:00.000000000 +0000 +++ u-boot-2023.01+dfsg/debian/patches/CVE-2026-46728-1.patch 2026-06-22 08:36:22.000000000 +0000 @@ -0,0 +1,51 @@ +From: Quentin Schulz +Date: Wed, 3 Dec 2025 17:19:34 +0100 +Subject: boot/fit: declare (and use) new constant for conf's compatible prop + +Fit conf node may have a compatible property[1] which stores the root +compatible of the first blob in the fdt property of the node. This can +be used to automatically select the proper conf node based on the +compatible from the running U-Boot (matching the former's compatible +with the latter)[2]. + +This adds (and uses) this constant for FIT node parsing. + +Note that this property may also appear in fpga image nodes[3] but that +isn't done in this commit. + +[1] https://fitspec.osfw.foundation/#optional-properties compatible paragraph +[2] https://fitspec.osfw.foundation/#select-a-configuration-to-boot +[3] https://fitspec.osfw.foundation/#images-node 2.3.2 Conditionally mandatory property + +Signed-off-by: Quentin Schulz +(cherry picked from commit 3059eb0c27dd1b4a40a06bda4a47e10246185aca) +--- + boot/image-fit.c | 2 +- + include/image.h | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/boot/image-fit.c b/boot/image-fit.c +index 3cc556b..56bf484 100644 +--- a/boot/image-fit.c ++++ b/boot/image-fit.c +@@ -1760,7 +1760,7 @@ int fit_conf_find_compat(const void *fit, const void *fdt) + continue; + + /* If there's a compat property in the config node, use that. */ +- if (fdt_getprop(fit, noffset, "compatible", NULL)) { ++ if (fdt_getprop(fit, noffset, FIT_COMPAT_PROP, NULL)) { + fdt = fit; /* search in FIT image */ + compat_noffset = noffset; /* search under config node */ + } else { /* Otherwise extract it from the kernel FDT. */ +diff --git a/include/image.h b/include/image.h +index 6f21daf..3192409 100644 +--- a/include/image.h ++++ b/include/image.h +@@ -1032,6 +1032,7 @@ int booti_setup(ulong image, ulong *relocated_addr, ulong *size, + #define FIT_FIRMWARE_PROP "firmware" + #define FIT_STANDALONE_PROP "standalone" + #define FIT_PHASE_PROP "phase" ++#define FIT_COMPAT_PROP "compatible" + + #define FIT_MAX_HASH_LEN HASH_MAX_DIGEST_SIZE + diff -Nru u-boot-2023.01+dfsg/debian/patches/CVE-2026-46728-2.patch u-boot-2023.01+dfsg/debian/patches/CVE-2026-46728-2.patch --- u-boot-2023.01+dfsg/debian/patches/CVE-2026-46728-2.patch 1970-01-01 00:00:00.000000000 +0000 +++ u-boot-2023.01+dfsg/debian/patches/CVE-2026-46728-2.patch 2026-06-22 08:36:22.000000000 +0000 @@ -0,0 +1,360 @@ +From: Simon Glass +Date: Thu, 5 Mar 2026 18:20:09 -0700 +Subject: boot: Add fit_config_get_hash_list() to build signed node list + +The hashed-nodes property in a FIT signature node lists which FDT paths +are included in the signature hash. It is intended as a hint so should +not be used for verification. + +Add a function to build the node list from scratch by iterating the +configuration's image references. Skip properties known not to be image +references. For each image, collect the path plus all hash and cipher +subnodes. + +Use the new function in fit_config_check_sig() instead of reading +'hashed-nodes'. + +Update the test_vboot kernel@ test case: fit_check_sign now catches the +attack at signature-verification time (the @-suffixed node is hashed +instead of the real one, causing a mismatch) rather than at +fit_check_format() time. + +Update the docs to cover this. The FIT spec can be updated separately. + +Signed-off-by: Simon Glass +Closes: https://lore.kernel.org/u-boot/20260302220937.3682128-1-trini@konsulko.com/ +Reported-by: Apple Security Engineering and Architecture (SEAR) +Tested-by: Tom Rini +(cherry picked from commit 2092322b31cc8b1f8c9e2e238d1043ae0637b241) +--- + boot/image-fit-sig.c | 227 ++++++++++++++++++++++++++++++++++--------- + doc/uImage.FIT/signature.txt | 20 ++-- + test/py/tests/test_vboot.py | 10 +- + 3 files changed, 203 insertions(+), 54 deletions(-) + +diff --git a/boot/image-fit-sig.c b/boot/image-fit-sig.c +index 1236989..11674f5 100644 +--- a/boot/image-fit-sig.c ++++ b/boot/image-fit-sig.c +@@ -19,6 +19,7 @@ DECLARE_GLOBAL_DATA_PTR; + #include + + #define IMAGE_MAX_HASHED_NODES 100 ++#define FIT_MAX_HASH_PATH_BUF 4096 + + /** + * fit_region_make_list() - Make a list of image regions +@@ -225,6 +226,179 @@ int fit_image_verify_required_sigs(const void *fit, int image_noffset, + return 0; + } + ++/** ++ * fit_config_add_hash() - Add hash nodes for one image to the node list ++ * ++ * Adds the image path, all its hash-* subnode paths, and its cipher ++ * subnode path (if present) to the packed buffer. ++ * ++ * @fit: FIT blob ++ * @image_noffset: Image node offset (e.g. /images/kernel-1) ++ * @node_inc: Array of path pointers to fill ++ * @count: Pointer to current count (updated on return) ++ * @max_nodes: Maximum entries in @node_inc ++ * @buf: Buffer for packed path strings ++ * @buf_used: Pointer to bytes used in @buf (updated on return) ++ * @buf_len: Total size of @buf ++ * Return: 0 on success, -ve on error ++ */ ++static int fit_config_add_hash(const void *fit, int image_noffset, ++ char **node_inc, int *count, int max_nodes, ++ char *buf, int *buf_used, int buf_len) ++{ ++ int noffset, hash_count, ret, len; ++ ++ if (*count >= max_nodes) ++ return -ENOSPC; ++ ++ ret = fdt_get_path(fit, image_noffset, buf + *buf_used, ++ buf_len - *buf_used); ++ if (ret < 0) ++ return -ENOENT; ++ len = strlen(buf + *buf_used) + 1; ++ node_inc[(*count)++] = buf + *buf_used; ++ *buf_used += len; ++ ++ /* Add all this image's hash subnodes */ ++ hash_count = 0; ++ for (noffset = fdt_first_subnode(fit, image_noffset); ++ noffset >= 0; ++ noffset = fdt_next_subnode(fit, noffset)) { ++ const char *name = fit_get_name(fit, noffset, NULL); ++ ++ if (strncmp(name, FIT_HASH_NODENAME, ++ strlen(FIT_HASH_NODENAME))) ++ continue; ++ if (*count >= max_nodes) ++ return -ENOSPC; ++ ret = fdt_get_path(fit, noffset, buf + *buf_used, ++ buf_len - *buf_used); ++ if (ret < 0) ++ return -ENOENT; ++ len = strlen(buf + *buf_used) + 1; ++ node_inc[(*count)++] = buf + *buf_used; ++ *buf_used += len; ++ hash_count++; ++ } ++ ++ if (!hash_count) { ++ printf("No hash nodes in image '%s'\n", ++ fdt_get_name(fit, image_noffset, NULL)); ++ return -ENOMSG; ++ } ++ ++ /* Add this image's cipher node if present */ ++ noffset = fdt_subnode_offset(fit, image_noffset, FIT_CIPHER_NODENAME); ++ if (noffset != -FDT_ERR_NOTFOUND) { ++ if (noffset < 0) ++ return -EIO; ++ if (*count >= max_nodes) ++ return -ENOSPC; ++ ret = fdt_get_path(fit, noffset, buf + *buf_used, ++ buf_len - *buf_used); ++ if (ret < 0) ++ return -ENOENT; ++ len = strlen(buf + *buf_used) + 1; ++ node_inc[(*count)++] = buf + *buf_used; ++ *buf_used += len; ++ } ++ ++ return 0; ++} ++ ++/** ++ * fit_config_get_hash_list() - Build the list of nodes to hash ++ * ++ * Works through every image referenced by the configuration and collects the ++ * node paths: root + config + all referenced images with their hash and ++ * cipher subnodes. ++ * ++ * Properties known not to be image references (description, compatible, ++ * default, load-only) are skipped, so any new image type is covered by default. ++ * ++ * @fit: FIT blob ++ * @conf_noffset: Configuration node offset ++ * @node_inc: Array to fill with path string pointers ++ * @max_nodes: Size of @node_inc array ++ * @buf: Buffer for packed null-terminated path strings ++ * @buf_len: Size of @buf ++ * Return: number of entries in @node_inc, or -ve on error ++ */ ++static int fit_config_get_hash_list(const void *fit, int conf_noffset, ++ char **node_inc, int max_nodes, ++ char *buf, int buf_len) ++{ ++ const char *conf_name; ++ int image_count; ++ int prop_offset; ++ int used = 0; ++ int count = 0; ++ int ret, len; ++ ++ conf_name = fit_get_name(fit, conf_noffset, NULL); ++ ++ /* Always include the root node and the configuration node */ ++ if (max_nodes < 2) ++ return -ENOSPC; ++ ++ len = 2; /* "/" + nul */ ++ if (len > buf_len) ++ return -ENOSPC; ++ strcpy(buf, "/"); ++ node_inc[count++] = buf; ++ used += len; ++ ++ len = snprintf(buf + used, buf_len - used, "%s/%s", FIT_CONFS_PATH, ++ conf_name) + 1; ++ if (used + len > buf_len) ++ return -ENOSPC; ++ node_inc[count++] = buf + used; ++ used += len; ++ ++ /* Process each image referenced by the config */ ++ image_count = 0; ++ fdt_for_each_property_offset(prop_offset, fit, conf_noffset) { ++ const char *prop_name; ++ int img_count, i; ++ ++ fdt_getprop_by_offset(fit, prop_offset, &prop_name, NULL); ++ if (!prop_name) ++ continue; ++ ++ /* Skip properties that are not image references */ ++ if (!strcmp(prop_name, FIT_DESC_PROP) || ++ !strcmp(prop_name, FIT_COMPAT_PROP) || ++ !strcmp(prop_name, FIT_DEFAULT_PROP)) ++ continue; ++ ++ img_count = fdt_stringlist_count(fit, conf_noffset, prop_name); ++ for (i = 0; i < img_count; i++) { ++ int noffset; ++ ++ noffset = fit_conf_get_prop_node_index(fit, ++ conf_noffset, ++ prop_name, i); ++ if (noffset < 0) ++ continue; ++ ++ ret = fit_config_add_hash(fit, noffset, node_inc, ++ &count, max_nodes, buf, &used, ++ buf_len); ++ if (ret < 0) ++ return ret; ++ ++ image_count++; ++ } ++ } ++ ++ if (!image_count) { ++ printf("No images in config '%s'\n", conf_name); ++ return -ENOMSG; ++ } ++ ++ return count; ++} ++ + /** + * fit_config_check_sig() - Check the signature of a config + * +@@ -265,20 +439,16 @@ static int fit_config_check_sig(const void *fit, int noffset, int conf_noffset, + FIT_DATA_POSITION_PROP, + FIT_DATA_OFFSET_PROP, + }; +- +- const char *prop, *end, *name; ++ char *node_inc[IMAGE_MAX_HASHED_NODES]; ++ char hash_buf[FIT_MAX_HASH_PATH_BUF]; + struct image_sign_info info; + const uint32_t *strings; +- const char *config_name; + uint8_t *fit_value; + int fit_value_len; +- bool found_config; + int max_regions; +- int i, prop_len; + char path[200]; + int count; + +- config_name = fit_get_name(fit, conf_noffset, NULL); + debug("%s: fdt=%p, conf='%s', sig='%s'\n", __func__, key_blob, + fit_get_name(fit, noffset, NULL), + fit_get_name(key_blob, required_keynode, NULL)); +@@ -293,45 +463,12 @@ static int fit_config_check_sig(const void *fit, int noffset, int conf_noffset, + return -1; + } + +- /* Count the number of strings in the property */ +- prop = fdt_getprop(fit, noffset, "hashed-nodes", &prop_len); +- end = prop ? prop + prop_len : prop; +- for (name = prop, count = 0; name < end; name++) +- if (!*name) +- count++; +- if (!count) { +- *err_msgp = "Can't get hashed-nodes property"; +- return -1; +- } +- +- if (prop && prop_len > 0 && prop[prop_len - 1] != '\0') { +- *err_msgp = "hashed-nodes property must be null-terminated"; +- return -1; +- } +- +- /* Add a sanity check here since we are using the stack */ +- if (count > IMAGE_MAX_HASHED_NODES) { +- *err_msgp = "Number of hashed nodes exceeds maximum"; +- return -1; +- } +- +- /* Create a list of node names from those strings */ +- char *node_inc[count]; +- +- debug("Hash nodes (%d):\n", count); +- found_config = false; +- for (name = prop, i = 0; name < end; name += strlen(name) + 1, i++) { +- debug(" '%s'\n", name); +- node_inc[i] = (char *)name; +- if (!strncmp(FIT_CONFS_PATH, name, strlen(FIT_CONFS_PATH)) && +- name[sizeof(FIT_CONFS_PATH) - 1] == '/' && +- !strcmp(name + sizeof(FIT_CONFS_PATH), config_name)) { +- debug(" (found config node %s)", config_name); +- found_config = true; +- } +- } +- if (!found_config) { +- *err_msgp = "Selected config not in hashed nodes"; ++ /* Build the node list from the config, ignoring hashed-nodes */ ++ count = fit_config_get_hash_list(fit, conf_noffset, ++ node_inc, IMAGE_MAX_HASHED_NODES, ++ hash_buf, sizeof(hash_buf)); ++ if (count < 0) { ++ *err_msgp = "Failed to build hash node list"; + return -1; + } + +diff --git a/doc/uImage.FIT/signature.txt b/doc/uImage.FIT/signature.txt +index c71280b..7c7534b 100644 +--- a/doc/uImage.FIT/signature.txt ++++ b/doc/uImage.FIT/signature.txt +@@ -385,18 +385,26 @@ meantime. + Details + ------- + The signature node contains a property ('hashed-nodes') which lists all the +-nodes that the signature was made over. The image is walked in order and each +-tag processed as follows: ++nodes that the signature was made over. The signer (mkimage) writes this ++property as a record of what was included in the hash. During verification, ++however, U-Boot does not read 'hashed-nodes'. Instead it rebuilds the node ++list from the configuration's own image references (kernel, fdt, ramdisk, ++etc.), since 'hashed-nodes' is not itself covered by the signature. The ++rebuilt list always includes the root node, the configuration node, each ++referenced image node and its hash/cipher subnodes. ++ ++The image is walked in order and each tag processed as follows: ++ + - DTB_BEGIN_NODE: The tag and the following name are included in the signature +- if the node or its parent are present in 'hashed-nodes' ++ if the node or its parent are present in the node list + - DTB_END_NODE: The tag is included in the signature if the node or its parent +- are present in 'hashed-nodes' ++ are present in the node list + - DTB_PROPERTY: The tag, the length word, the offset in the string table, and +- the data are all included if the current node is present in 'hashed-nodes' ++ the data are all included if the current node is present in the node list + and the property name is not 'data'. + - DTB_END: The tag is always included in the signature. + - DTB_NOP: The tag is included in the signature if the current node is present +- in 'hashed-nodes' ++ in the node list + + In addition, the signature contains a property 'hashed-strings' which contains + the offset and length in the string table of the strings that are to be +diff --git a/test/py/tests/test_vboot.py b/test/py/tests/test_vboot.py +index e3e7ca4..aec2d54 100644 +--- a/test/py/tests/test_vboot.py ++++ b/test/py/tests/test_vboot.py +@@ -345,10 +345,14 @@ def test_vboot(u_boot_console, name, sha_algo, padding, sign_options, required, + shutil.copyfile(fit, efit) + vboot_evil.add_evil_node(fit, efit, evil_kernel, 'kernel@') + +- msg = 'Signature checking prevents use of unit addresses (@) in nodes' +- util.run_and_log_expect_exception( ++ # fit_check_sign catches this via signature mismatch (the @ ++ # node is hashed instead of the real one) ++ utils.run_and_log_expect_exception( + cons, [fit_check_sign, '-f', efit, '-k', dtb], +- 1, msg) ++ 1, 'Failed to verify required signature') ++ ++ # bootm catches it earlier, at fit_check_format() time ++ msg = 'Signature checking prevents use of unit addresses (@) in nodes' + run_bootm(sha_algo, 'evil kernel@', msg, False, efit) + + # Create a new properly signed fit and replace header bytes diff -Nru u-boot-2023.01+dfsg/debian/patches/CVE-2026-46728-3.patch u-boot-2023.01+dfsg/debian/patches/CVE-2026-46728-3.patch --- u-boot-2023.01+dfsg/debian/patches/CVE-2026-46728-3.patch 1970-01-01 00:00:00.000000000 +0000 +++ u-boot-2023.01+dfsg/debian/patches/CVE-2026-46728-3.patch 2026-06-22 08:36:22.000000000 +0000 @@ -0,0 +1,134 @@ +From: Tom Rini +Date: Wed, 18 Mar 2026 11:02:33 -0600 +Subject: tests: FIT: Add "clone" image attack image test + +Related to the problem resolved with commit 2092322b31cc ("boot: Add +fit_config_get_hash_list() to build signed node list"), add a testcase +for the problem as well. + +Reported-by: Apple Security Engineering and Architecture (SEAR) +Signed-off-by: Tom Rini +(cherry picked from commit a22e9e1b8ec7c96664072d7e629e811c318fb92a) +--- + test/py/tests/test_vboot.py | 10 +++++++ + test/py/tests/vboot_evil.py | 65 +++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 75 insertions(+) + +diff --git a/test/py/tests/test_vboot.py b/test/py/tests/test_vboot.py +index aec2d54..4de0e76 100644 +--- a/test/py/tests/test_vboot.py ++++ b/test/py/tests/test_vboot.py +@@ -355,6 +355,16 @@ def test_vboot(u_boot_console, name, sha_algo, padding, sign_options, required, + msg = 'Signature checking prevents use of unit addresses (@) in nodes' + run_bootm(sha_algo, 'evil kernel@', msg, False, efit) + ++ # Try doing a clone of the images ++ efit = '%stest.evilclone.fit' % tmpdir ++ shutil.copyfile(fit, efit) ++ vboot_evil.add_evil_node(fit, efit, evil_kernel, 'clone') ++ ++ utils.run_and_log_expect_exception( ++ cons, [fit_check_sign, '-f', efit, '-k', dtb], ++ 1, 'Failed to verify required signature') ++ run_bootm(sha_algo, 'evil clone', 'Bad Data Hash', False, efit) ++ + # Create a new properly signed fit and replace header bytes + make_fit('sign-configs-%s%s.its' % (sha_algo, padding)) + sign_fit(sha_algo, sign_options) +diff --git a/test/py/tests/vboot_evil.py b/test/py/tests/vboot_evil.py +index e2b0cd6..5720631 100644 +--- a/test/py/tests/vboot_evil.py ++++ b/test/py/tests/vboot_evil.py +@@ -14,6 +14,7 @@ FDT_END = 0x9 + + FAKE_ROOT_ATTACK = 0 + KERNEL_AT = 1 ++IMAGE_CLONE = 2 + + MAGIC = 0xd00dfeed + +@@ -274,6 +275,66 @@ def get_prop_value(dt_struct, dt_strings, prop_path): + + return tag_data + ++def image_clone_attack(dt_struct, dt_strings, kernel_content, kernel_hash): ++ # retrieve the default configuration name ++ default_conf_name = get_prop_value( ++ dt_struct, dt_strings, '/configurations/default') ++ default_conf_name = str(default_conf_name[:-1], 'utf-8') ++ ++ conf_path = '/configurations/' + default_conf_name ++ ++ # fetch the loaded kernel name from the default configuration ++ loaded_kernel = get_prop_value(dt_struct, dt_strings, conf_path + '/kernel') ++ ++ loaded_kernel = str(loaded_kernel[:-1], 'utf-8') ++ ++ # since this is the last child in images! ++ loaded_fdt_name = get_prop_value(dt_struct, dt_strings, conf_path + '/fdt') ++ ++ loaded_fdt_name = str(loaded_fdt_name[:-1], 'utf-8') ++ ++ # determine boundaries of the images ++ (img_node_start, img_node_end) = (determine_offset( ++ dt_struct, dt_strings, '/images')) ++ if img_node_start is None and img_node_end is None: ++ print('Fatal error, unable to find images node') ++ sys.exit() ++ ++ # copy the images node ++ img_node_copy = dt_struct[img_node_start:img_node_end] ++ ++ # create an additional empty node ++ empty_node = struct.pack('>I', FDT_BEGIN_NODE) + b"EMPTYNO\0" + struct.pack('>I', FDT_END_NODE) ++ # right before the end, we add it! ++ img_node_copy = img_node_copy[:-4] + empty_node + img_node_copy[-4:] ++ ++ # insert the copy inside the tree ++ dt_struct = dt_struct[:img_node_end-4] + \ ++ img_node_copy + empty_node + dt_struct[img_node_end-4:] ++ ++ # change the content of the kernel being loaded ++ dt_struct = change_property_value( ++ dt_struct, dt_strings, '/images/' + loaded_kernel + '/data', kernel_content) ++ ++ # change the content of the kernel being loaded ++ dt_struct = change_property_value( ++ dt_struct, dt_strings, '/images/' + loaded_kernel + '/hash-1/value', kernel_hash) ++ ++ # finally, the main bug: change the hashed nodes to use the images clone instead! ++ hashed_nodes: bytes = get_prop_value(dt_struct, dt_strings, conf_path + '/signature/hashed-nodes') ++ print(f"got hashed nodes: {hashed_nodes}") ++ nodes = hashed_nodes.split(b"\0") ++ patched_nodes = [] ++ for node in nodes: ++ new_node = node ++ if node.startswith(b"/images/"): ++ # reparent the node ++ new_node = b"/images" + node ++ patched_nodes.append(new_node) ++ hashed_nodes = b"\0".join(patched_nodes) ++ dt_struct = change_property_value( ++ dt_struct, dt_strings, conf_path + '/signature/hashed-nodes', hashed_nodes) ++ return dt_struct + + def kernel_at_attack(dt_struct, dt_strings, kernel_content, kernel_hash): + """Conduct the kernel@ attack +@@ -419,6 +480,8 @@ def add_evil_node(in_fname, out_fname, kernel_fname, attack): + attack = FAKE_ROOT_ATTACK + elif attack == 'kernel@': + attack = KERNEL_AT ++ elif attack == 'clone': ++ attack = IMAGE_CLONE + else: + raise ValueError('Unknown attack name!') + +@@ -455,6 +518,8 @@ def add_evil_node(in_fname, out_fname, kernel_fname, attack): + elif attack == KERNEL_AT: + dt_struct = kernel_at_attack(dt_struct, dt_strings, kernel_content, + hash_digest) ++ elif attack == IMAGE_CLONE: ++ dt_struct = image_clone_attack(dt_struct, dt_strings, kernel_content, hash_digest) + + # now rebuild the new file + size_dt_strings = len(dt_strings) diff -Nru u-boot-2023.01+dfsg/debian/patches/series u-boot-2023.01+dfsg/debian/patches/series --- u-boot-2023.01+dfsg/debian/patches/series 2025-10-01 00:06:28.000000000 +0000 +++ u-boot-2023.01+dfsg/debian/patches/series 2026-06-22 08:36:22.000000000 +0000 @@ -1,29 +1,17 @@ mx53loco - arndale/board-spl-rule.diff - test-imagetools-test-fixes - exynos/0001-arm-config-fix-default-console-only-to-specify-the-d.patch - riscv64/unmatched-prevent-relocating-initrd-and-fdt.patch - disable-fit-image-tests - rockchip/rockchip-inno-usb.patch rockchip/rockchip-roc-pc-rk3399-Enable-rockchip-efuse-support.patch - qemu/efi-secure-boot.patch - fix-qemu-ppce500-with-binutils-2.38.patch Makefile-Use-relative-paths-for-debugging-symbols.patch - tools-disable-video-logo - riscv64/vbe-Allow-probing-the-VBE-bootmeth-to-fail-in-OS-fixup.patch - upstream/0001-timer-orion-timer-Fix-problem-in-early_init_done.patch - CVE-2024-57254.patch CVE-2024-57255.patch CVE-2024-57256.patch @@ -32,3 +20,7 @@ CVE-2024-57258-2.patch CVE-2024-57258-3.patch CVE-2024-57259.patch +CVE-2024-42040.patch +CVE-2026-46728-1.patch +CVE-2026-46728-2.patch +CVE-2026-46728-3.patch diff -Nru u-boot-2023.01+dfsg/debian/targets.mk u-boot-2023.01+dfsg/debian/targets.mk --- u-boot-2023.01+dfsg/debian/targets.mk 2025-10-01 00:06:28.000000000 +0000 +++ u-boot-2023.01+dfsg/debian/targets.mk 2026-06-22 08:37:38.000000000 +0000 @@ -539,13 +539,6 @@ u-boot-tegra_platforms += jetson-tk1 jetson-tk1_targets := u-boot-tegra.bin uboot.elf -else ifeq (${DEB_HOST_ARCH},avr32) - -# u-boot - - u-boot_platforms += hammerhead - hammerhead_targets := u-boot.img uboot.elf - else ifeq (${DEB_HOST_ARCH},riscv64) # u-boot-sifive