Subject: kern/3748: bdwrite() can reference bdevsw with an invalid index
To: None <gnats-bugs@gnats.netbsd.org>
From: None <mhitch@gemini.oscs.montana.edu>
List: netbsd-bugs
Date: 06/13/1997 21:04:09
>Number: 3748
>Category: kern
>Synopsis: bdwrite() can access bdevsw with an invalid index
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: kern-bug-people (Kernel Bug People)
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Fri Jun 13 20:20:01 1997
>Last-Modified:
>Originator: Michael L Hitch
>Organization:
Montana State University
>Release: NetBSD-current June 12, 1997
>Environment:
System: NetBSD news.oscs.montana.edu 1.2G NetBSD 1.2G (R4000) #970612TX-5: Fri Jun 13 20:18:41 MDT 1997 mhitch@news.oscs.montana.edu:/d/d/sys.new/arch/pmax/compile/R4000 pmax
>Description:
It would appear that bdwrite() can be passed a buffer with NODEV in
b_dev. This can cause a bad index into bdevsw[] when bdwrite()
makes the test to see if the device is a tape. If you happen to
be unlucky and the memory location contains D_TAPE [which is the
case for pmax in -current], the buffer is written out. This can
cause a significant decrease in file write performance.
>How-To-Repeat:
To demonstrate the file write degradation, bdevsw[255].d_type needs
to be equal to D_TAPE. The -current pmax GENERIC kernel meets this
condition. Inserting dummy data initialized to 1 at the correct
location addressed by bdevsw[255].d_type can be used to demonstrate
this as well. Running iozone on a DECstation 5000 results in
write rates 3 to 4 times slower than possible.
Adding a printf() in bdwrite() to check for a invalid index by
checking major(bp->b_dev) against nblkdev shows that bdwrite()
gets called with 0xffffffff and 0x0000ff00 in b_dev. I don't
know enough about how bdwrite() is used to know if those values
are valid, but they should not be used to index bdevsw.
>Fix:
To prevent accessing bdevsw[] with a bad index, the index should
be checked for a valid value (i.e. < nblkdev).
*** /c/work/src/sys/kern/vfs_bio.c Sat May 17 22:43:33 1997
--- sys/kern/vfs_bio.c Thu Jun 12 19:29:30 1997
***************
*** 357,363 ****
struct proc *p = (curproc != NULL ? curproc : &proc0); /* XXX */
/* If this is a tape block, write the block now. */
! if (bdevsw[major(bp->b_dev)].d_type == D_TAPE) {
bawrite(bp);
return;
}
--- 357,364 ----
struct proc *p = (curproc != NULL ? curproc : &proc0); /* XXX */
/* If this is a tape block, write the block now. */
! if (major(bp->b_dev) < nblkdev &&
! bdevsw[major(bp->b_dev)].d_type == D_TAPE) {
bawrite(bp);
return;
}
>Audit-Trail:
>Unformatted: