In case MULTI_DTB_FIT_GZIP is enabled, fdtdec_setup() does uncompress
the compressed DTs in uncompress_blob() using gunzip(), which invokes
malloc() internally. The early simple malloc is initialized in board_f
initf_malloc() call, which sets up the early simple malloc limit and
offset pointer in global data. Currently, the initf_malloc() is called
after fdtdec_setup(), which leads to malloc failure in fdtdec_setup()
during the gzip decompression, because the early simple malloc is not
initialized yet.
Call initf_malloc() before fdtdec_setup() to assure fdtdec_setup() can
use malloc() during gzip decompression of the DTs.
The impact of this change on boot time is negligible, because the
initf_malloc() only assigns two fields in global data.
Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
Fixes: 95f4bbd581 ("lib: fdt: Allow LZO and GZIP DT compression in U-Boot")
Reviewed-by: Simon Glass <sjg@chromium.org>
[trini: Update test/py/tests/test_trace.py]
Signed-off-by: Tom Rini <trini@konsulko.com>
Daniel Golle <daniel@makrotopia.org> says:
A signed FIT configuration can delegate the integrity of a (potentially
large) root filesystem image to the kernel's dm-verity instead of having
U-Boot hash the whole payload at boot: the FIT carries a "dm-verity"
subnode with the roothash, salt and block parameters, U-Boot passes the
roothash to Linux through the dm-mod.create bootargs, and dm-verity then
validates the filesystem block by block against it.
For that to be safe the roothash has to be trusted, and in a signed
configuration the only thing that establishes trust is the configuration
signature. The roothash was not covered by it. fit_config_add_hash()
collected the image node, its hash subnodes and its cipher subnode into
the signed region, but not the dm-verity subnode, so the roothash, the
sole integrity anchor for the filesystem, was left unsigned.
The result is a verified-boot bypass for the root filesystem: an
attacker who can rewrite the boot medium can replace the filesystem,
recompute a matching dm-verity tree, write the new roothash into the
unsigned dm-verity subnode, and the configuration signature still
verifies. dm-verity then faithfully validates the malicious filesystem
against the attacker's roothash.
This series closes the gap.
Link: https://lore.kernel.org/r/cover.1785276461.git.daniel@makrotopia.org
A dm-verity protected filesystem image is not hashed by U-Boot; its
integrity is delegated to the kernel, which trusts the roothash taken
from the FIT dm-verity subnode. For that chain of trust to hold, the
roothash (and salt) must be part of the region covered by the
configuration signature, otherwise an attacker can replace both the
filesystem and the roothash while keeping the signature valid.
Add two independent checks of this property:
- test/py/tests/test_fit_verity_sign.py signs a configuration that
references a filesystem image carrying a dm-verity subnode, then
confirms that tampering the roothash or the salt is rejected by
fit_check_sign. A control that tampers a byte known to be signed
proves the check can fail. A matching page is added under
doc/develop/pytest/ so the module documentation is rendered with
the rest of the generated docs.
- test/boot/fit_verity.c gains a runtime unit test that builds the
exact node list the configuration signature is computed over,
turns it into hashed regions and checks both that the roothash
bytes fall inside a signed region and that tampering them changes
the hash. It needs no private key, so it also runs on real devices
and uses the same hash path a device would.
To let the unit test build the signed-region node list, rename the
config node-list helper to fit_config_get_signed_nodes(), make it
non-static and declare it in image.h.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
Add a DM test that feeds __net_defragment() a single crafted fragment
whose trailing hole descriptor lands just past pkt_buff. Without the
preceding fix the 8-byte hole write goes out of bounds; with it the
fragment is dropped and no datagram is delivered.
Signed-off-by: Shahriyar Jalayeri <shahriyar@byteray.co.uk>
Acked-by: Jerome Forissier <jerome.forissier@arm.com>
The hash command currently always uses the software implementation for
the selected algorithm, even when driver-model hash providers are
available.
Add a hash_digest_wd_lookup() helper which probes UCLASS_HASH devices in
order and uses the first provider supporting the requested algorithm.
Continue past unavailable providers and unsupported operations, but
propagate a hard digest failure once a provider accepts the operation.
Remember probe failures so they are not silently hidden by software
fallback when no later provider succeeds.
Use the helper from the hash command and retain its software fallback
when no usable provider is present. Add sandbox tests covering provider
fallback and hard-error propagation.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
Vincent Jardin <vjardin@free.fr> says:
3 commits providing documentation of impacts and testing the dispatch
for null_dev_desc_ok fstypes (semihosting, ubifs, sandbox) in the
generic `load <iface> ...` command.
The test does not cover ubifs, I could not make it work with
qemu. Since the code logic is there and testing with semihost
is done, it should cover the needed cases.
Link: https://lore.kernel.org/r/20260715165735.3207801-1-vjardin@free.fr
The name to GUID mapping that "env set -e" applies when no -guid
option is given was not covered by any test, which is how the wrong
default GUID for "dbr" went unnoticed until the previous commit.
Add a test case that enrolls each of db, dbx, dbt and dbr in setup
mode without an explicit -guid option and checks that every variable
is created under the image security database GUID and not under the
global variable GUID. Then enroll PK and KEK, also without -guid, and
check that both are created under the global variable GUID and not
under the image security database GUID. This is also the first
coverage of dbt and dbr anywhere under test/.
The signature database enrollment happens in setup mode because once
secure boot is enabled, efi_variable_authenticate() only accepts
writes to PK, KEK, db and dbx; PK and KEK are enrolled last because
installing PK leaves setup mode.
Signed-off-by: Aristo Chen <aristo.chen@canonical.com>
Some pytest modules exercising the dispatch added by
fs: dispatch null_dev_desc_ok filesystems before lookup
test_load_semihosting.py:
"load semihosting - <addr> <file>" and the optional
[bytes] [pos] variant. Runs on qemu_arm64 with
CONFIG_SEMIHOSTING=y; reuses test_hostfs.py's host-staged
fixture.
test_load_sandbox.py:
"load sandbox - <addr> <file>" and the optional [bytes] [pos]
variant. Runs on sandbox (boardspec('sandbox')); the sandbox
fstype is registered with name="sandbox" and
null_dev_desc_ok=true,
so the same fs_lookup_null_dev_info() helper that
routes semihosting also routes the "sandbox".
A "load ubifs - <addr> <file>" test is intentionally not provided.
UBIFS is built on UBI on MTD, which requires some additional works
that are not available with qemu/sandbox-ing.
Signed-off-by: Vincent Jardin <vjardin@free.fr>
Reviewed-by: Simon Glass <sjg@chromium.org>
With CONFIG_FIT_BEST_MATCH, fit_conf_find_compat() selects the
configuration matching the most specific U-Boot compatible string; on
equal matches the first listed configuration wins and the configurations
node 'default' property is never consulted.
A FIT whose configurations all share the same base devicetree compatible
(e.g. one manifest carrying a base tree plus overlay combinations for a
single board) therefore always boots the first configuration, silently
ignoring the default chosen by the manifest author.
Break score ties in favour of the default configuration. A strictly
better compatible match still wins over it, and FITs without a default
keep the current first-listed behaviour.
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Tom Rini <trini@konsulko.com>
Signed-off-by: Carlo Caione <ccaione@baylibre.com>
Aristo Chen <aristo.chen@canonical.com> says:
fit_import_data() in tools/fit_image.c declares the data pointer and
the name of the external data property outside its loop over the
/images subnodes, so both values leak from one image into the next. An
image node that carries data-size but neither data-offset nor
data-position then reuses the pointer left behind by the previously
imported image: the previous image's data is written into the node,
after which the import aborts trying to delete an external data
property the node never had. Since that abort path only prints a
debug() message, a regular mkimage build fails with nothing but the
generic usage text. The failure mode also depends on the order of the
image nodes: when no externally stored image precedes the malformed
node, the pointer is still NULL, the node is skipped, and the hashing
stage reports a proper error instead.
A FIT authored from a .its cannot hit this, because dtc-authored
images carry inline data. It takes re-processing an external-data FIT
in which an image has lost its data-offset, for example one edited
with fdtput -d or produced by another tool:
mkimage -E -f demo.its demo.itb
fdtput -d demo.itb /images/kernel-2 data-offset
mkimage -F demo.itb
There is no silent-success path, because the failing property delete
always aborts the run before the file is written back, but the user is
left without any indication of what is wrong.
Patch 1 moves the declarations into the loop so that each image starts
from a clean state. A node without an external data reference is now
skipped consistently regardless of node order, and the later
processing stages report the malformed node with a proper error
message (Can't get image data/size).
Patch 2 adds a regression test that builds an external-data FIT,
deletes the data-offset property of the second image and re-processes
the result with mkimage -F. It asserts that mkimage fails and that the
diagnostic is present on stderr; the unfixed tool fails the second
assertion since it prints nothing beyond the usage text.
Link: https://lore.kernel.org/r/20260710153343.1839357-1-aristo.chen@canonical.com
Build an external-data FIT, remove the data-offset property from the
second image so that only its data-size remains, and re-process the
result with mkimage -F. mkimage must reject the malformed FIT with a
clear diagnostic from the hashing stage. Previously the stale per-image
state in fit_import_data() made the import copy the first image's data
into the second image and abort without printing anything.
Signed-off-by: Aristo Chen <aristo.chen@canonical.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
The legacy network stack supports tftpsrv, which listens for an
incoming TFTP write request and receives the first file into memory.
Despite the old command help wording, the command returns after
receiving the file and does not boot it automatically.
The lwIP stack already builds the lwIP TFTP application, but only wires
it up for client-side tftpboot. Add a lwIP tftpsrv command and
implement the server path with tftp_init_server(). Reuse the existing
lwIP TFTP write callback and memory copy path so LMB checks, progress
output, filesize/fileaddr updates and EFI bootdev handling stay
consistent with tftpboot.
Track receive timeout and write-failure state around the lwIP callbacks
so a stalled or rejected receive is not reported as a successful close.
Move CMD_TFTPSRV out of the legacy-only Kconfig block so it can be
enabled with either network stack. Update the command help text and add
usage documentation for the receive-only behavior.
Add pytest coverage for tftpsrv using a generated host file and curl's
TFTP upload support. Enable the command in qemu_arm64_lwip_defconfig so
the test can be run with the existing lwIP QEMU build when the boardenv
provides env__net_tftpsrv_file.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
[Jerome Forissier: remove trailing ':' after SPDX tag]
Signed-off-by: Jerome Forissier <jerome.forissier@arm.com>
Reviewed-by: Jerome Forissier <jerome.forissier@arm.com>
Rasmus Villemoes <rv@rasmusvillemoes.dk> says:
This started by me wanting something like what patch 8 does. That
wasn't too hard, except we had no strcasestr(), and also our regex
engine (which I didn't really want to pull into the mix anyway)
doesn't have a flag that requests case-insensitive matching. So I
wanted to add strcasestr(), but then I stumbled on a bunch of stuff
that should be cleaned up in str-land.
Link: https://lore.kernel.org/r/20260708203711.849489-1-rv@rasmusvillemoes.dk
Add some test cases for the 'config' command, including the ability to
filter the output.
Signed-off-by: Rasmus Villemoes <rv@rasmusvillemoes.dk>
Reviewed-by: Simon Glass <sjg@chromium.org>
Change the existing strstr() test a little so that the substring not
found is "bits", i.e. one that is actually found when doing case
insensitive search.
Then copy all of lib_strstr(), adapt the expectation for the
strcasestr(s1, s3) result, and add another "not found" case.
Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Rasmus Villemoes <rv@rasmusvillemoes.dk>
Add a regression test that builds a FIT with external data, inflates
the data-size property far beyond the image and any plausible load
region, and confirms that spl_load_simple_fit() returns -EFBIG instead
of reading the declared size off the device. Without the bounds check
in load_simple_fit() this test overruns memory and crashes; with it the
load is rejected cleanly.
Signed-off-by: Aristo Chen <aristo.chen@canonical.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Aristo Chen <aristo.chen@canonical.com> says:
vbe_read_fit() loads a firmware-phase FIT from a fixed firmware area on
a block device and then issues a follow-up blk_read() to pull in the
image, and optionally an FDT, referenced by the FIT's image node. The
source offset on the device and the read length both come from the FIT
itself, via data-position or data-offset and data-size. Those properties
live on mutable boot media and can be controlled by an attacker with
write access to the firmware area. On the TPL or VPL path, and on the
bootmeth bootflow path reached via abrec_read_bootflow_fw() and
vbe_simple_read_bootflow_fw(), the follow-up blk_read() runs before any
signature or hash check on the loaded phase.
Patch 1 is a sandbox test-tree preparation. The firmware1 node in
arch/sandbox/dts/test.dts declared area-size = 0xe00000 (14 MiB), but
the binman fw-update section in sandbox_vpl.dtsi is 32 MiB and the FIT
inside it carries ~16 MiB of external data, so the FIT already extended
past the declared area. The mismatch was tolerated because no caller
bounded the external-data load against area_size. Patch 1 raises
area-size to match the binman section size so test_vbe_vpl keeps passing
once the bound is enforced. The patches are ordered so the test is never
broken in the middle of the series.
Patch 2 adds the missing range check, confining the FIT-supplied
[load_addr, load_addr + len) window to [addr, addr + area_size] before
block numbers and lengths are computed, and applying the same constraint
to fdt_load_addr and fdt_size. The check is written in subtraction-only
form against the trusted area_size so the comparison cannot itself
overflow.
Patch 3 adds two sandbox unit tests under test/boot/ that construct
synthetic FITs with out-of-range data-position and oversized data-size,
write them to mmc1, and confirm vbe_read_fit() returns -E2BIG for each
before issuing the follow-up blk_read().
Deferring the external-data blk_read() until after the phase has been
signature-verified would be a stronger structural fix and was discussed
on the v1 thread. Simon confirmed the bounded read is the right first
step and that the verify-then-load change should be a separate series,
so this v3 stays scoped to the bound.
Link: https://lore.kernel.org/r/20260705034414.2247-1-aristo.chen@canonical.com
vbe_read_fit() rejects FITs whose external-data window extends past the
trusted firmware area on disk by returning -E2BIG. Add two sandbox unit
tests that construct synthetic FITs with attacker-controlled
data-position and data-size values, write them to mmc1, and assert
vbe_read_fit() catches each one before issuing the follow-up
blk_read().
vbe_read_fit_oob_position uses a data-position past area_size, which
trips the load_addr - addr > area_size clause. vbe_read_fit_oversize_data
keeps data-position inside the area but picks a data-size that overruns
area_size - (load_addr - addr), tripping the third clause.
The two remaining bound clauses stay unreachable from a sandbox test.
The load_addr < addr guard trivially holds when addr comes from
CONFIG_VAL(TEXT_BASE), which is 0 on sandbox, and the FDT-region bound
sits behind a !CONFIG_SANDBOX guard in vbe_read_fit(), so fdt_size stays
0 and that block is skipped in this test environment.
The new file follows the existing bootstd VBE test layout and writes
the FIT at block 16, past the version and nvdata blocks already used by
bootstd_setup_for_tests().
Suggested-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Aristo Chen <aristo.chen@canonical.com>
CI: https://git.u-boot-project.org/u-boot/custodians/u-boot-mmc/-/pipelines/614
- Add PMBUS regulator, thermal and test
- Add regulator helper to set voltage within an acceptable range
- Update dw_mmc to use in-spec voltage range for vqmmc
- Fix regulator_enable/disable() macros
- Clear LPUART OR STAT in tstc to avoid hang
- Add MAINTAINERS entry for SDHCI
Coverity reports an INTEGER_OVERFLOW issue because ut_asserteq() compares
an unsigned int (mmc_dev_num) with ret, which can hold a negative error
code.
Addresses-Coverity-ID: CID 646439: Integer handling issues (INTEGER_OVERFLOW)
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
Reviewed-by: Quentin Schulz <quentin.schulz@cherry.de>
Add dm unit tests that drive every pmbus subcommand handler against
the sandbox PMBus chip emulator:
dev (select by bus:addr and by regulator-name), list, info,
telemetry, status, dump, read, write, clear, vout, scan and help.
Tested using:
./u-boot -T -c "ut dm pmbus*"
Signed-off-by: Vincent Jardin <vjardin@free.fr>
Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
Add a sandbox LDO3 with a configurable 1.8V to 3.3V range and use it
to test regulator_set_value_clamp().
Test in-range requests, clamping against the regulator limits, invalid
ranges outside the regulator limits and a min value higher than max.
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Reviewed-by: Peng Fan <peng.fan@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
The patman tests no longer exist in the tree, so drop them from the
test/run script (used by 'make tcheck' and friends) and from the
tools-testing example in the documentation.
Signed-off-by: Simon Glass <sjg@chromium.org>
Add bootdev_hunt_fallthrough() test to verify that 'bootflow scan -l'
falls back to a lower-priority bootdev when a higher-priority hunter
fails.
Introduce a simple 'sandbox-bootdev' device for the test. The new
bootdev can be configured to produce an error at the hunting stage.
Introduce new host_set_flags_by_label() API and a flags field to
'host_sb_plat' to simulate a bootdev hunter failure for the test.
Adjust boot{dev,flow} tests which depend on bootdev hunters.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Set the acpi_ops structure as static const where applicable. The
The structure is not accessible from outside of drivers and is not
going to be modified at runtime. The structure may be unused in a
couple of drivers depending on their configuration, mark those
sites with __maybe_unused .
Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
Currently, the bi_dram[] information is stored in the board info
structure (bd). Because bd is only valid after reserve_board(),
dram_init_banksize() must be called late in the initialization process.
This limitation is problematic, as it forces us to rely on a variety of
bespoke functions to determine board RAM, bank memory sizes, and other
early setup requirements.
By moving bi_dram[] into the global data (gd), we can run it earlier.
This is particularly convenient since boards define their own
dram_init_banksize() routines, which do not always rely on parsing
Device Tree (DT) memory nodes.
Additionally, U-Boot defaults to relocating to the top of the first memory
bank. While boards currently use custom functions to override this
behavior, having the DRAM bank information available earlier in gd makes
relocating to a different bank trivial and standardizes the process.
Reviewed-by: Anshul Dalal <anshuld@ti.com>
Tested-by: Michal Simek <michal.simek@amd.com> # Versal Gen 2 Vek385
Tested-by: Anshul Dalal <anshuld@ti.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Tested-by: Christophe Leroy (CS GROUP) <chleroy@kernel.org>
Add a unit test for the IP datagram reassembler (CONFIG_IP_DEFRAG) that
covers the duplicate-last-fragment scenario.
Without the fix the last fragment will re-trigger datagram delivery,
increasing udp_rx_count to 2 and effectively failing the test; with it
applied the test passes with udp_rx_count == 1.
Signed-off-by: Mateusz Furdyna <mateusz.furdyna@nokia.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Francesco Valla <francesco@valla.it> says:
This patch set contains a collection of small fixes and cleanups for the
"full" FIT loader that can be used for the SPL. The main beneficiary is
the falcon boot flow, but the same loader can be used also for U-Boot
proper.
Patch 1 was part of another set, but I decided to put it here for a
better separation between plumbing (here) and new features (there). I
kept the Reviewed-by tag collected from Simon in that occasion.
Patch 6 introduces a new unit test covering most of the code that is
being cleaned up.
The set was tested on a i.MX93 FRDM, both with and without signature and
to boot both U-Boot proper and the Linux kernel directly (i.e., falcon
boot).
Link: https://lore.kernel.org/r/20260604-spl_fit_full_cleanup-v1-0-ec036b5872e2@valla.it
Aristo Chen <aristo.chen@canonical.com> says:
For a compressed kernel_noload image, bootm_load_os() allocates a
decompression buffer of ALIGN(image_len * 4, SZ_1M) and then passes
CONFIG_SYS_BOOTM_LEN (typically 128 MiB on arm64) to image_decomp() as
the output limit. The decompressors honour whatever limit they are
given, so a kernel that decompresses to more than four times its
compressed size runs past the end of the allocated buffer and silently
corrupts adjacent memory.
A 4x compression ratio is at the edge of what modern compressors
(zstd, xz) achieve on real kernels, and is trivially exceeded by
crafted, highly compressible payloads, so this is reachable both
accidentally and intentionally. The overflow can land on already-loaded
boot artefacts (FDT, ramdisk, loadables), U-Boot's own data, or
memory-mapped device registers; the existing post-decompression overlap
check in bootm_load_os() only catches overlap with the FIT itself.
Patch 1 plumbs the actual allocation size through to image_decomp() and
handle_decomp_error() via a single decomp_len variable, so
decompression stops at the buffer boundary and fails cleanly when the
image is too large. The non-noload code path is unchanged and continues
to use CONFIG_SYS_BOOTM_LEN. A clarifying note is printed when the
failure is gated by the per-image buffer, so the generic
"increase CONFIG_SYS_BOOTM_LEN" advice does not mislead.
Patch 2 raises the noload-decompression headroom from 4x to 8x. The 4x
factor is at the edge of what zstd and xz achieve on real kernels, so
well-compressed vendor kernels can fail to boot at runtime once the
bound is enforced. 8x covers them comfortably while remaining bounded.
Patch 3 adds two sandbox py-tests against the per-image buffer at the
final 8x value: one that exceeds the buffer and must be rejected, and
one that matches the buffer exactly and must succeed (guarding the
boundary).
Tested on sandbox: both new tests pass; the existing
test_fit_compressed_images_load (which covers the load-address path)
and the other tests in test/py/tests/test_fit.py continue to pass.
Link: https://lore.kernel.org/r/20260605154255.833334-1-aristo.chen@canonical.com
Add sandbox tests that exercise the per-image decompression buffer that
bootm_load_os() allocates for a compressed kernel_noload image
(ALIGN(image_len * 8, SZ_1M)).
The overflow test builds a FIT whose decompressed size far exceeds the
per-image buffer and asserts that 'bootm loados' rejects it with a
decompression error rather than overflowing.
The boundary test builds a FIT whose decompressed size equals the
per-image buffer exactly and asserts that 'bootm loados' succeeds,
guarding against an off-by-one rejection at the buffer limit.
Signed-off-by: Aristo Chen <aristo.chen@canonical.com>
rs@ti.com <rs@ti.com> says:
From: Randolph Sapp <rs@ti.com>
Nitpicks and fixes from the discovery thread on adding PocketBeagle2 support
[1]. This does a lot of general setup required for the device, but these
modifications themselves aren't device specific. For those specifically
interested in PocketBeagle2 support and don't care about these details, my
development branch is public [2].
That first patch may provoke some opinions, but honestly if that warning was
still present I wouldn't have spent a week poking holes in both the EFI and LMB
allocations systems. Please let me know if there is a specific usecase that it
breaks though.
[1] https://lore.kernel.org/all/DHHC66BBMD27.YHGIH43C6XBK@ti.com/
[2] https://github.com/StaticRocket/u-boot/tree/feature/pocketbeagle2
Link: https://lore.kernel.org/r/20260604155038.3182-1-rs@ti.com
Add a image_fdt suite and a check for boot_fdt_add_mem_rsv_regions. This
will ensure the user is properly informed of any reservation failures.
It will also validate that reservations are cleaned up correctly when
switching FDTs.
Signed-off-by: Randolph Sapp <rs@ti.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Acked-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Add a ut_ubman fixture to clean up after certain problematic tests
without negatively affecting the current assert based testing.
Currently this catches "bootstd bootflow_cmd_boot" and "bootstd
bootflow_scan_boot" ut_subtests, as these will change the sandbox state
a little too much to be recoverable from.
Signed-off-by: Randolph Sapp <rs@ti.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
fit_image_get_data() uses the data-position, data-offset, and
data-size FIT properties without bounds checking. A crafted FIT
image can specify values that cause out-of-bounds read during
signature verification of an untrusted FIT.
Validate that the external data offset and size are non-negative,
and that the data region fits within the FIT image bounds.
Signed-off-by: Anton Ivanov <anton@binarly.io>
Reviewed-by: Simon Glass <sjg@chromium.org>
fit_config_check_sig() reads the hashed-strings property and uses
its size value without validation when building the region list for
signature verification. A crafted FIT image can specify an arbitrary
size, causing the hash calculation to read beyond the end of the FIT
image. The property length is also not checked, so a truncated
hashed-strings property causes strings[1] to be read past the end of
the property. This may result in the out-of-bounds read during signature
verification of an untrusted FIT.
Validate both the property length and that the declared strings region
fits within bounds before adding it to the region list.
Signed-off-by: Anton Ivanov <anton@binarly.io>
Aristo Chen <aristo.chen@canonical.com> says:
The get_basename() helper in tools/fit_image.c searches the entire input
path independently for the last '/' and the last '.'. When the last '.'
falls at an offset earlier than the last '/', for example "./mydt",
"a.b/c" or "sub.d/leaf", 'end' points before 'start' and the computed
length is negative. The size check uses signed comparison so the negative
value flows unchanged into memcpy() (cast to size_t there) and mkimage
segfaults during -f auto FIT generation. The helper is reached on every
auto-FIT build via the -b, --fit-tee and --fit-tfa-bl31 file arguments.
The first patch restricts the dot search to the substring that follows
the last slash, which is the minimal fix and preserves the existing
behaviour for typical inputs such as "arch/arm/dts/foo.dtb".
The second patch adds a parametrized sandbox test under
test/py/tests/test_fit_mkimage_validate.py that drives mkimage -f auto
with each of the crashing inputs ("./mydt", "./sub.d/leaf", "./a.b/c")
plus one control input ("./mydt.dtb"). The test reads the resulting
/images/fdt-1 description back from the produced FIT via fdtget to verify
get_basename()'s output matches the expected stripped basename.
Reproducer that previously segfaulted and now produces a valid image:
echo dummy > kernel.bin
echo dummy > ./mydt
./tools/mkimage -f auto -A arm -O linux -T kernel -C none \
-a 0x80000000 -e 0x80000000 -n test \
-d kernel.bin -b ./mydt out.itb
Verified by rebuilding tools/mkimage on master and running the command
above with each of the four parametrized inputs. The three crash triggers
all segfault before the fix and now produce the expected fdt-1
descriptions ("mydt", "leaf", "c"); the control input "./mydt.dtb"
continues to produce "mydt" as before.
Link: https://lore.kernel.org/r/20260526070336.23199-1-aristo.chen@canonical.com
Add a parametrized regression test for the fix in the previous commit.
The test invokes mkimage in auto-FIT mode (-f auto) with a -b argument
whose directory component contains a '.' and whose leaf either lacks an
extension or is a plain identifier. Before the fix these inputs caused
get_basename() to compute a negative length and segfault inside memcpy.
The test asserts that mkimage exits successfully and that the fdt
sub-image description matches the expected stripped basename, covering
"./mydt", "./sub.d/leaf", and "./a.b/c". A control input of "./mydt.dtb"
is also exercised to confirm normal extension stripping still works.
Signed-off-by: Aristo Chen <aristo.chen@canonical.com>
Rasmus Villemoes <rv@rasmusvillemoes.dk> says:
The commit message for patch 1 explains what it is I'd like to be able
to do, but here's some more background:
For a long time, we've embedded the boot script in the U-Boot binary
by building a bootscript.itb, and using a .dtsi like
/ {
config {
bootscript = /incbin/("/path/to/bootscript.itb");
};
};
which in turn is mentioned in CONFIG_DEVICE_TREE_INCLUDES, that
bootscript.itb FIT image has been embedded in U-Boot's control
dtb. Running that was then a matter of doing
fdt addr ${fdtcontroladdr} && fdt get addr bsaddr /config bootscript && source ${bsaddr}
There are a couple of advantage of having the bootscript (and other
script logic) embedded in the U-Boot binary. First, there's no need to
figure out some separate partition to store the script in, and making
sure that gets updated whenever the bootloader itself does. Second,
one doesn't need to worry about verifying the script; whatever steps
one needs to take to implement secure boot for U-Boot itself will by
necessity also cover the control dtb (if nothing else then because
that's where the public key for the kernel verification lives). And
third, the boot script is automatically updated together with U-Boot
itself; and if U-Boot is stored in an eMMC boot partition, that update
is guaranteed to be atomic.
Now with the stricter requirements of libfdt starting from v2026.04,
the above command no longer worked, or only half the time, because the
embedded FIT image may not land on an 8-byte aligned address. So that
line had to be changed a little (line breaks added)
fdt addr ${fdtcontroladdr}
&& fdt get addr bsaddr /config bootscript
&& fdt get size bssize /config bootscript
&& cp.b ${bsaddr} ${loadaddr} ${bssize}
&& source ${loadaddr}
which is getting quite unwieldy.
Then it struck me that one could perhaps simplify all of this quite a
lot: Cut out the intermediate bootscript.itb, just create a .dtsi
which directly puts a /images node inside the control dtb
/ {
images {
default = "bootscript";
bootscript {
description = "Boot script";
data = /incbin/("/path/to/bootscript.sh");
type = "script";
compression = "none";
};
};
};
and treat the control dtb itself as a FIT image; so the command to put
in $bootcmd becomes simply
source ${fdtcontroladdr}:bootscript
and embedding other pieces of callable scripts is quite trivial.
And that almost works out-of-the-box, except for the fit_check_format() sanity check.
Introduce a CONFIG_ knob that allows one to opt out of those sanity
checks, for the special case of the address being checked being
identical to gd->fdt_blob.
Link: https://lore.kernel.org/r/20260602213013.558064-1-rv@rasmusvillemoes.dk
Add a test demonstrating how one can embed various scripts in the
control DTB.
Verify that the source command can be used with ${fdtcontroladdr} by
itself (invoking the default script), and with :<node-name>
suffix. Check that the scripts themselves can invoke "sibling"
scripts. Also verify that without CONTROL_DTB_AS_FIT set, the control
DTB is not accepted by the source command.
Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Rasmus Villemoes <rv@rasmusvillemoes.dk>
Add a sandbox reset controller compatible string
"sandbox,reset-ctl-fallback-only" that reuses the existing sandbox assert,
deassert, request, and free helpers but omits rst_reset. That forces
reset_reset() through the core assert / udelay / deassert fallback.
Extend the reset-ctl-test DT node with a fifth reset line named "fallback"
that points at the new provider, and add dm_test_reset_reset_fallback_path
which verifies sandbox_reset_get_count() stays zero (rst_reset is never
invoked) while the line ends deasserted after reset_reset().
This complements the existing rst_reset coverage on sandbox,reset-ctl and
matches the approach of using a separate controller to exercise the
fallback path in unit tests.
Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Michal Simek <michal.simek@amd.com>
Link: https://lore.kernel.org/r/c1d40db6e2332a8b23ba842385b3f8c3d0290109.1779709539.git.michal.simek@amd.com
If the filesystem creation attempted by the FsHelper class fails, the
invocation of the cleanup function will cause a TypeError exception,
because the path of the filesystem itself, fed to os.remove(), will be
None. This will lead to a test failure even in case a skip is instead
wanted.
Such an exception will lead to a backtrace like this:
test/py/tests/test_fs/conftest.py:269: in fs_obj_basic
fsh.mk_fs()
test/py/tests/fs_helper.py:70: in mk_fs
self.fs_img = mk_fs(self.config, self.fs_type, self.size_mb << 20,
test/py/tests/fs_helper.py:246: in mk_fs
check_call(f'mkfs.{fs_lnxtype} {mkfs_opt} {fs_img}', shell=True,
/usr/lib64/python3.14/subprocess.py:420: in check_call
raise CalledProcessError(retcode, cmd)
E subprocess.CalledProcessError: Command '<...>' returned non-zero exit status 1.
During handling of the above exception, another exception occurred:
test/py/tests/test_fs/conftest.py:272: in fs_obj_basic
pytest.skip('Setup failed for filesystem: ' + fs_type + '. {}'.format(err))
E Skipped: Setup failed for filesystem: ext4. Command '<...>' returned non-zero exit status 1.
During handling of the above exception, another exception occurred:
test/py/tests/test_fs/conftest.py:277: in fs_obj_basic
fsh.cleanup()
test/py/tests/fs_helper.py:91: in cleanup
os.remove(self.fs_img)
E TypeError: remove: path should be string, bytes or os.PathLike, not NoneType
Fix this by checking if the variable containing the filesystem path is
valid before attempting to call os.remove() on it.
Fixes: 3691b1e4ce ("test: Convert fs_helper to use a class")
Signed-off-by: Francesco Valla <francesco@valla.it>
Add test/py/tests/test_fit_verity.py covering:
- mkimage writes correct dm-verity properties for matched and
mismatched block sizes (4096/4096 and 4096/1024);
- veritysetup verify re-checks the digest against the .itb's
external data section;
- mkimage rejects dm-verity images built without -E.
All tests are skipped if veritysetup is not installed on the host.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Reviewed-by: Simon Glass <sjg@chromium.org>