diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2007-12-17 16:11:57 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 18:08:58 -0500 |
commit | 0dd2212fb6872d8f5dd90391a12fb3fcb877c7c1 (patch) | |
tree | 75166515117c968f4c1bc77b0a944db30ed97988 /drivers/net/wireless/airo.c | |
parent | 593c2b9cf28355c6c409d71594bed797279d01f5 (diff) |
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>
Diffstat (limited to 'drivers/net/wireless/airo.c')
-rw-r--r-- | drivers/net/wireless/airo.c | 103 |
1 files changed, 49 insertions, 54 deletions
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 76cd1036e2d2..c4ae44142a67 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c | |||
@@ -510,12 +510,12 @@ typedef struct { | |||
510 | 510 | ||
511 | /* These structures are from the Aironet's PC4500 Developers Manual */ | 511 | /* These structures are from the Aironet's PC4500 Developers Manual */ |
512 | typedef struct { | 512 | typedef struct { |
513 | u16 len; | 513 | __le16 len; |
514 | u8 ssid[32]; | 514 | u8 ssid[32]; |
515 | } Ssid; | 515 | } Ssid; |
516 | 516 | ||
517 | typedef struct { | 517 | typedef struct { |
518 | u16 len; | 518 | __le16 len; |
519 | Ssid ssids[3]; | 519 | Ssid ssids[3]; |
520 | } SsidRid; | 520 | } SsidRid; |
521 | 521 | ||
@@ -1789,28 +1789,16 @@ static int writeWepKeyRid(struct airo_info*ai, WepKeyRid *pwkr, int perm, int lo | |||
1789 | return rc; | 1789 | return rc; |
1790 | } | 1790 | } |
1791 | 1791 | ||
1792 | static int readSsidRid(struct airo_info*ai, SsidRid *ssidr) { | 1792 | static int readSsidRid(struct airo_info*ai, SsidRid *ssidr) |
1793 | int i; | 1793 | { |
1794 | int rc = PC4500_readrid(ai, RID_SSID, ssidr, sizeof(*ssidr), 1); | 1794 | return PC4500_readrid(ai, RID_SSID, ssidr, sizeof(*ssidr), 1); |
1795 | |||
1796 | ssidr->len = le16_to_cpu(ssidr->len); | ||
1797 | for(i = 0; i < 3; i++) { | ||
1798 | ssidr->ssids[i].len = le16_to_cpu(ssidr->ssids[i].len); | ||
1799 | } | ||
1800 | return rc; | ||
1801 | } | 1795 | } |
1802 | static int writeSsidRid(struct airo_info*ai, SsidRid *pssidr, int lock) { | ||
1803 | int rc; | ||
1804 | int i; | ||
1805 | SsidRid ssidr = *pssidr; | ||
1806 | 1796 | ||
1807 | ssidr.len = cpu_to_le16(ssidr.len); | 1797 | static int writeSsidRid(struct airo_info*ai, SsidRid *pssidr, int lock) |
1808 | for(i = 0; i < 3; i++) { | 1798 | { |
1809 | ssidr.ssids[i].len = cpu_to_le16(ssidr.ssids[i].len); | 1799 | return PC4500_writerid(ai, RID_SSID, pssidr, sizeof(*pssidr), lock); |
1810 | } | ||
1811 | rc = PC4500_writerid(ai, RID_SSID, &ssidr, sizeof(ssidr), lock); | ||
1812 | return rc; | ||
1813 | } | 1800 | } |
1801 | |||
1814 | static int readConfigRid(struct airo_info*ai, int lock) { | 1802 | static int readConfigRid(struct airo_info*ai, int lock) { |
1815 | int rc; | 1803 | int rc; |
1816 | u16 *s; | 1804 | u16 *s; |
@@ -3886,13 +3874,13 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) | |||
3886 | if ( ssids[0] ) { | 3874 | if ( ssids[0] ) { |
3887 | int i; | 3875 | int i; |
3888 | for( i = 0; i < 3 && ssids[i]; i++ ) { | 3876 | for( i = 0; i < 3 && ssids[i]; i++ ) { |
3889 | mySsid.ssids[i].len = strlen(ssids[i]); | 3877 | size_t len = strlen(ssids[i]); |
3890 | if ( mySsid.ssids[i].len > 32 ) | 3878 | if (len > 32) |
3891 | mySsid.ssids[i].len = 32; | 3879 | len = 32; |
3892 | memcpy(mySsid.ssids[i].ssid, ssids[i], | 3880 | mySsid.ssids[i].len = cpu_to_le16(len); |
3893 | mySsid.ssids[i].len); | 3881 | memcpy(mySsid.ssids[i].ssid, ssids[i], len); |
3894 | } | 3882 | } |
3895 | mySsid.len = sizeof(mySsid); | 3883 | mySsid.len = cpu_to_le16(sizeof(mySsid)); |
3896 | } | 3884 | } |
3897 | 3885 | ||
3898 | status = writeConfigRid(ai, lock); | 3886 | status = writeConfigRid(ai, lock); |
@@ -5123,34 +5111,38 @@ static int proc_config_open( struct inode *inode, struct file *file ) { | |||
5123 | return 0; | 5111 | return 0; |
5124 | } | 5112 | } |
5125 | 5113 | ||
5126 | static void proc_SSID_on_close( struct inode *inode, struct file *file ) { | 5114 | static void proc_SSID_on_close(struct inode *inode, struct file *file) |
5115 | { | ||
5127 | struct proc_data *data = (struct proc_data *)file->private_data; | 5116 | struct proc_data *data = (struct proc_data *)file->private_data; |
5128 | struct proc_dir_entry *dp = PDE(inode); | 5117 | struct proc_dir_entry *dp = PDE(inode); |
5129 | struct net_device *dev = dp->data; | 5118 | struct net_device *dev = dp->data; |
5130 | struct airo_info *ai = dev->priv; | 5119 | struct airo_info *ai = dev->priv; |
5131 | SsidRid SSID_rid; | 5120 | SsidRid SSID_rid; |
5132 | int i; | 5121 | int i; |
5133 | int offset = 0; | 5122 | char *p = data->wbuffer; |
5123 | char *end = p + data->writelen; | ||
5134 | 5124 | ||
5135 | if ( !data->writelen ) return; | 5125 | if (!data->writelen) |
5126 | return; | ||
5136 | 5127 | ||
5137 | memset( &SSID_rid, 0, sizeof( SSID_rid ) ); | 5128 | *end = '\n'; /* sentinel; we have space for it */ |
5138 | 5129 | ||
5139 | for( i = 0; i < 3; i++ ) { | 5130 | memset(&SSID_rid, 0, sizeof(SSID_rid)); |
5140 | int j; | 5131 | |
5141 | for( j = 0; j+offset < data->writelen && j < 32 && | 5132 | for (i = 0; i < 3 && p < end; i++) { |
5142 | data->wbuffer[offset+j] != '\n'; j++ ) { | 5133 | int j = 0; |
5143 | SSID_rid.ssids[i].ssid[j] = data->wbuffer[offset+j]; | 5134 | /* copy up to 32 characters from this line */ |
5144 | } | 5135 | while (*p != '\n' && j < 32) |
5145 | if ( j == 0 ) break; | 5136 | SSID_rid.ssids[i].ssid[j++] = *p++; |
5146 | SSID_rid.ssids[i].len = j; | 5137 | if (j == 0) |
5147 | offset += j; | 5138 | break; |
5148 | while( data->wbuffer[offset] != '\n' && | 5139 | SSID_rid.ssids[i].len = cpu_to_le16(j); |
5149 | offset < data->writelen ) offset++; | 5140 | /* skip to the beginning of the next line */ |
5150 | offset++; | 5141 | while (*p++ != '\n') |
5142 | ; | ||
5151 | } | 5143 | } |
5152 | if (i) | 5144 | if (i) |
5153 | SSID_rid.len = sizeof(SSID_rid); | 5145 | SSID_rid.len = cpu_to_le16(sizeof(SSID_rid)); |
5154 | disable_MAC(ai, 1); | 5146 | disable_MAC(ai, 1); |
5155 | writeSsidRid(ai, &SSID_rid, 1); | 5147 | writeSsidRid(ai, &SSID_rid, 1); |
5156 | enable_MAC(ai, 1); | 5148 | enable_MAC(ai, 1); |
@@ -5345,7 +5337,8 @@ static int proc_wepkey_open( struct inode *inode, struct file *file ) { | |||
5345 | return 0; | 5337 | return 0; |
5346 | } | 5338 | } |
5347 | 5339 | ||
5348 | static int proc_SSID_open( struct inode *inode, struct file *file ) { | 5340 | static int proc_SSID_open(struct inode *inode, struct file *file) |
5341 | { | ||
5349 | struct proc_data *data; | 5342 | struct proc_data *data; |
5350 | struct proc_dir_entry *dp = PDE(inode); | 5343 | struct proc_dir_entry *dp = PDE(inode); |
5351 | struct net_device *dev = dp->data; | 5344 | struct net_device *dev = dp->data; |
@@ -5363,7 +5356,8 @@ static int proc_SSID_open( struct inode *inode, struct file *file ) { | |||
5363 | } | 5356 | } |
5364 | data->writelen = 0; | 5357 | data->writelen = 0; |
5365 | data->maxwritelen = 33*3; | 5358 | data->maxwritelen = 33*3; |
5366 | if ((data->wbuffer = kzalloc( 33*3, GFP_KERNEL )) == NULL) { | 5359 | /* allocate maxwritelen + 1; we'll want a sentinel */ |
5360 | if ((data->wbuffer = kzalloc(33*3 + 1, GFP_KERNEL)) == NULL) { | ||
5367 | kfree (data->rbuffer); | 5361 | kfree (data->rbuffer); |
5368 | kfree (file->private_data); | 5362 | kfree (file->private_data); |
5369 | return -ENOMEM; | 5363 | return -ENOMEM; |
@@ -5372,14 +5366,15 @@ static int proc_SSID_open( struct inode *inode, struct file *file ) { | |||
5372 | 5366 | ||
5373 | readSsidRid(ai, &SSID_rid); | 5367 | readSsidRid(ai, &SSID_rid); |
5374 | ptr = data->rbuffer; | 5368 | ptr = data->rbuffer; |
5375 | for( i = 0; i < 3; i++ ) { | 5369 | for (i = 0; i < 3; i++) { |
5376 | int j; | 5370 | int j; |
5377 | if ( !SSID_rid.ssids[i].len ) break; | 5371 | size_t len = le16_to_cpu(SSID_rid.ssids[i].len); |
5378 | for( j = 0; j < 32 && | 5372 | if (!len) |
5379 | j < SSID_rid.ssids[i].len && | 5373 | break; |
5380 | SSID_rid.ssids[i].ssid[j]; j++ ) { | 5374 | if (len > 32) |
5375 | len = 32; | ||
5376 | for (j = 0; j < len && SSID_rid.ssids[i].ssid[j]; j++) | ||
5381 | *ptr++ = SSID_rid.ssids[i].ssid[j]; | 5377 | *ptr++ = SSID_rid.ssids[i].ssid[j]; |
5382 | } | ||
5383 | *ptr++ = '\n'; | 5378 | *ptr++ = '\n'; |
5384 | } | 5379 | } |
5385 | *ptr = '\0'; | 5380 | *ptr = '\0'; |
@@ -5895,9 +5890,9 @@ static int airo_set_essid(struct net_device *dev, | |||
5895 | memset(SSID_rid.ssids[index].ssid, 0, | 5890 | memset(SSID_rid.ssids[index].ssid, 0, |
5896 | sizeof(SSID_rid.ssids[index].ssid)); | 5891 | sizeof(SSID_rid.ssids[index].ssid)); |
5897 | memcpy(SSID_rid.ssids[index].ssid, extra, dwrq->length); | 5892 | memcpy(SSID_rid.ssids[index].ssid, extra, dwrq->length); |
5898 | SSID_rid.ssids[index].len = dwrq->length; | 5893 | SSID_rid.ssids[index].len = cpu_to_le16(dwrq->length); |
5899 | } | 5894 | } |
5900 | SSID_rid.len = sizeof(SSID_rid); | 5895 | SSID_rid.len = cpu_to_le16(sizeof(SSID_rid)); |
5901 | /* Write it to the card */ | 5896 | /* Write it to the card */ |
5902 | disable_MAC(local, 1); | 5897 | disable_MAC(local, 1); |
5903 | writeSsidRid(local, &SSID_rid, 1); | 5898 | writeSsidRid(local, &SSID_rid, 1); |