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

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
Loading
Loading
Loading
Loading
+69 −63
Original line number Diff line number Diff line
@@ -718,32 +718,32 @@ typedef struct {
} 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 @@ static int writeAPListRid(struct airo_info*ai, APListRid *aplr, int lock) {
	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 @@ static int airo_test_wpa_capable(struct airo_info *ai)
	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 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
		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 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
		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 @@ static int proc_status_open( struct inode *inode, struct file *file ) {
		 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,7 +5728,12 @@ static int airo_get_quality (StatusRid *status_rid, CapabilityRid *cap_rid)
{
	int quality = 0;

	if ((status_rid->mode & 0x3f) == 0x3f && (cap_rid->hardCap & 8)) {
	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;
@@ -5747,7 +5746,6 @@ static int airo_get_quality (StatusRid *status_rid, CapabilityRid *cap_rid)
			quality = 0xa0;
		else
			quality = 0xb0 - status_rid->signalQuality;
	}
	return quality;
}

@@ -6289,6 +6287,13 @@ static int airo_get_mode(struct net_device *dev,
	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 @@ static int airo_set_encode(struct net_device *dev,
	/* 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 @@ static int airo_set_encode(struct net_device *dev,
			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 @@ static int airo_set_encode(struct net_device *dev,
	} 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 @@ static int airo_get_encode(struct net_device *dev,

	/* 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 @@ static int airo_get_encode(struct net_device *dev,
	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 @@ static int airo_set_encodeext(struct net_device *dev,
	/* 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 @@ static int airo_set_encodeext(struct net_device *dev,
	/* 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 @@ static int airo_get_encodeext(struct net_device *dev,

	/* 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 @@ static int airo_get_encodeext(struct net_device *dev,

	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 @@ static int airo_set_txpow(struct net_device *dev,
	}
	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 @@ static int airo_get_range(struct net_device *dev,
	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 @@ static int airo_get_range(struct net_device *dev,

	/* 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;
	}