[PATCH] firewire: core-card: fix ROM length mismatch and strengthen descriptor validation

From: Sreeraj S Kurup

Date: Mon Jul 20 2026 - 10:57:56 EST


The FireWire core had two issues:

1. ROM length mismatch handling:
Previously, generate_config_rom() only WARNed when the computed
length differed from config_rom_length. This left the driver in
an inconsistent state. Now we log a warning and resynchronize
config_rom_length to the actual value.

2. Descriptor validation:
fw_core_add_descriptor() only checked internal block consistency.
We now reject empty descriptors and those exceeding 256 quadlets
before parsing, preventing malformed input from corrupting the
config ROM.

These changes improve robustness of the FireWire core against
invalid descriptors and ensure config ROM stays consistent.

Signed-off-by: Sreeraj S Kurup <sreekuttan2156239@xxxxxxxxx>
---
drivers/firewire/core-card.c | 51 ++++++++++++++++++++----------------
1 file changed, 29 insertions(+), 22 deletions(-)

diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c
index a754c6366b97..97439da6f480 100644
--- a/drivers/firewire/core-card.c
+++ b/drivers/firewire/core-card.c
@@ -143,7 +143,11 @@ static void generate_config_rom(struct fw_card *card, __be32 *config_rom)
for (i = 0; i < j; i += length + 1)
length = fw_compute_block_crc(config_rom + i);

- WARN_ON(j != config_rom_length);
+ if (j != config_rom_length) {
+ pr_warn("FireWire ROM length mismatch: expected %zu, got %d\n",
+ config_rom_length, j);
+ config_rom_length = j;
+ }
}

static void update_config_roms(void)
@@ -165,33 +169,36 @@ static size_t required_space(struct fw_descriptor *desc)

int fw_core_add_descriptor(struct fw_descriptor *desc)
{
- size_t i;
+ size_t i;

- /*
- * Check descriptor is valid; the length of all blocks in the
- * descriptor has to add up to exactly the length of the
- * block.
- */
- i = 0;
- while (i < desc->length)
- i += (desc->data[i] >> 16) + 1;
+ /* Extra validation: reject empty or oversized descriptors */
+ if (desc->length == 0 || desc->length > 256)
+ return -EINVAL;

- if (i != desc->length)
- return -EINVAL;
+ /*
+ * Check descriptor is valid, the length of all blocks in the
+ * descriptor has to add up to exactly the length of the block.
+ */
+ i = 0;
+ while (i < desc->length)
+ i += (desc->data[i] >> 16) + 1;

- guard(mutex)(&card_mutex);
+ if (i != desc->length)
+ return -EINVAL;

- if (config_rom_length + required_space(desc) > 256)
- return -EBUSY;
+ guard(mutex)(&card_mutex);

- list_add_tail(&desc->link, &descriptor_list);
- config_rom_length += required_space(desc);
- descriptor_count++;
- if (desc->immediate > 0)
- descriptor_count++;
- update_config_roms();
+ if (config_rom_length + required_space(desc) > 256)
+ return -EBUSY;

- return 0;
+ list_add_tail(&desc->link, &descriptor_list);
+ config_rom_length += required_space(desc);
+ descriptor_count++;
+ if (desc->immediate > 0)
+ descriptor_count++;
+ update_config_roms();
+
+ return 0;
}
EXPORT_SYMBOL(fw_core_add_descriptor);

--
2.54.0