From 855ece352dc2e11715f8c98e38e8afc47ef96d5d Mon Sep 17 00:00:00 2001 From: Richard Hughes Date: Thu, 28 Apr 2022 10:46:10 +0100 Subject: [PATCH] Check the alignment when reading in raw firmware --- libfwupdplugin/fu-firmware.c | 15 +++++++++++++++ libfwupdplugin/fu-self-test.c | 22 ++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/libfwupdplugin/fu-firmware.c b/libfwupdplugin/fu-firmware.c index ea849f06f..4bb30676b 100644 --- a/libfwupdplugin/fu-firmware.c +++ b/libfwupdplugin/fu-firmware.c @@ -743,6 +743,7 @@ fu_firmware_parse_full(FuFirmware *self, GError **error) { FuFirmwareClass *klass = FU_FIRMWARE_GET_CLASS(self); + FuFirmwarePrivate *priv = GET_PRIVATE(self); g_return_val_if_fail(FU_IS_FIRMWARE(self), FALSE); g_return_val_if_fail(fw != NULL, FALSE); @@ -776,6 +777,19 @@ fu_firmware_parse_full(FuFirmware *self, if (klass->parse != NULL) return klass->parse(self, fw, addr_start, addr_end, flags, error); + /* verify alignment */ + if (g_bytes_get_size(fw) % (1ull << priv->alignment) != 0) { + g_autofree gchar *str = NULL; + str = g_format_size_full(1ull << priv->alignment, G_FORMAT_SIZE_IEC_UNITS); + g_set_error(error, + FWUPD_ERROR, + FWUPD_ERROR_INVALID_FILE, + "raw firmware is not aligned to 0x%x (%s)", + (guint)(1ull << priv->alignment), + str); + return FALSE; + } + /* just add entire blob */ fu_firmware_set_bytes(self, fw); fu_firmware_set_size(self, g_bytes_get_size(fw)); @@ -1603,6 +1617,7 @@ fu_firmware_export(FuFirmware *self, FuFirmwareExportFlags flags, XbBuilderNode fu_xmlb_builder_insert_kx(bn, "version_raw", priv->version_raw); fu_xmlb_builder_insert_kx(bn, "addr", priv->addr); fu_xmlb_builder_insert_kx(bn, "offset", priv->offset); + fu_xmlb_builder_insert_kx(bn, "alignment", priv->alignment); fu_xmlb_builder_insert_kx(bn, "size", priv->size); fu_xmlb_builder_insert_kv(bn, "filename", priv->filename); if (priv->bytes != NULL) { diff --git a/libfwupdplugin/fu-self-test.c b/libfwupdplugin/fu-self-test.c index fef02220f..caf1253c1 100644 --- a/libfwupdplugin/fu-self-test.c +++ b/libfwupdplugin/fu-self-test.c @@ -2460,6 +2460,27 @@ fu_common_vercmp_func(void) G_MAXINT); } +static void +fu_firmware_raw_aligned_func(void) +{ + gboolean ret; + g_autoptr(FuFirmware) firmware1 = fu_firmware_new(); + g_autoptr(FuFirmware) firmware2 = fu_firmware_new(); + g_autoptr(GError) error = NULL; + g_autoptr(GBytes) blob = g_bytes_new_static("hello", 5); + + /* no alignment */ + ret = fu_firmware_parse(firmware1, blob, FWUPD_INSTALL_FLAG_NONE, &error); + g_assert_no_error(error); + g_assert_true(ret); + + /* invalid alignment */ + fu_firmware_set_alignment(firmware2, FU_FIRMWARE_ALIGNMENT_4K); + ret = fu_firmware_parse(firmware2, blob, FWUPD_INSTALL_FLAG_NONE, &error); + g_assert_error(error, FWUPD_ERROR, FWUPD_ERROR_INVALID_FILE); + g_assert_false(ret); +} + static void fu_firmware_ihex_func(void) { @@ -4022,6 +4043,7 @@ main(int argc, char **argv) g_test_add_func("/fwupd/firmware{common}", fu_firmware_common_func); g_test_add_func("/fwupd/firmware{dedupe}", fu_firmware_dedupe_func); g_test_add_func("/fwupd/firmware{build}", fu_firmware_build_func); + g_test_add_func("/fwupd/firmware{raw-aligned}", fu_firmware_raw_aligned_func); g_test_add_func("/fwupd/firmware{ihex}", fu_firmware_ihex_func); g_test_add_func("/fwupd/firmware{ihex-xml}", fu_firmware_ihex_xml_func); g_test_add_func("/fwupd/firmware{ihex-offset}", fu_firmware_ihex_offset_func);