diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2007-12-19 22:24:16 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 18:09:02 -0500 |
commit | a23ace5f226aea6c8ba04794720502b1aad1dd92 (patch) | |
tree | e742f6a548f7773f8c89090748b7ac331d5ba61c /drivers/net/wireless/airo.c | |
parent | 4293ea33c8a85c3b4401df5df82fc3e070ec0c8e (diff) |
airo: sanitize handling of StatsRid
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 | 78 |
1 files changed, 42 insertions, 36 deletions
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 8eac7fb4521d..9b0714cea75e 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c | |||
@@ -706,9 +706,9 @@ typedef struct { | |||
706 | } StatusRid; | 706 | } StatusRid; |
707 | 707 | ||
708 | typedef struct { | 708 | typedef struct { |
709 | u16 len; | 709 | __le16 len; |
710 | u16 spacer; | 710 | __le16 spacer; |
711 | u32 vals[100]; | 711 | __le32 vals[100]; |
712 | } StatsRid; | 712 | } StatsRid; |
713 | 713 | ||
714 | 714 | ||
@@ -1889,13 +1889,10 @@ static int readCapabilityRid(struct airo_info*ai, CapabilityRid *capr, int lock) | |||
1889 | *s = le16_to_cpu(*s); | 1889 | *s = le16_to_cpu(*s); |
1890 | return rc; | 1890 | return rc; |
1891 | } | 1891 | } |
1892 | static int readStatsRid(struct airo_info*ai, StatsRid *sr, int rid, int lock) { | ||
1893 | int rc = PC4500_readrid(ai, rid, sr, sizeof(*sr), lock); | ||
1894 | u32 *i; | ||
1895 | 1892 | ||
1896 | sr->len = le16_to_cpu(sr->len); | 1893 | static int readStatsRid(struct airo_info*ai, StatsRid *sr, int rid, int lock) |
1897 | for(i = &sr->vals[0]; i <= &sr->vals[99]; i++) *i = le32_to_cpu(*i); | 1894 | { |
1898 | return rc; | 1895 | return PC4500_readrid(ai, rid, sr, sizeof(*sr), lock); |
1899 | } | 1896 | } |
1900 | 1897 | ||
1901 | static void try_auto_wep(struct airo_info *ai) | 1898 | static void try_auto_wep(struct airo_info *ai) |
@@ -2260,9 +2257,10 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) { | |||
2260 | return 0; | 2257 | return 0; |
2261 | } | 2258 | } |
2262 | 2259 | ||
2263 | static void airo_read_stats(struct airo_info *ai) { | 2260 | static void airo_read_stats(struct airo_info *ai) |
2261 | { | ||
2264 | StatsRid stats_rid; | 2262 | StatsRid stats_rid; |
2265 | u32 *vals = stats_rid.vals; | 2263 | __le32 *vals = stats_rid.vals; |
2266 | 2264 | ||
2267 | clear_bit(JOB_STATS, &ai->jobs); | 2265 | clear_bit(JOB_STATS, &ai->jobs); |
2268 | if (ai->power.event) { | 2266 | if (ai->power.event) { |
@@ -2272,20 +2270,23 @@ static void airo_read_stats(struct airo_info *ai) { | |||
2272 | readStatsRid(ai, &stats_rid, RID_STATS, 0); | 2270 | readStatsRid(ai, &stats_rid, RID_STATS, 0); |
2273 | up(&ai->sem); | 2271 | up(&ai->sem); |
2274 | 2272 | ||
2275 | ai->stats.rx_packets = vals[43] + vals[44] + vals[45]; | 2273 | ai->stats.rx_packets = le32_to_cpu(vals[43]) + le32_to_cpu(vals[44]) + |
2276 | ai->stats.tx_packets = vals[39] + vals[40] + vals[41]; | 2274 | le32_to_cpu(vals[45]); |
2277 | ai->stats.rx_bytes = vals[92]; | 2275 | ai->stats.tx_packets = le32_to_cpu(vals[39]) + le32_to_cpu(vals[40]) + |
2278 | ai->stats.tx_bytes = vals[91]; | 2276 | le32_to_cpu(vals[41]); |
2279 | ai->stats.rx_errors = vals[0] + vals[2] + vals[3] + vals[4]; | 2277 | ai->stats.rx_bytes = le32_to_cpu(vals[92]); |
2280 | ai->stats.tx_errors = vals[42] + ai->stats.tx_fifo_errors; | 2278 | ai->stats.tx_bytes = le32_to_cpu(vals[91]); |
2281 | ai->stats.multicast = vals[43]; | 2279 | ai->stats.rx_errors = le32_to_cpu(vals[0]) + le32_to_cpu(vals[2]) + |
2282 | ai->stats.collisions = vals[89]; | 2280 | le32_to_cpu(vals[3]) + le32_to_cpu(vals[4]); |
2281 | ai->stats.tx_errors = le32_to_cpu(vals[42]) + ai->stats.tx_fifo_errors; | ||
2282 | ai->stats.multicast = le32_to_cpu(vals[43]); | ||
2283 | ai->stats.collisions = le32_to_cpu(vals[89]); | ||
2283 | 2284 | ||
2284 | /* detailed rx_errors: */ | 2285 | /* detailed rx_errors: */ |
2285 | ai->stats.rx_length_errors = vals[3]; | 2286 | ai->stats.rx_length_errors = le32_to_cpu(vals[3]); |
2286 | ai->stats.rx_crc_errors = vals[4]; | 2287 | ai->stats.rx_crc_errors = le32_to_cpu(vals[4]); |
2287 | ai->stats.rx_frame_errors = vals[2]; | 2288 | ai->stats.rx_frame_errors = le32_to_cpu(vals[2]); |
2288 | ai->stats.rx_fifo_errors = vals[0]; | 2289 | ai->stats.rx_fifo_errors = le32_to_cpu(vals[0]); |
2289 | } | 2290 | } |
2290 | 2291 | ||
2291 | static struct net_device_stats *airo_get_stats(struct net_device *dev) | 2292 | static struct net_device_stats *airo_get_stats(struct net_device *dev) |
@@ -4741,14 +4742,16 @@ static int proc_stats_open( struct inode *inode, struct file *file ) { | |||
4741 | 4742 | ||
4742 | static int proc_stats_rid_open( struct inode *inode, | 4743 | static int proc_stats_rid_open( struct inode *inode, |
4743 | struct file *file, | 4744 | struct file *file, |
4744 | u16 rid ) { | 4745 | u16 rid ) |
4746 | { | ||
4745 | struct proc_data *data; | 4747 | struct proc_data *data; |
4746 | struct proc_dir_entry *dp = PDE(inode); | 4748 | struct proc_dir_entry *dp = PDE(inode); |
4747 | struct net_device *dev = dp->data; | 4749 | struct net_device *dev = dp->data; |
4748 | struct airo_info *apriv = dev->priv; | 4750 | struct airo_info *apriv = dev->priv; |
4749 | StatsRid stats; | 4751 | StatsRid stats; |
4750 | int i, j; | 4752 | int i, j; |
4751 | u32 *vals = stats.vals; | 4753 | __le32 *vals = stats.vals; |
4754 | int len = le16_to_cpu(stats.len); | ||
4752 | 4755 | ||
4753 | if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) | 4756 | if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) |
4754 | return -ENOMEM; | 4757 | return -ENOMEM; |
@@ -4761,17 +4764,17 @@ static int proc_stats_rid_open( struct inode *inode, | |||
4761 | readStatsRid(apriv, &stats, rid, 1); | 4764 | readStatsRid(apriv, &stats, rid, 1); |
4762 | 4765 | ||
4763 | j = 0; | 4766 | j = 0; |
4764 | for(i=0; statsLabels[i]!=(char *)-1 && | 4767 | for(i=0; statsLabels[i]!=(char *)-1 && i*4<len; i++) { |
4765 | i*4<stats.len; i++){ | ||
4766 | if (!statsLabels[i]) continue; | 4768 | if (!statsLabels[i]) continue; |
4767 | if (j+strlen(statsLabels[i])+16>4096) { | 4769 | if (j+strlen(statsLabels[i])+16>4096) { |
4768 | airo_print_warn(apriv->dev->name, | 4770 | airo_print_warn(apriv->dev->name, |
4769 | "Potentially disasterous buffer overflow averted!"); | 4771 | "Potentially disasterous buffer overflow averted!"); |
4770 | break; | 4772 | break; |
4771 | } | 4773 | } |
4772 | j+=sprintf(data->rbuffer+j, "%s: %u\n", statsLabels[i], vals[i]); | 4774 | j+=sprintf(data->rbuffer+j, "%s: %u\n", statsLabels[i], |
4775 | le32_to_cpu(vals[i])); | ||
4773 | } | 4776 | } |
4774 | if (i*4>=stats.len){ | 4777 | if (i*4 >= len) { |
4775 | airo_print_warn(apriv->dev->name, "Got a short rid"); | 4778 | airo_print_warn(apriv->dev->name, "Got a short rid"); |
4776 | } | 4779 | } |
4777 | data->readlen = j; | 4780 | data->readlen = j; |
@@ -7624,7 +7627,7 @@ static void airo_read_wireless_stats(struct airo_info *local) | |||
7624 | StatusRid status_rid; | 7627 | StatusRid status_rid; |
7625 | StatsRid stats_rid; | 7628 | StatsRid stats_rid; |
7626 | CapabilityRid cap_rid; | 7629 | CapabilityRid cap_rid; |
7627 | u32 *vals = stats_rid.vals; | 7630 | __le32 *vals = stats_rid.vals; |
7628 | 7631 | ||
7629 | /* Get stats out of the card */ | 7632 | /* Get stats out of the card */ |
7630 | clear_bit(JOB_WSTATS, &local->jobs); | 7633 | clear_bit(JOB_WSTATS, &local->jobs); |
@@ -7659,12 +7662,15 @@ static void airo_read_wireless_stats(struct airo_info *local) | |||
7659 | 7662 | ||
7660 | /* Packets discarded in the wireless adapter due to wireless | 7663 | /* Packets discarded in the wireless adapter due to wireless |
7661 | * specific problems */ | 7664 | * specific problems */ |
7662 | local->wstats.discard.nwid = vals[56] + vals[57] + vals[58];/* SSID Mismatch */ | 7665 | local->wstats.discard.nwid = le32_to_cpu(vals[56]) + |
7663 | local->wstats.discard.code = vals[6];/* RxWepErr */ | 7666 | le32_to_cpu(vals[57]) + |
7664 | local->wstats.discard.fragment = vals[30]; | 7667 | le32_to_cpu(vals[58]); /* SSID Mismatch */ |
7665 | local->wstats.discard.retries = vals[10]; | 7668 | local->wstats.discard.code = le32_to_cpu(vals[6]);/* RxWepErr */ |
7666 | local->wstats.discard.misc = vals[1] + vals[32]; | 7669 | local->wstats.discard.fragment = le32_to_cpu(vals[30]); |
7667 | local->wstats.miss.beacon = vals[34]; | 7670 | local->wstats.discard.retries = le32_to_cpu(vals[10]); |
7671 | local->wstats.discard.misc = le32_to_cpu(vals[1]) + | ||
7672 | le32_to_cpu(vals[32]); | ||
7673 | local->wstats.miss.beacon = le32_to_cpu(vals[34]); | ||
7668 | } | 7674 | } |
7669 | 7675 | ||
7670 | static struct iw_statistics *airo_get_wireless_stats(struct net_device *dev) | 7676 | static struct iw_statistics *airo_get_wireless_stats(struct net_device *dev) |