aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/orinoco
diff options
context:
space:
mode:
authorDavid Kilroy <kilroyd@googlemail.com>2009-02-21 11:52:53 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-02-27 14:53:02 -0500
commit7e57811ac5b595bdb53f2aef3bcb2b3d72663fa4 (patch)
treea96c77c56e2b0dd659b29f09b6a7290121c30d79 /drivers/net/wireless/orinoco
parentba3907e508454520569bf1a3c1570f05ea578768 (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.c37
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. */
48static 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. */
47static int 74static int
48orinoco_dl_firmware(struct orinoco_private *priv, 75orinoco_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);