[2.0.30pre3] aic7xxx proc overflow patch.

Gordon Oliver (gordo@telsur.cl)
Wed, 6 Aug 1997 23:42:17 -0400 (CST)


Hi.

This patch fixes a possible nasty bug in the aic7xxx proc info
function. The proc info function had no checking whatsoever for the
file length, and, if there are several LUN #'s on a single device
would happily scribble all over kernel memory. Please add this to the
fixes for 2.0.31

The fix was a simple check placed in several places to guard against
overflow. It is a bit ugly (in that it assumes stuff about the way
scsi proc reads are done), but it should work (doesn't break at least
on my system).

I also killed a static buffer that was only cleared (maybe they
wanted to clear "buffer" instead of "buff"?)

I accidentally deleted the mail of the person who crashed while
looking at the file... could others test this. If the printk's are
ever triggered, it is a bad thing, and blocks will need to be made
smaller.
-gordo
-----------------------------------------------------------------
--- linux/drivers/scsi/aic7xxx_proc.c.pre3 Wed Aug 6 20:43:53 1997
+++ linux/drivers/scsi/aic7xxx_proc.c Wed Aug 6 23:11:32 1997
@@ -76,7 +76,6 @@
{
struct Scsi_Host *HBAptr;
struct aic7xxx_host *p;
- static u8 buff[512];
int i;
int found = FALSE;
int size = 0;
@@ -129,11 +128,6 @@
return (aic7xxx_set_info(buffer, length, HBAptr));
}

- if (offset == 0)
- {
- memset(buff, 0, sizeof(buff));
- }
-
p = (struct aic7xxx_host *) HBAptr->hostdata;

size += sprintf(BLS, "Adaptec AIC7xxx driver version: ");
@@ -142,7 +136,14 @@
#if 0
size += sprintf(BLS, "%s\n", rcs_version(AIC7XXX_SEQ_VER));
#endif
+ if (size > 512)
+ printk(KERN_CRIT "aic7xxx: possible overflow at first position\n");
len += size; pos = begin + len; size = 0;
+ if (pos < offset)
+ {
+ begin = pos;
+ len = 0;
+ }

size += sprintf(BLS, "\n");
size += sprintf(BLS, "Compile Options:\n");
@@ -167,7 +168,16 @@
#else
size += sprintf(BLS, " AIC7XXX_PROC_STATS : Disabled\n");
#endif
+ if (size > 512)
+ printk(KERN_CRIT "aic7xxx: possible overflow at second position\n");
len += size; pos = begin + len; size = 0;
+ if (pos < offset)
+ {
+ begin = pos;
+ len = 0;
+ }
+ else if (pos >= offset + length)
+ goto stop_output;

size += sprintf(BLS, "\n");
size += sprintf(BLS, "Adapter Configuration:\n");
@@ -201,7 +211,16 @@
(p->flags & ULTRA_ENABLED) ? "En" : "Dis");
size += sprintf(BLS, " Target Disconnect: %sabled\n",
p->discenable ? "En" : "Dis");
+ if (size > 512)
+ printk(KERN_CRIT "aic7xxx: possible overflow at third position\n");
len += size; pos = begin + len; size = 0;
+ if (pos < offset)
+ {
+ begin = pos;
+ len = 0;
+ }
+ else if (pos >= offset + length)
+ goto stop_output;

#ifdef AIC7XXX_PROC_STATS
{
@@ -210,6 +229,7 @@

/*
* XXX: Need to fix this to avoid overflow...
+ * Fixed - gordo.
*/
size += sprintf(BLS, "\n");
size += sprintf(BLS, "Statistics:\n");
@@ -247,9 +267,18 @@
sp->w_bins[9]);
size += sprintf(BLS, "\n");
}
+ if (size > 512)
+ printk(KERN_CRIT "aic7xxx: possible overflow at loop %d:%d\n", target, lun);
+ len += size; pos = begin + len; size = 0;
+ if (pos < offset)
+ {
+ begin = pos;
+ len = 0;
+ }
+ else if (pos >= offset + length)
+ goto stop_output;
}
}
- len += size; pos = begin + len; size = 0;
}
#endif /* AIC7XXX_PROC_STATS */

@@ -257,7 +286,11 @@
proc_debug("2pos: %ld offset: %ld len: %d\n", pos, offset, len);
*start = buffer + (offset - begin); /* Start of wanted data */
len -= (offset - begin); /* Start slop */
- if (len > length)
+ if (len < 0)
+ {
+ len = 0; /* off end of file */
+ }
+ else if (len > length)
{
len = length; /* Ending slop */
}