diff options
author | David Kilroy <kilroyd@googlemail.com> | 2009-02-21 11:52:53 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-02-27 14:53:02 -0500 |
commit | 7e57811ac5b595bdb53f2aef3bcb2b3d72663fa4 (patch) | |
tree | a96c77c56e2b0dd659b29f09b6a7290121c30d79 /drivers/net/wireless/orinoco | |
parent | ba3907e508454520569bf1a3c1570f05ea578768 (diff) |
orinoco: validate firmware header
Check the Agere firmware headers for validity before attempting to
download it.
Signed-off-by: David Kilroy <kilroyd@googlemail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/orinoco')
-rw-r--r-- | drivers/net/wireless/orinoco/fw.c | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/drivers/net/wireless/orinoco/fw.c b/drivers/net/wireless/orinoco/fw.c index 7d2292d6ce09..9f163feb9362 100644 --- a/drivers/net/wireless/orinoco/fw.c +++ b/drivers/net/wireless/orinoco/fw.c | |||
@@ -43,6 +43,33 @@ struct orinoco_fw_header { | |||
43 | char signature[0]; /* FW signature length headersize-20 */ | 43 | char signature[0]; /* FW signature length headersize-20 */ |
44 | } __attribute__ ((packed)); | 44 | } __attribute__ ((packed)); |
45 | 45 | ||
46 | /* Check the range of various header entries. Return a pointer to a | ||
47 | * description of the problem, or NULL if everything checks out. */ | ||
48 | static const char *validate_fw(const struct orinoco_fw_header *hdr, size_t len) | ||
49 | { | ||
50 | u16 hdrsize; | ||
51 | |||
52 | if (len < sizeof(*hdr)) | ||
53 | return "image too small"; | ||
54 | if (memcmp(hdr->hdr_vers, "HFW", 3) != 0) | ||
55 | return "format not recognised"; | ||
56 | |||
57 | hdrsize = le16_to_cpu(hdr->headersize); | ||
58 | if (hdrsize > len) | ||
59 | return "bad headersize"; | ||
60 | if ((hdrsize + le32_to_cpu(hdr->block_offset)) > len) | ||
61 | return "bad block offset"; | ||
62 | if ((hdrsize + le32_to_cpu(hdr->pdr_offset)) > len) | ||
63 | return "bad PDR offset"; | ||
64 | if ((hdrsize + le32_to_cpu(hdr->pri_offset)) > len) | ||
65 | return "bad PRI offset"; | ||
66 | if ((hdrsize + le32_to_cpu(hdr->compat_offset)) > len) | ||
67 | return "bad compat offset"; | ||
68 | |||
69 | /* TODO: consider adding a checksum or CRC to the firmware format */ | ||
70 | return NULL; | ||
71 | } | ||
72 | |||
46 | /* Download either STA or AP firmware into the card. */ | 73 | /* Download either STA or AP firmware into the card. */ |
47 | static int | 74 | static int |
48 | orinoco_dl_firmware(struct orinoco_private *priv, | 75 | orinoco_dl_firmware(struct orinoco_private *priv, |
@@ -58,6 +85,7 @@ orinoco_dl_firmware(struct orinoco_private *priv, | |||
58 | const unsigned char *first_block; | 85 | const unsigned char *first_block; |
59 | const unsigned char *end; | 86 | const unsigned char *end; |
60 | const char *firmware; | 87 | const char *firmware; |
88 | const char *fw_err; | ||
61 | struct net_device *dev = priv->ndev; | 89 | struct net_device *dev = priv->ndev; |
62 | int err = 0; | 90 | int err = 0; |
63 | 91 | ||
@@ -93,6 +121,15 @@ orinoco_dl_firmware(struct orinoco_private *priv, | |||
93 | 121 | ||
94 | hdr = (const struct orinoco_fw_header *) fw_entry->data; | 122 | hdr = (const struct orinoco_fw_header *) fw_entry->data; |
95 | 123 | ||
124 | fw_err = validate_fw(hdr, fw_entry->size); | ||
125 | if (fw_err) { | ||
126 | printk(KERN_WARNING "%s: Invalid firmware image detected (%s). " | ||
127 | "Aborting download\n", | ||
128 | dev->name, fw_err); | ||
129 | err = -EINVAL; | ||
130 | goto abort; | ||
131 | } | ||
132 | |||
96 | /* Enable aux port to allow programming */ | 133 | /* Enable aux port to allow programming */ |
97 | err = hermesi_program_init(hw, le32_to_cpu(hdr->entry_point)); | 134 | err = hermesi_program_init(hw, le32_to_cpu(hdr->entry_point)); |
98 | printk(KERN_DEBUG "%s: Program init returned %d\n", dev->name, err); | 135 | printk(KERN_DEBUG "%s: Program init returned %d\n", dev->name, err); |