summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoel Kluin <roel.kluin@gmail.com>2009-02-12 16:52:31 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2009-02-20 14:40:22 -0800
commit952367c3f56b126ac04c88c7b3cb4f08d5708091 (patch)
tree1bb018ca6fc452683445ab003fe1aa4967eaace8
parent64cc2eaf399ac38469833bda5d6b219d815d084d (diff)
3c505: do not set pcb->data.raw beyond its size
commit 501aa061bd68169a5b54c123641f8dfa9ad31545 upstream. Ensure that we do not set pcb->data.raw beyond its size, print an error message and return false if we attempt to. A timout message was printed one too early. Signed-off-by: Roel Kluin <roel.kluin@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/net/3c505.c26
1 files changed, 16 insertions, 10 deletions
diff --git a/drivers/net/3c505.c b/drivers/net/3c505.c
index a424869707a5..3d11a7f0bbf2 100644
--- a/drivers/net/3c505.c
+++ b/drivers/net/3c505.c
@@ -493,21 +493,27 @@ static bool receive_pcb(struct net_device *dev, pcb_struct * pcb)
}
/* read the data */
spin_lock_irqsave(&adapter->lock, flags);
- i = 0;
- do {
- j = 0;
- while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && j++ < 20000);
- pcb->data.raw[i++] = inb_command(dev->base_addr);
- if (i > MAX_PCB_DATA)
- INVALID_PCB_MSG(i);
- } while ((stat & ASF_PCB_MASK) != ASF_PCB_END && j < 20000);
+ for (i = 0; i < MAX_PCB_DATA; i++) {
+ for (j = 0; j < 20000; j++) {
+ stat = get_status(dev->base_addr);
+ if (stat & ACRF)
+ break;
+ }
+ pcb->data.raw[i] = inb_command(dev->base_addr);
+ if ((stat & ASF_PCB_MASK) == ASF_PCB_END || j >= 20000)
+ break;
+ }
spin_unlock_irqrestore(&adapter->lock, flags);
+ if (i >= MAX_PCB_DATA) {
+ INVALID_PCB_MSG(i);
+ return false;
+ }
if (j >= 20000) {
TIMEOUT_MSG(__LINE__);
return false;
}
- /* woops, the last "data" byte was really the length! */
- total_length = pcb->data.raw[--i];
+ /* the last "data" byte was really the length! */
+ total_length = pcb->data.raw[i];
/* safety check total length vs data length */
if (total_length != (pcb->length + 2)) {