From 1c4326e7d8305389c5ee7d15127b33da2f3ec98a Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Tue, 1 Sep 2026 22:45:27 +0900 Subject: [PATCH] firewire: core: add test to avoid excessive configuration ROM length 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 Link: https://lore.kernel.org/lkml/20250901171547.47065-1-mistermidi@gmail.com/ Link: https://lore.kernel.org/r/20260901134534.2386577-7-o-takashi@sakamocchi.jp Signed-off-by: Takashi Sakamoto --- 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), {} };