Commit 56d81bd3 authored by Al Viro's avatar Al Viro Committed by David S. Miller

airo: sanitize handling of CapabilityRid

Don't byteswap any fields, annotate.  That has caught a bug,
BTW - will be handled in the next patch.
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent a23ace5f
...@@ -718,32 +718,32 @@ typedef struct { ...@@ -718,32 +718,32 @@ typedef struct {
} APListRid; } APListRid;
typedef struct { typedef struct {
u16 len; __le16 len;
char oui[3]; char oui[3];
char zero; char zero;
u16 prodNum; __le16 prodNum;
char manName[32]; char manName[32];
char prodName[16]; char prodName[16];
char prodVer[8]; char prodVer[8];
char factoryAddr[ETH_ALEN]; char factoryAddr[ETH_ALEN];
char aironetAddr[ETH_ALEN]; char aironetAddr[ETH_ALEN];
u16 radioType; __le16 radioType;
u16 country; __le16 country;
char callid[ETH_ALEN]; char callid[ETH_ALEN];
char supportedRates[8]; char supportedRates[8];
char rxDiversity; char rxDiversity;
char txDiversity; char txDiversity;
u16 txPowerLevels[8]; __le16 txPowerLevels[8];
u16 hardVer; __le16 hardVer;
u16 hardCap; __le16 hardCap;
u16 tempRange; __le16 tempRange;
u16 softVer; __le16 softVer;
u16 softSubVer; __le16 softSubVer;
u16 interfaceVer; __le16 interfaceVer;
u16 softCap; __le16 softCap;
u16 bootBlockVer; __le16 bootBlockVer;
u16 requiredHard; __le16 requiredHard;
u16 extSoftCap; __le16 extSoftCap;
} CapabilityRid; } CapabilityRid;
...@@ -1877,17 +1877,10 @@ static int writeAPListRid(struct airo_info*ai, APListRid *aplr, int lock) { ...@@ -1877,17 +1877,10 @@ static int writeAPListRid(struct airo_info*ai, APListRid *aplr, int lock) {
rc = PC4500_writerid(ai, RID_APLIST, aplr, sizeof(*aplr), lock); rc = PC4500_writerid(ai, RID_APLIST, aplr, sizeof(*aplr), lock);
return rc; return rc;
} }
static int readCapabilityRid(struct airo_info*ai, CapabilityRid *capr, int lock) {
int rc = PC4500_readrid(ai, RID_CAPABILITIES, capr, sizeof(*capr), lock);
u16 *s;
capr->len = le16_to_cpu(capr->len); static int readCapabilityRid(struct airo_info *ai, CapabilityRid *capr, int lock)
capr->prodNum = le16_to_cpu(capr->prodNum); {
capr->radioType = le16_to_cpu(capr->radioType); return PC4500_readrid(ai, RID_CAPABILITIES, capr, sizeof(*capr), lock);
capr->country = le16_to_cpu(capr->country);
for(s = &capr->txPowerLevels[0]; s <= &capr->requiredHard; s++)
*s = le16_to_cpu(*s);
return rc;
} }
static int readStatsRid(struct airo_info*ai, StatsRid *sr, int rid, int lock) static int readStatsRid(struct airo_info*ai, StatsRid *sr, int rid, int lock)
...@@ -2773,8 +2766,9 @@ static int airo_test_wpa_capable(struct airo_info *ai) ...@@ -2773,8 +2766,9 @@ static int airo_test_wpa_capable(struct airo_info *ai)
if (status != SUCCESS) return 0; if (status != SUCCESS) return 0;
/* Only firmware versions 5.30.17 or better can do WPA */ /* Only firmware versions 5.30.17 or better can do WPA */
if ((cap_rid.softVer > 0x530) if (le16_to_cpu(cap_rid.softVer) > 0x530
|| ((cap_rid.softVer == 0x530) && (cap_rid.softSubVer >= 17))) { || (le16_to_cpu(cap_rid.softVer) == 0x530
&& le16_to_cpu(cap_rid.softSubVer) >= 17)) {
airo_print_info("", "WPA is supported."); airo_print_info("", "WPA is supported.");
return 1; return 1;
} }
...@@ -3809,7 +3803,7 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) ...@@ -3809,7 +3803,7 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
else { else {
kfree(ai->rssi); kfree(ai->rssi);
ai->rssi = NULL; ai->rssi = NULL;
if (cap_rid.softCap & 8) if (cap_rid.softCap & cpu_to_le16(8))
ai->config.rmode |= RXMODE_NORMALIZED_RSSI; ai->config.rmode |= RXMODE_NORMALIZED_RSSI;
else else
airo_print_warn(ai->dev->name, "unknown received signal " airo_print_warn(ai->dev->name, "unknown received signal "
...@@ -3819,9 +3813,9 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) ...@@ -3819,9 +3813,9 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
ai->config.authType = AUTH_OPEN; ai->config.authType = AUTH_OPEN;
ai->config.modulation = MOD_CCK; ai->config.modulation = MOD_CCK;
if ((cap_rid.len>=sizeof(cap_rid)) && if (le16_to_cpu(cap_rid.len) >= sizeof(cap_rid) &&
(cap_rid.extSoftCap & cpu_to_le16(1)) && (cap_rid.extSoftCap & cpu_to_le16(1)) &&
(micsetup(ai) == SUCCESS)) { micsetup(ai) == SUCCESS) {
ai->config.opmode |= MODE_MIC; ai->config.opmode |= MODE_MIC;
set_bit(FLAG_MIC_CAPABLE, &ai->flags); set_bit(FLAG_MIC_CAPABLE, &ai->flags);
} }
...@@ -4717,12 +4711,12 @@ static int proc_status_open( struct inode *inode, struct file *file ) { ...@@ -4717,12 +4711,12 @@ static int proc_status_open( struct inode *inode, struct file *file ) {
cap_rid.prodName, cap_rid.prodName,
cap_rid.manName, cap_rid.manName,
cap_rid.prodVer, cap_rid.prodVer,
cap_rid.radioType, le16_to_cpu(cap_rid.radioType),
cap_rid.country, le16_to_cpu(cap_rid.country),
cap_rid.hardVer, le16_to_cpu(cap_rid.hardVer),
(int)cap_rid.softVer, le16_to_cpu(cap_rid.softVer),
(int)cap_rid.softSubVer, le16_to_cpu(cap_rid.softSubVer),
(int)cap_rid.bootBlockVer ); le16_to_cpu(cap_rid.bootBlockVer));
data->readlen = strlen( data->rbuffer ); data->readlen = strlen( data->rbuffer );
return 0; return 0;
} }
...@@ -5734,20 +5728,24 @@ static int airo_get_quality (StatusRid *status_rid, CapabilityRid *cap_rid) ...@@ -5734,20 +5728,24 @@ static int airo_get_quality (StatusRid *status_rid, CapabilityRid *cap_rid)
{ {
int quality = 0; int quality = 0;
if ((status_rid->mode & 0x3f) == 0x3f && (cap_rid->hardCap & 8)) { if ((status_rid->mode & 0x3f) != 0x3f)
if (memcmp(cap_rid->prodName, "350", 3)) return 0;
if (status_rid->signalQuality > 0x20)
quality = 0; if (!(cap_rid->hardCap & cpu_to_le16(8)))
else return 0;
quality = 0x20 - status_rid->signalQuality;
if (memcmp(cap_rid->prodName, "350", 3))
if (status_rid->signalQuality > 0x20)
quality = 0;
else else
if (status_rid->signalQuality > 0xb0) quality = 0x20 - status_rid->signalQuality;
quality = 0; else
else if (status_rid->signalQuality < 0x10) if (status_rid->signalQuality > 0xb0)
quality = 0xa0; quality = 0;
else else if (status_rid->signalQuality < 0x10)
quality = 0xb0 - status_rid->signalQuality; quality = 0xa0;
} else
quality = 0xb0 - status_rid->signalQuality;
return quality; return quality;
} }
...@@ -6289,6 +6287,13 @@ static int airo_get_mode(struct net_device *dev, ...@@ -6289,6 +6287,13 @@ static int airo_get_mode(struct net_device *dev,
return 0; return 0;
} }
static inline int valid_index(CapabilityRid *p, int index)
{
if (index < 0)
return 0;
return index < (p->softCap & cpu_to_le16(0x80) ? 4 : 1);
}
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
/* /*
* Wireless Handler : set Encryption Key * Wireless Handler : set Encryption Key
...@@ -6306,7 +6311,7 @@ static int airo_set_encode(struct net_device *dev, ...@@ -6306,7 +6311,7 @@ static int airo_set_encode(struct net_device *dev,
/* Is WEP supported ? */ /* Is WEP supported ? */
readCapabilityRid(local, &cap_rid, 1); readCapabilityRid(local, &cap_rid, 1);
/* Older firmware doesn't support this... /* Older firmware doesn't support this...
if(!(cap_rid.softCap & 2)) { if(!(cap_rid.softCap & cpu_to_le16(2))) {
return -EOPNOTSUPP; return -EOPNOTSUPP;
} */ } */
readConfigRid(local, 1); readConfigRid(local, 1);
...@@ -6326,7 +6331,7 @@ static int airo_set_encode(struct net_device *dev, ...@@ -6326,7 +6331,7 @@ static int airo_set_encode(struct net_device *dev,
return -EINVAL; return -EINVAL;
} }
/* Check the index (none -> use current) */ /* Check the index (none -> use current) */
if ((index < 0) || (index >= ((cap_rid.softCap & 0x80) ? 4:1))) if (!valid_index(&cap_rid, index))
index = current_index; index = current_index;
/* Set the length */ /* Set the length */
if (dwrq->length > MIN_KEY_SIZE) if (dwrq->length > MIN_KEY_SIZE)
...@@ -6356,7 +6361,7 @@ static int airo_set_encode(struct net_device *dev, ...@@ -6356,7 +6361,7 @@ static int airo_set_encode(struct net_device *dev,
} else { } else {
/* Do we want to just set the transmit key index ? */ /* Do we want to just set the transmit key index ? */
int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
if ((index >= 0) && (index < ((cap_rid.softCap & 0x80)?4:1))) { if (valid_index(&cap_rid, index)) {
set_wep_key(local, index, NULL, 0, perm, 1); set_wep_key(local, index, NULL, 0, perm, 1);
} else } else
/* Don't complain if only change the mode */ /* Don't complain if only change the mode */
...@@ -6391,7 +6396,7 @@ static int airo_get_encode(struct net_device *dev, ...@@ -6391,7 +6396,7 @@ static int airo_get_encode(struct net_device *dev,
/* Is it supported ? */ /* Is it supported ? */
readCapabilityRid(local, &cap_rid, 1); readCapabilityRid(local, &cap_rid, 1);
if(!(cap_rid.softCap & 2)) { if(!(cap_rid.softCap & cpu_to_le16(2))) {
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
readConfigRid(local, 1); readConfigRid(local, 1);
...@@ -6413,7 +6418,7 @@ static int airo_get_encode(struct net_device *dev, ...@@ -6413,7 +6418,7 @@ static int airo_get_encode(struct net_device *dev,
memset(extra, 0, 16); memset(extra, 0, 16);
/* Which key do we want ? -1 -> tx index */ /* Which key do we want ? -1 -> tx index */
if ((index < 0) || (index >= ((cap_rid.softCap & 0x80) ? 4 : 1))) if (!valid_index(&cap_rid, index))
index = get_wep_key(local, 0xffff); index = get_wep_key(local, 0xffff);
dwrq->flags |= index + 1; dwrq->flags |= index + 1;
/* Copy the key to the user buffer */ /* Copy the key to the user buffer */
...@@ -6445,7 +6450,7 @@ static int airo_set_encodeext(struct net_device *dev, ...@@ -6445,7 +6450,7 @@ static int airo_set_encodeext(struct net_device *dev,
/* Is WEP supported ? */ /* Is WEP supported ? */
readCapabilityRid(local, &cap_rid, 1); readCapabilityRid(local, &cap_rid, 1);
/* Older firmware doesn't support this... /* Older firmware doesn't support this...
if(!(cap_rid.softCap & 2)) { if(!(cap_rid.softCap & cpu_to_le16(2))) {
return -EOPNOTSUPP; return -EOPNOTSUPP;
} */ } */
readConfigRid(local, 1); readConfigRid(local, 1);
...@@ -6453,7 +6458,7 @@ static int airo_set_encodeext(struct net_device *dev, ...@@ -6453,7 +6458,7 @@ static int airo_set_encodeext(struct net_device *dev,
/* Determine and validate the key index */ /* Determine and validate the key index */
idx = encoding->flags & IW_ENCODE_INDEX; idx = encoding->flags & IW_ENCODE_INDEX;
if (idx) { if (idx) {
if (idx < 1 || idx > ((cap_rid.softCap & 0x80) ? 4:1)) if (!valid_index(&cap_rid, idx - 1))
return -EINVAL; return -EINVAL;
idx--; idx--;
} else } else
...@@ -6527,7 +6532,7 @@ static int airo_get_encodeext(struct net_device *dev, ...@@ -6527,7 +6532,7 @@ static int airo_get_encodeext(struct net_device *dev,
/* Is it supported ? */ /* Is it supported ? */
readCapabilityRid(local, &cap_rid, 1); readCapabilityRid(local, &cap_rid, 1);
if(!(cap_rid.softCap & 2)) { if(!(cap_rid.softCap & cpu_to_le16(2))) {
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
readConfigRid(local, 1); readConfigRid(local, 1);
...@@ -6538,7 +6543,7 @@ static int airo_get_encodeext(struct net_device *dev, ...@@ -6538,7 +6543,7 @@ static int airo_get_encodeext(struct net_device *dev,
idx = encoding->flags & IW_ENCODE_INDEX; idx = encoding->flags & IW_ENCODE_INDEX;
if (idx) { if (idx) {
if (idx < 1 || idx > ((cap_rid.softCap & 0x80) ? 4:1)) if (!valid_index(&cap_rid, idx - 1))
return -EINVAL; return -EINVAL;
idx--; idx--;
} else } else
...@@ -6716,7 +6721,7 @@ static int airo_set_txpow(struct net_device *dev, ...@@ -6716,7 +6721,7 @@ static int airo_set_txpow(struct net_device *dev,
} }
clear_bit (FLAG_RADIO_OFF, &local->flags); clear_bit (FLAG_RADIO_OFF, &local->flags);
for (i = 0; cap_rid.txPowerLevels[i] && (i < 8); i++) for (i = 0; cap_rid.txPowerLevels[i] && (i < 8); i++)
if ((vwrq->value==cap_rid.txPowerLevels[i])) { if (vwrq->value == le16_to_cpu(cap_rid.txPowerLevels[i])) {
readConfigRid(local, 1); readConfigRid(local, 1);
local->config.txPower = vwrq->value; local->config.txPower = vwrq->value;
set_bit (FLAG_COMMIT, &local->flags); set_bit (FLAG_COMMIT, &local->flags);
...@@ -6888,16 +6893,17 @@ static int airo_get_range(struct net_device *dev, ...@@ -6888,16 +6893,17 @@ static int airo_get_range(struct net_device *dev,
range->min_frag = 256; range->min_frag = 256;
range->max_frag = AIRO_DEF_MTU; range->max_frag = AIRO_DEF_MTU;
if(cap_rid.softCap & 2) { if(cap_rid.softCap & cpu_to_le16(2)) {
// WEP: RC4 40 bits // WEP: RC4 40 bits
range->encoding_size[0] = 5; range->encoding_size[0] = 5;
// RC4 ~128 bits // RC4 ~128 bits
if (cap_rid.softCap & 0x100) { if (cap_rid.softCap & cpu_to_le16(0x100)) {
range->encoding_size[1] = 13; range->encoding_size[1] = 13;
range->num_encoding_sizes = 2; range->num_encoding_sizes = 2;
} else } else
range->num_encoding_sizes = 1; range->num_encoding_sizes = 1;
range->max_encoding_tokens = (cap_rid.softCap & 0x80) ? 4 : 1; range->max_encoding_tokens =
cap_rid.softCap & cpu_to_le16(0x80) ? 4 : 1;
} else { } else {
range->num_encoding_sizes = 0; range->num_encoding_sizes = 0;
range->max_encoding_tokens = 0; range->max_encoding_tokens = 0;
...@@ -6912,7 +6918,7 @@ static int airo_get_range(struct net_device *dev, ...@@ -6912,7 +6918,7 @@ static int airo_get_range(struct net_device *dev,
/* Transmit Power - values are in mW */ /* Transmit Power - values are in mW */
for(i = 0 ; i < 8 ; i++) { for(i = 0 ; i < 8 ; i++) {
range->txpower[i] = cap_rid.txPowerLevels[i]; range->txpower[i] = le16_to_cpu(cap_rid.txPowerLevels[i]);
if(range->txpower[i] == 0) if(range->txpower[i] == 0)
break; break;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment