summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Richter <stefanr@s5r6.in-berlin.de>2010-01-29 21:25:46 +0100
committerGreg Kroah-Hartman <gregkh@suse.de>2010-02-09 04:50:52 -0800
commit80569f607b59fb59d0e7d86ae6467fefcab8e89b (patch)
treece7c8502b19e26941cc28fad879ec521e746461a
parent612e99b2d1ba8839896c6ea78d4329782d4e16b8 (diff)
firewire: core: add_descriptor size check
Backport of commit e300839da40e99581581c5d053a95a172651fec8 upstream. Presently, firewire-core only checks whether descriptors that are to be added by userspace drivers to the local node's config ROM do not exceed a size of 256 quadlets. However, the sum of the bare minimum ROM plus all descriptors (from firewire-core, from firewire-net, from userspace) must not exceed 256 quadlets. Otherwise, the bounds of a statically allocated buffer will be overwritten. If the kernel survives that, firewire-core will subsequently be unable to parse the local node's config ROM. (Note, userspace drivers can add descriptors only through device files of local nodes. These are usually only accessible by root, unlike device files of remote nodes which may be accessible to lesser privileged users.) Therefore add a test which takes the actual present and required ROM size into account for all descriptors of kernelspace and userspace drivers. Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/firewire/core-card.c42
1 files changed, 29 insertions, 13 deletions
diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c
index e4864e894e4f..ed635ae2b5d3 100644
--- a/drivers/firewire/core-card.c
+++ b/drivers/firewire/core-card.c
@@ -57,6 +57,9 @@ static LIST_HEAD(card_list);
static LIST_HEAD(descriptor_list);
static int descriptor_count;
+/* ROM header, bus info block, root dir header, capabilities = 7 quadlets */
+static size_t config_rom_length = 1 + 4 + 1 + 1;
+
#define BIB_CRC(v) ((v) << 0)
#define BIB_CRC_LENGTH(v) ((v) << 16)
#define BIB_INFO_LENGTH(v) ((v) << 24)
@@ -72,7 +75,7 @@ static int descriptor_count;
#define BIB_CMC ((1) << 30)
#define BIB_IMC ((1) << 31)
-static u32 *generate_config_rom(struct fw_card *card, size_t *config_rom_length)
+static u32 *generate_config_rom(struct fw_card *card)
{
struct fw_descriptor *desc;
static u32 config_rom[256];
@@ -131,7 +134,7 @@ static u32 *generate_config_rom(struct fw_card *card, size_t *config_rom_length)
for (i = 0; i < j; i += length + 1)
length = fw_compute_block_crc(config_rom + i);
- *config_rom_length = j;
+ WARN_ON(j != config_rom_length);
return config_rom;
}
@@ -140,17 +143,24 @@ static void update_config_roms(void)
{
struct fw_card *card;
u32 *config_rom;
- size_t length;
list_for_each_entry (card, &card_list, link) {
- config_rom = generate_config_rom(card, &length);
- card->driver->set_config_rom(card, config_rom, length);
+ config_rom = generate_config_rom(card);
+ card->driver->set_config_rom(card, config_rom,
+ config_rom_length);
}
}
+static size_t required_space(struct fw_descriptor *desc)
+{
+ /* descriptor + entry into root dir + optional immediate entry */
+ return desc->length + 1 + (desc->immediate > 0 ? 1 : 0);
+}
+
int fw_core_add_descriptor(struct fw_descriptor *desc)
{
size_t i;
+ int ret;
/*
* Check descriptor is valid; the length of all blocks in the
@@ -166,15 +176,21 @@ int fw_core_add_descriptor(struct fw_descriptor *desc)
mutex_lock(&card_mutex);
- list_add_tail(&desc->link, &descriptor_list);
- descriptor_count++;
- if (desc->immediate > 0)
+ if (config_rom_length + required_space(desc) > 256) {
+ ret = -EBUSY;
+ } else {
+ list_add_tail(&desc->link, &descriptor_list);
+ config_rom_length += required_space(desc);
descriptor_count++;
- update_config_roms();
+ if (desc->immediate > 0)
+ descriptor_count++;
+ update_config_roms();
+ ret = 0;
+ }
mutex_unlock(&card_mutex);
- return 0;
+ return ret;
}
EXPORT_SYMBOL(fw_core_add_descriptor);
@@ -183,6 +199,7 @@ void fw_core_remove_descriptor(struct fw_descriptor *desc)
mutex_lock(&card_mutex);
list_del(&desc->link);
+ config_rom_length -= required_space(desc);
descriptor_count--;
if (desc->immediate > 0)
descriptor_count--;
@@ -436,7 +453,6 @@ int fw_card_add(struct fw_card *card,
u32 max_receive, u32 link_speed, u64 guid)
{
u32 *config_rom;
- size_t length;
int ret;
card->max_receive = max_receive;
@@ -445,8 +461,8 @@ int fw_card_add(struct fw_card *card,
mutex_lock(&card_mutex);
- config_rom = generate_config_rom(card, &length);
- ret = card->driver->enable(card, config_rom, length);
+ config_rom = generate_config_rom(card);
+ ret = card->driver->enable(card, config_rom, config_rom_length);
if (ret == 0)
list_add_tail(&card->link, &card_list);