airo: sanitize handling of SSID_rid
* store SSID_rid without conversions
* sanitize proc_SSID_on_close() (and avoid access past the end of
buffer, while we are at it)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 76cd103..c4ae441 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -510,12 +510,12 @@
/* These structures are from the Aironet's PC4500 Developers Manual */
typedef struct {
- u16 len;
+ __le16 len;
u8 ssid[32];
} Ssid;
typedef struct {
- u16 len;
+ __le16 len;
Ssid ssids[3];
} SsidRid;
@@ -1789,28 +1789,16 @@
return rc;
}
-static int readSsidRid(struct airo_info*ai, SsidRid *ssidr) {
- int i;
- int rc = PC4500_readrid(ai, RID_SSID, ssidr, sizeof(*ssidr), 1);
-
- ssidr->len = le16_to_cpu(ssidr->len);
- for(i = 0; i < 3; i++) {
- ssidr->ssids[i].len = le16_to_cpu(ssidr->ssids[i].len);
- }
- return rc;
+static int readSsidRid(struct airo_info*ai, SsidRid *ssidr)
+{
+ return PC4500_readrid(ai, RID_SSID, ssidr, sizeof(*ssidr), 1);
}
-static int writeSsidRid(struct airo_info*ai, SsidRid *pssidr, int lock) {
- int rc;
- int i;
- SsidRid ssidr = *pssidr;
- ssidr.len = cpu_to_le16(ssidr.len);
- for(i = 0; i < 3; i++) {
- ssidr.ssids[i].len = cpu_to_le16(ssidr.ssids[i].len);
- }
- rc = PC4500_writerid(ai, RID_SSID, &ssidr, sizeof(ssidr), lock);
- return rc;
+static int writeSsidRid(struct airo_info*ai, SsidRid *pssidr, int lock)
+{
+ return PC4500_writerid(ai, RID_SSID, pssidr, sizeof(*pssidr), lock);
}
+
static int readConfigRid(struct airo_info*ai, int lock) {
int rc;
u16 *s;
@@ -3886,13 +3874,13 @@
if ( ssids[0] ) {
int i;
for( i = 0; i < 3 && ssids[i]; i++ ) {
- mySsid.ssids[i].len = strlen(ssids[i]);
- if ( mySsid.ssids[i].len > 32 )
- mySsid.ssids[i].len = 32;
- memcpy(mySsid.ssids[i].ssid, ssids[i],
- mySsid.ssids[i].len);
+ size_t len = strlen(ssids[i]);
+ if (len > 32)
+ len = 32;
+ mySsid.ssids[i].len = cpu_to_le16(len);
+ memcpy(mySsid.ssids[i].ssid, ssids[i], len);
}
- mySsid.len = sizeof(mySsid);
+ mySsid.len = cpu_to_le16(sizeof(mySsid));
}
status = writeConfigRid(ai, lock);
@@ -5123,34 +5111,38 @@
return 0;
}
-static void proc_SSID_on_close( struct inode *inode, struct file *file ) {
+static void proc_SSID_on_close(struct inode *inode, struct file *file)
+{
struct proc_data *data = (struct proc_data *)file->private_data;
struct proc_dir_entry *dp = PDE(inode);
struct net_device *dev = dp->data;
struct airo_info *ai = dev->priv;
SsidRid SSID_rid;
int i;
- int offset = 0;
+ char *p = data->wbuffer;
+ char *end = p + data->writelen;
- if ( !data->writelen ) return;
+ if (!data->writelen)
+ return;
- memset( &SSID_rid, 0, sizeof( SSID_rid ) );
+ *end = '\n'; /* sentinel; we have space for it */
- for( i = 0; i < 3; i++ ) {
- int j;
- for( j = 0; j+offset < data->writelen && j < 32 &&
- data->wbuffer[offset+j] != '\n'; j++ ) {
- SSID_rid.ssids[i].ssid[j] = data->wbuffer[offset+j];
- }
- if ( j == 0 ) break;
- SSID_rid.ssids[i].len = j;
- offset += j;
- while( data->wbuffer[offset] != '\n' &&
- offset < data->writelen ) offset++;
- offset++;
+ memset(&SSID_rid, 0, sizeof(SSID_rid));
+
+ for (i = 0; i < 3 && p < end; i++) {
+ int j = 0;
+ /* copy up to 32 characters from this line */
+ while (*p != '\n' && j < 32)
+ SSID_rid.ssids[i].ssid[j++] = *p++;
+ if (j == 0)
+ break;
+ SSID_rid.ssids[i].len = cpu_to_le16(j);
+ /* skip to the beginning of the next line */
+ while (*p++ != '\n')
+ ;
}
if (i)
- SSID_rid.len = sizeof(SSID_rid);
+ SSID_rid.len = cpu_to_le16(sizeof(SSID_rid));
disable_MAC(ai, 1);
writeSsidRid(ai, &SSID_rid, 1);
enable_MAC(ai, 1);
@@ -5345,7 +5337,8 @@
return 0;
}
-static int proc_SSID_open( struct inode *inode, struct file *file ) {
+static int proc_SSID_open(struct inode *inode, struct file *file)
+{
struct proc_data *data;
struct proc_dir_entry *dp = PDE(inode);
struct net_device *dev = dp->data;
@@ -5363,7 +5356,8 @@
}
data->writelen = 0;
data->maxwritelen = 33*3;
- if ((data->wbuffer = kzalloc( 33*3, GFP_KERNEL )) == NULL) {
+ /* allocate maxwritelen + 1; we'll want a sentinel */
+ if ((data->wbuffer = kzalloc(33*3 + 1, GFP_KERNEL)) == NULL) {
kfree (data->rbuffer);
kfree (file->private_data);
return -ENOMEM;
@@ -5372,14 +5366,15 @@
readSsidRid(ai, &SSID_rid);
ptr = data->rbuffer;
- for( i = 0; i < 3; i++ ) {
+ for (i = 0; i < 3; i++) {
int j;
- if ( !SSID_rid.ssids[i].len ) break;
- for( j = 0; j < 32 &&
- j < SSID_rid.ssids[i].len &&
- SSID_rid.ssids[i].ssid[j]; j++ ) {
+ size_t len = le16_to_cpu(SSID_rid.ssids[i].len);
+ if (!len)
+ break;
+ if (len > 32)
+ len = 32;
+ for (j = 0; j < len && SSID_rid.ssids[i].ssid[j]; j++)
*ptr++ = SSID_rid.ssids[i].ssid[j];
- }
*ptr++ = '\n';
}
*ptr = '\0';
@@ -5895,9 +5890,9 @@
memset(SSID_rid.ssids[index].ssid, 0,
sizeof(SSID_rid.ssids[index].ssid));
memcpy(SSID_rid.ssids[index].ssid, extra, dwrq->length);
- SSID_rid.ssids[index].len = dwrq->length;
+ SSID_rid.ssids[index].len = cpu_to_le16(dwrq->length);
}
- SSID_rid.len = sizeof(SSID_rid);
+ SSID_rid.len = cpu_to_le16(sizeof(SSID_rid));
/* Write it to the card */
disable_MAC(local, 1);
writeSsidRid(local, &SSID_rid, 1);