[PATCH 06/13] firewire: core: add test to avoid excessive configuration ROM length
From: Takashi Sakamoto
Date: Tue Sep 01 2026 - 10:01:15 EST
The configuration ROM parser needs to handle malformed ROM contents
safely. In particular, malformed directory and leaf offsets and block
lengths should not result in accesses beyond the available configuration
ROM data.
Add a KUnit test with malformed configuration ROM content to verify that
the parser sanitizes entries that would cause accesses beyond the
available configuration ROM data.
Reported-by: Aleksandr Shabelnikov <mistermidi@xxxxxxxxx>
Link: https://lore.kernel.org/lkml/20250901171547.47065-1-mistermidi@xxxxxxxxx/
Signed-off-by: Takashi Sakamoto <o-takashi@xxxxxxxxxxxxx>
---
drivers/firewire/config-rom-parser-test.c | 68 ++++++++++++++++++++++-
1 file changed, 66 insertions(+), 2 deletions(-)
diff --git a/drivers/firewire/config-rom-parser-test.c b/drivers/firewire/config-rom-parser-test.c
index d7c58c7fb995..e5c173353057 100644
--- a/drivers/firewire/config-rom-parser-test.c
+++ b/drivers/firewire/config-rom-parser-test.c
@@ -193,7 +193,7 @@ static const struct parser_test_case {
// Define parser_test_gen_params.
KUNIT_ARRAY_PARAM_DESC(parser_test, parser_test_cases, name);
-static int stub_run_regular_transaction(struct fw_card *card, int tcode, int destination_id,
+static int stub_run_transaction_regular(struct fw_card *card, int tcode, int destination_id,
int generation, int speed, unsigned long long offset,
void *payload, size_t length)
{
@@ -221,7 +221,7 @@ static void test_parser_with_regular_cases(struct kunit *test)
struct fw_device *device = test->priv;
const struct parser_test_case *param = test->param_value;
- kunit_activate_static_stub(test, fw_run_transaction, stub_run_regular_transaction);
+ kunit_activate_static_stub(test, fw_run_transaction, stub_run_transaction_regular);
device->card->link_speed = SCODE_BETA;
device->node->max_speed = param->phy_speed_in_self_id;
@@ -240,6 +240,69 @@ static void test_parser_with_regular_cases(struct kunit *test)
kunit_deactivate_static_stub(test, fw_run_transaction);
}
+static int stub_run_transaction_malformed(struct fw_card *card, int tcode, int destination_id,
+ int generation, int speed, unsigned long long offset,
+ void *payload, size_t length)
+{
+ static const u32 config_rom_first_part[] = {
+ 0x04000000,
+ 0x31333934,
+ 0x00008002,
+ 0x00000000,
+ 0x00000000,
+ 0x00030000,
+ (CSR_VENDOR << 24) | 0x00123456, // Regular entry.
+ ((CSR_LEAF | CSR_DESCRIPTOR) << 24) | 0x000000f9, // Beyond the upper limit.
+ ((CSR_DIRECTORY | CSR_UNIT) << 24) | 0x00000001,
+ 0xffff0000, // Over the upper limit.
+ };
+ struct kunit *test = kunit_get_current_test();
+
+ KUNIT_ASSERT_GE(test, offset, CSR_REGISTER_BASE | CSR_CONFIG_ROM);
+ KUNIT_ASSERT_LT(test, offset, CSR_REGISTER_BASE | CSR_CONFIG_ROM_END);
+ KUNIT_ASSERT_NOT_NULL(test, payload);
+ KUNIT_ASSERT_EQ(test, length, 4);
+
+ unsigned int index = (offset - (CSR_REGISTER_BASE | CSR_CONFIG_ROM)) / sizeof(u32);
+ u32 *quadlet = payload;
+
+ if (index < ARRAY_SIZE(config_rom_first_part))
+ *quadlet = cpu_to_be32(config_rom_first_part[index]);
+ else
+ *quadlet = 0;
+
+ return RCODE_COMPLETE;
+}
+
+static void test_parser_with_overflowed_case(struct kunit *test)
+{
+ static const u32 corrected_config_rom[] = {
+ 0x04000000,
+ 0x31333934,
+ 0x00008002,
+ 0x00000000,
+ 0x00000000,
+ 0x00030000,
+ 0x03123456,
+ 0x00000000, // Sanitized.
+ 0xd1000001,
+ 0x00000000, // Sanitized.
+ };
+ struct fw_device *device = test->priv;
+
+ kunit_activate_static_stub(test, fw_run_transaction, stub_run_transaction_malformed);
+
+ device->card->link_speed = SCODE_BETA;
+
+ KUNIT_EXPECT_EQ(test, read_config_rom(device, 0), RCODE_COMPLETE);
+
+ KUNIT_EXPECT_EQ(test, device->config_rom_length, ARRAY_SIZE(corrected_config_rom));
+ KUNIT_EXPECT_MEMEQ(test, device->config_rom, corrected_config_rom,
+ sizeof(corrected_config_rom));
+
+ kunit_deactivate_static_stub(test, fw_run_transaction);
+}
+
static const struct fw_card_driver dummy_card_driver;
static int config_rom_parser_test_init(struct kunit *test)
@@ -279,6 +342,7 @@ static void config_rom_parser_test_exit(struct kunit *test)
static struct kunit_case config_rom_parser_test_cases[] = {
KUNIT_CASE_PARAM(test_parser_with_regular_cases, parser_test_gen_params),
+ KUNIT_CASE(test_parser_with_overflowed_case),
{}
};
--
2.53.0