Date: Fri, 7 Jan 2000 09:51:14 +1100 From: peter.jeremy@alcatel.com.au To: freefall-gnats@gsmx07.alcatel.com.au Subject: kern/15956: Off-by-1 error in diskstrategy() triggers bug in ATA Message-ID: <00Jan7.095115est.40327@border.alcanet.com.au>
next in thread | raw e-mail | index | archive | help
>Number: 15956
>Category: kern
>Synopsis: Off-by-1 error in diskstrategy()
>Confidential: no
>Severity: serious
>Priority: high
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Thu Jan 6 15:00:01 PST 2000
>Closed-Date:
>Last-Modified:
>Originator: Peter Jeremy
>Release: FreeBSD 4.0-CURRENT i386
>Organization:
>Environment:
cvs-cur 5961
>Description:
The I/O request range check in /sys/kern/subr_disk.c does not
correctly handle an EOF return from dscheck() - instead of
terminating the I/O (returning EOF to the caller), it passes a
zero-length request to the underlying d_strategy() - which
at least for the ATA device can't handle it.
>How-To-Repeat:
# dd if=/dev/rad0c of=/dev/null bs=128k
will report an error at the end of the slice (even if the slice
is a multiple of 128k). The problem does not occur with the
old wd driver (and it shouldn't appear with the wfd, ida or vn
drivers), but appears to affect all other disk devices.
>Fix:
1) Don't pass zero-length requests to the underlying device:
Index: subr_disk.c
===================================================================
RCS file: /home/CVSROOT/src/sys/kern/subr_disk.c,v
retrieving revision 1.16
diff -u -r1.16 subr_disk.c
--- subr_disk.c 1999/12/19 12:36:41 1.16
+++ subr_disk.c 2000/01/06 21:39:34
@@ -193,7 +193,7 @@
return;
}
- if (dscheck(bp, dp->d_slice) < 0) {
+ if (dscheck(bp, dp->d_slice) <= 0) {
biodone(bp);
return;
}
2) Add belt-and-braces checks to ATA device (this code compiles
and links, but I haven't booted from the resultant kernel):
Index: ata-disk.c
===================================================================
RCS file: /home/CVSROOT/src/sys/dev/ata/ata-disk.c,v
retrieving revision 1.47
diff -u -r1.47 ata-disk.c
--- ata-disk.c 1999/12/21 20:18:55 1.47
+++ ata-disk.c 2000/01/06 22:13:09
@@ -301,6 +301,9 @@
struct ad_softc *adp = bp->b_dev->si_drv1;
int32_t s;
+ if (!bp || !bp->b_bcount)
+ return;
+
s = splbio();
bufqdisksort(&adp->queue, bp);
ad_start(adp);
@@ -375,7 +378,7 @@
struct buf *bp = bufq_first(&adp->queue);
struct ad_request *request;
- if (!bp)
+ if (!bp || !bp->b_bcount)
return;
if (!(request = malloc(sizeof(struct ad_request), M_AD, M_NOWAIT))) {
>Release-Note:
>Audit-Trail:
>Unformatted:
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?00Jan7.095115est.40327>
