Skip site navigation (1)Skip section navigation (2)
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>