From owner-freebsd-current Wed Jun 5 17:45:39 2002 Delivered-To: freebsd-current@freebsd.org Received: from mailman.zeta.org.au (mailman.zeta.org.au [203.26.10.16]) by hub.freebsd.org (Postfix) with ESMTP id 5505437B882 for ; Wed, 5 Jun 2002 17:39:50 -0700 (PDT) Received: from bde.zeta.org.au (bde.zeta.org.au [203.2.228.102]) by mailman.zeta.org.au (8.9.3/8.8.7) with ESMTP id KAA04413; Thu, 6 Jun 2002 10:36:35 +1000 Date: Thu, 6 Jun 2002 10:37:12 +1000 (EST) From: Bruce Evans X-X-Sender: bde@gamplex.bde.org To: Brooks Davis Cc: current@FreeBSD.ORG Subject: Re: dump (via amanda) causing panics In-Reply-To: <20020605161454.A22201@Odin.AC.HMC.Edu> Message-ID: <20020606100455.N9476-100000@gamplex.bde.org> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG On Wed, 5 Jun 2002, Brooks Davis wrote: > For the last week or so I've had my laptop panic every time amanda did > a dump of it. This happens with a kernel as of yesterday so it probably > wasn't just a bad update. > > Before the crash I see the following in dmesg: > > ad0: count 6359632 size transfers not supported > bus_dmamap_load: Too many segs! buf_len = 0xc204abb0 > ad0: READ command tiemotu tag=0 serv=0 - resetting > ad0: resetting devices .. done > [the above repeated twice more] > ad0: count 6359632 size transfers not supported > bus_dmamap_load: Too many segs! buf_len = 0xc204abb0 > ad0: READ command tiemotu tag=0 serv=0 - resetting > ad0: trying to fall back to PIO mode > ad0: resetting devices .. done > ad0: count 6359632 size transfers not supported > PANIC This is caused by: (1) amanda attempting to read from a bad offset on the device. Almost any offset that causes a block number of >= 2GB or 4GB will trigger the kernel bug. (2) the bounds checking in dscheck() being 64-bit daddr_t casualty (*blush*). I just committed this fix which I had been sitting on this fix for too long: %%% Index: subr_diskslice.c =================================================================== RCS file: /home/ncvs/src/sys/kern/subr_diskslice.c,v retrieving revision 1.103 diff -u -2 -r1.103 subr_diskslice.c --- subr_diskslice.c 12 May 2002 20:49:41 -0000 1.103 +++ subr_diskslice.c 23 May 2002 14:10:26 -0000 @@ -57,4 +57,5 @@ #include #include +#include #include #include @@ -225,5 +226,5 @@ /* beyond partition? */ - if (secno + nsec > endsecno) { + if ((uintmax_t)secno + nsec > endsecno) { /* if exactly at end of disk, return an EOF */ if (secno == endsecno) { @@ -232,10 +233,9 @@ } /* or truncate if part of it fits */ - nsec = endsecno - secno; - if (nsec <= 0) { + if (secno > endsecno) { bp->bio_error = EINVAL; goto bad; } - bp->bio_bcount = nsec * ssp->dss_secsize; + bp->bio_bcount = (endsecno - secno) * ssp->dss_secsize; } %%% This fixes 2 overflow bugs. The main one is in the second hunk. Offsets way beyond the end of the disk caused "truncation" to actually expand the block to a huge one. (`nsec = endsecno - secno' subtracts a daddr_t that is known to be positive from a u_long and stores the result in a long, so overflow used to be only possible (for the assignment only) for physical disks with more than 2GB sectors, but it is now possible for byte offsets larger than 1TB which are much cheaper than 1TB disks.) Device drivers that check the bounds directly probably have variants of this bug. Ones that use the deprecated bounds_check_with_label() (mainly ccd and drivers for ancient cdroms) certainly do. Bruce To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message