Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 2 Aug 1996 17:27:54 +1000
From:      Bruce Evans <bde@zeta.org.au>
To:        CVS-committers@freefall.freebsd.org, cvs-all@freefall.freebsd.org, cvs-sys@freefall.freebsd.org, peter@freefall.freebsd.org
Subject:   Re: cvs commit:  src/sys/scsi od.c sd.c
Message-ID:  <199608020727.RAA13989@godzilla.zeta.org.au>

next in thread | raw e-mail | index | archive | help
>  Modified:    sys/scsi  od.c sd.c
>  Log:
>  The sd and od drivers didn't check for negative block numbers (like wd.c
>  does) before calling dscheck().  dscheck() doesn't appreciate this and

wd.c is incorrect.  It's stupid to repeat this check in all drivers.  A
complete check involves checking much more than the block number (see
below).  Note that all the cd drivers still haven't been converted to
use dscheck(), so they call bounds_check_with_label(), and neither the
drivers nor bounds_check_with_label() check for negative block numbers.

>  calls Debugger() and returns without setting bp->b_error.

It should set bp->b_error = EINVAL.  It does set bp->b_flags |= B_ERROR.
This should be translated to bp->b_error = EIO if bp->b_error is 0.
Perhaps the critical bug is in biodone() or physio() not doing this
translation.  physio() does the following:

	if (bp->b_flags & B_ERROR) {
		error = bp->b_error;
		goto doerror;
	}
	...
doerror:
	...
	return (error);

The translation seems to only be done in biowait().  I now think that
there should be no translation.  bp->b_flags & B_ERROR should never be
set without setting bp->b_error to nonzero.

>  This can happen when there is a casting error and offsets > 2G are
>  converted to negative off_t's in the disk tools.  (dumpfs used to do this).

The bug for this is in physio().  physio() should check for unrepresentable
block numbers (which can result from both negative off_t's and off_t's
larger than 2**40) and the dscheck() should only check inside an
`#ifdef DIAGNOSTIC' section (unless the check can be folded into normal
checks).

dscheck() also has various overflow possibilities for block numbers
slightly less than the maximum.  Overflows to a negative number may
occur for adding the partition offset, adding the slice offset and
adding the size.  These were supposed to be checked for (at least on 2's
complement machines) provided overflows don't trap and disk sizes are
not near the maximum (maxsz is signless so disk regions than begin near
the maximum appear to be entirely beyond the disk).  I can't see any
fatal errors in the check.  If bp->b_blkno < 0, then the `sz <= 0' case
is reached and dscheck() sets bp->b_error = EINVAL and bp->b_flags |=
B_ERROR and returns an error.

bounds_check_with_label() has the same overflow possibilities but
they aren't checked for at all (maxsz is signed ...).

Bogus bp->b_count's also have interesting overflow possibilities.
E.g., bp->b_bcount = -1 is rounded "up" to sz = 0.

Bruce



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199608020727.RAA13989>