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: 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 9b0714c..e139a18 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -718,32 +718,32 @@
} APListRid;
typedef struct {
- u16 len;
+ __le16 len;
char oui[3];
char zero;
- u16 prodNum;
+ __le16 prodNum;
char manName[32];
char prodName[16];
char prodVer[8];
char factoryAddr[ETH_ALEN];
char aironetAddr[ETH_ALEN];
- u16 radioType;
- u16 country;
+ __le16 radioType;
+ __le16 country;
char callid[ETH_ALEN];
char supportedRates[8];
char rxDiversity;
char txDiversity;
- u16 txPowerLevels[8];
- u16 hardVer;
- u16 hardCap;
- u16 tempRange;
- u16 softVer;
- u16 softSubVer;
- u16 interfaceVer;
- u16 softCap;
- u16 bootBlockVer;
- u16 requiredHard;
- u16 extSoftCap;
+ __le16 txPowerLevels[8];
+ __le16 hardVer;
+ __le16 hardCap;
+ __le16 tempRange;
+ __le16 softVer;
+ __le16 softSubVer;
+ __le16 interfaceVer;
+ __le16 softCap;
+ __le16 bootBlockVer;
+ __le16 requiredHard;
+ __le16 extSoftCap;
} CapabilityRid;
@@ -1877,17 +1877,10 @@
rc = PC4500_writerid(ai, RID_APLIST, aplr, sizeof(*aplr), lock);
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);
- capr->prodNum = le16_to_cpu(capr->prodNum);
- capr->radioType = le16_to_cpu(capr->radioType);
- 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 readCapabilityRid(struct airo_info *ai, CapabilityRid *capr, int lock)
+{
+ return PC4500_readrid(ai, RID_CAPABILITIES, capr, sizeof(*capr), lock);
}
static int readStatsRid(struct airo_info*ai, StatsRid *sr, int rid, int lock)
@@ -2773,8 +2766,9 @@
if (status != SUCCESS) return 0;
/* Only firmware versions 5.30.17 or better can do WPA */
- if ((cap_rid.softVer > 0x530)
- || ((cap_rid.softVer == 0x530) && (cap_rid.softSubVer >= 17))) {
+ if (le16_to_cpu(cap_rid.softVer) > 0x530
+ || (le16_to_cpu(cap_rid.softVer) == 0x530
+ && le16_to_cpu(cap_rid.softSubVer) >= 17)) {
airo_print_info("", "WPA is supported.");
return 1;
}
@@ -3809,7 +3803,7 @@
else {
kfree(ai->rssi);
ai->rssi = NULL;
- if (cap_rid.softCap & 8)
+ if (cap_rid.softCap & cpu_to_le16(8))
ai->config.rmode |= RXMODE_NORMALIZED_RSSI;
else
airo_print_warn(ai->dev->name, "unknown received signal "
@@ -3819,9 +3813,9 @@
ai->config.authType = AUTH_OPEN;
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)) &&
- (micsetup(ai) == SUCCESS)) {
+ micsetup(ai) == SUCCESS) {
ai->config.opmode |= MODE_MIC;
set_bit(FLAG_MIC_CAPABLE, &ai->flags);
}
@@ -4717,12 +4711,12 @@
cap_rid.prodName,
cap_rid.manName,
cap_rid.prodVer,
- cap_rid.radioType,
- cap_rid.country,
- cap_rid.hardVer,
- (int)cap_rid.softVer,
- (int)cap_rid.softSubVer,
- (int)cap_rid.bootBlockVer );
+ le16_to_cpu(cap_rid.radioType),
+ le16_to_cpu(cap_rid.country),
+ le16_to_cpu(cap_rid.hardVer),
+ le16_to_cpu(cap_rid.softVer),
+ le16_to_cpu(cap_rid.softSubVer),
+ le16_to_cpu(cap_rid.bootBlockVer));
data->readlen = strlen( data->rbuffer );
return 0;
}
@@ -5734,20 +5728,24 @@
{
int quality = 0;
- if ((status_rid->mode & 0x3f) == 0x3f && (cap_rid->hardCap & 8)) {
- if (memcmp(cap_rid->prodName, "350", 3))
- if (status_rid->signalQuality > 0x20)
- quality = 0;
- else
- quality = 0x20 - status_rid->signalQuality;
+ if ((status_rid->mode & 0x3f) != 0x3f)
+ return 0;
+
+ if (!(cap_rid->hardCap & cpu_to_le16(8)))
+ return 0;
+
+ if (memcmp(cap_rid->prodName, "350", 3))
+ if (status_rid->signalQuality > 0x20)
+ quality = 0;
else
- if (status_rid->signalQuality > 0xb0)
- quality = 0;
- else if (status_rid->signalQuality < 0x10)
- quality = 0xa0;
- else
- quality = 0xb0 - status_rid->signalQuality;
- }
+ quality = 0x20 - status_rid->signalQuality;
+ else
+ if (status_rid->signalQuality > 0xb0)
+ quality = 0;
+ else if (status_rid->signalQuality < 0x10)
+ quality = 0xa0;
+ else
+ quality = 0xb0 - status_rid->signalQuality;
return quality;
}
@@ -6289,6 +6287,13 @@
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
@@ -6306,7 +6311,7 @@
/* Is WEP supported ? */
readCapabilityRid(local, &cap_rid, 1);
/* Older firmware doesn't support this...
- if(!(cap_rid.softCap & 2)) {
+ if(!(cap_rid.softCap & cpu_to_le16(2))) {
return -EOPNOTSUPP;
} */
readConfigRid(local, 1);
@@ -6326,7 +6331,7 @@
return -EINVAL;
}
/* 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;
/* Set the length */
if (dwrq->length > MIN_KEY_SIZE)
@@ -6356,7 +6361,7 @@
} else {
/* Do we want to just set the transmit key index ? */
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);
} else
/* Don't complain if only change the mode */
@@ -6391,7 +6396,7 @@
/* Is it supported ? */
readCapabilityRid(local, &cap_rid, 1);
- if(!(cap_rid.softCap & 2)) {
+ if(!(cap_rid.softCap & cpu_to_le16(2))) {
return -EOPNOTSUPP;
}
readConfigRid(local, 1);
@@ -6413,7 +6418,7 @@
memset(extra, 0, 16);
/* 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);
dwrq->flags |= index + 1;
/* Copy the key to the user buffer */
@@ -6445,7 +6450,7 @@
/* Is WEP supported ? */
readCapabilityRid(local, &cap_rid, 1);
/* Older firmware doesn't support this...
- if(!(cap_rid.softCap & 2)) {
+ if(!(cap_rid.softCap & cpu_to_le16(2))) {
return -EOPNOTSUPP;
} */
readConfigRid(local, 1);
@@ -6453,7 +6458,7 @@
/* Determine and validate the key index */
idx = encoding->flags & IW_ENCODE_INDEX;
if (idx) {
- if (idx < 1 || idx > ((cap_rid.softCap & 0x80) ? 4:1))
+ if (!valid_index(&cap_rid, idx - 1))
return -EINVAL;
idx--;
} else
@@ -6527,7 +6532,7 @@
/* Is it supported ? */
readCapabilityRid(local, &cap_rid, 1);
- if(!(cap_rid.softCap & 2)) {
+ if(!(cap_rid.softCap & cpu_to_le16(2))) {
return -EOPNOTSUPP;
}
readConfigRid(local, 1);
@@ -6538,7 +6543,7 @@
idx = encoding->flags & IW_ENCODE_INDEX;
if (idx) {
- if (idx < 1 || idx > ((cap_rid.softCap & 0x80) ? 4:1))
+ if (!valid_index(&cap_rid, idx - 1))
return -EINVAL;
idx--;
} else
@@ -6716,7 +6721,7 @@
}
clear_bit (FLAG_RADIO_OFF, &local->flags);
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);
local->config.txPower = vwrq->value;
set_bit (FLAG_COMMIT, &local->flags);
@@ -6888,16 +6893,17 @@
range->min_frag = 256;
range->max_frag = AIRO_DEF_MTU;
- if(cap_rid.softCap & 2) {
+ if(cap_rid.softCap & cpu_to_le16(2)) {
// WEP: RC4 40 bits
range->encoding_size[0] = 5;
// RC4 ~128 bits
- if (cap_rid.softCap & 0x100) {
+ if (cap_rid.softCap & cpu_to_le16(0x100)) {
range->encoding_size[1] = 13;
range->num_encoding_sizes = 2;
} else
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 {
range->num_encoding_sizes = 0;
range->max_encoding_tokens = 0;
@@ -6912,7 +6918,7 @@
/* Transmit Power - values are in mW */
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)
break;
}