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 <[email protected]> --- test/image/spl_load.c | 49 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/test/image/spl_load.c b/test/image/spl_load.c index 3b6206955d3..c43c977f784 100644 --- a/test/image/spl_load.c +++ b/test/image/spl_load.c @@ -367,6 +367,55 @@ SPL_IMG_TEST(spl_test_image, IMX8, 0); SPL_IMG_TEST(spl_test_image, FIT_INTERNAL, 0); SPL_IMG_TEST(spl_test_image, FIT_EXTERNAL, 0); +/* + * A FIT image's data-size property is not covered by the configuration + * signature, so it is untrusted input. load_simple_fit() must reject a + * data-size larger than the destination rather than overrun it, because the + * device read happens before the image hash is verified. + */ +static int spl_test_fit_external_oversize(struct unit_test_state *uts) +{ + size_t img_size, img_data, data_size = SPL_TEST_DATA_SIZE; + struct spl_image_info info_write = { + .name = "oversize", + .size = data_size, + }, info_read = { }; + struct spl_load_info load; + void *img; + int node; + + if (!image_supported(FIT_EXTERNAL)) + return -EAGAIN; + + img_size = create_image(NULL, FIT_EXTERNAL, &info_write, &img_data); + ut_assert(img_size); + img = calloc(img_size, 1); + ut_assertnonnull(img); + + generate_data(img + img_data, data_size, "oversize"); + ut_asserteq(img_size, create_image(img, FIT_EXTERNAL, &info_write, + NULL)); + + /* + * Inflate data-size far beyond the image buffer and any plausible + * load region. Without a bounds check, load_simple_fit() reads this + * many bytes off the "device" before the hash is checked. + */ + node = fdt_path_offset(img, FIT_IMAGES_PATH); + ut_assert(node >= 0); + node = fdt_first_subnode(img, node); + ut_assert(node >= 0); + ut_assertok(fdt_setprop_inplace_u32(img, node, FIT_DATA_SIZE_PROP, + 0x40000000)); + + spl_load_init(&load, spl_test_read, img, 1); + ut_asserteq(-EFBIG, spl_load_simple_fit(&info_read, &load, 0, img)); + + free(img); + return 0; +} +SPL_TEST(spl_test_fit_external_oversize, 0); + /* * LZMA is too complex to generate on the fly, so let's use some data I put in * the oven^H^H^H^H compressed earlier -- 2.43.0

