test: spl: check load_simple_fit() rejects an oversized data-size
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>
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user