From owner-freebsd-bugs@FreeBSD.ORG Sat Dec 29 21:30:01 2007 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id CCAFF16A421 for ; Sat, 29 Dec 2007 21:30:01 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id AA6BC13C478 for ; Sat, 29 Dec 2007 21:30:01 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.14.2/8.14.2) with ESMTP id lBTLU1eM044891 for ; Sat, 29 Dec 2007 21:30:01 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.2/8.14.1/Submit) id lBTLU1el044888; Sat, 29 Dec 2007 21:30:01 GMT (envelope-from gnats) Resent-Date: Sat, 29 Dec 2007 21:30:01 GMT Resent-Message-Id: <200712292130.lBTLU1el044888@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Jens Rehsack Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id BEEA716A418 for ; Sat, 29 Dec 2007 21:28:29 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21]) by mx1.freebsd.org (Postfix) with ESMTP id ABF4113C458 for ; Sat, 29 Dec 2007 21:28:29 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.14.2/8.14.2) with ESMTP id lBTLRlUZ048662 for ; Sat, 29 Dec 2007 21:27:47 GMT (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.14.2/8.14.1/Submit) id lBTLRljV048661; Sat, 29 Dec 2007 21:27:47 GMT (envelope-from nobody) Message-Id: <200712292127.lBTLRljV048661@www.freebsd.org> Date: Sat, 29 Dec 2007 21:27:47 GMT From: Jens Rehsack To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Cc: Subject: kern/119144: spontaneous iir(4) crash in probe phase X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 29 Dec 2007 21:30:01 -0000 >Number: 119144 >Category: kern >Synopsis: spontaneous iir(4) crash in probe phase >Confidential: no >Severity: critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Sat Dec 29 21:30:01 UTC 2007 >Closed-Date: >Last-Modified: >Originator: Jens Rehsack >Release: 7.0-PRERELEASE >Organization: >Environment: FreeBSD netfinity.muppets.liwing.de 7.0-PRERELEASE FreeBSD 7.0-PRERELEASE #18: Sat Dec 29 20:40:00 UTC 2007 root@netfinity:/usr/obj/usr/src/sys/NETFINITY i386 >Description: When FreeBSD 7.0-BETA1 came out, I started some initial tests (abilities, how does it feel - just to get warm ...) and after I built my own kernel, it crashes on reboot ("Page fault while in kernel mode" and later sometimes "Memory modified after free"). So first I thought, I made a mistake configuring my kernel - that's what integration tests are good for, aren't they? So I built a generic kernel from updated sources - sometimes it works, sometimes it crashes with "Page fault while in kernel mode". So I added all debug options I could find: INVARIANTS, WITHNESS etc. incl. options DEBUG_MEMGUARD options DEBUG_REDZONE (I think from here it starts to give "Memory modified after free"). Because it's my very last x86 machine and my only 7.0 one, debugging was a little more difficult than usual. A lot of extra CAM_DEBUG() additions later I found a senseful watchpoint and could examinate the reason for the problem: In file sys/cam/cam_xpt.c 2 memory regions for scsi_inquiry are allocated - in line 5767 and 5833 - both smaller than sizeof(struct scsi_inquiry_data). In the iir.c module - within gdt_internal_cache_cmd() it's expected that the size of the given data area is large enough to hold the entire data structure used to execute given command. I choose as fix to fill the data into a local buffer on the stack and copy as much of it as fits into the csio.data_ptr area when ready. On systems with small stack size this fix may introduce new problems, but I don't expect a hardware raid controller on such systems ;) >How-To-Repeat: Enable options DEBUG_REDZONE and device iir to the kernel, insert iir compatible controller and boot. >Fix: Apply attached fix. Patch attached with submission follows: Index: sys/dev/iir/iir.c =================================================================== RCS file: /home/ncvs/src/sys/dev/iir/iir.c,v retrieving revision 1.19 diff -u -u -r1.19 iir.c --- sys/dev/iir/iir.c 17 Jun 2007 05:55:50 -0000 1.19 +++ sys/dev/iir/iir.c 29 Dec 2007 21:04:59 -0000 @@ -1160,20 +1160,25 @@ break; case INQUIRY: { - struct scsi_inquiry_data *inq; + struct scsi_inquiry_data inq; + size_t copylen = MIN(sizeof(inq), ccb->csio.dxfer_len); - inq = (struct scsi_inquiry_data *)ccb->csio.data_ptr; - bzero(inq, sizeof(struct scsi_inquiry_data)); - inq->device = (gdt->sc_hdr[t].hd_devtype & 4) ? + bzero(&inq, sizeof(inq)); + inq.device = (gdt->sc_hdr[t].hd_devtype & 4) ? T_CDROM : T_DIRECT; - inq->dev_qual2 = (gdt->sc_hdr[t].hd_devtype & 1) ? 0x80 : 0; - inq->version = SCSI_REV_2; - inq->response_format = 2; - inq->additional_length = 32; - inq->flags = SID_CmdQue | SID_Sync; - strcpy(inq->vendor, gdt->oem_name); - sprintf(inq->product, "Host Drive #%02d", t); - strcpy(inq->revision, " "); + inq.dev_qual2 = (gdt->sc_hdr[t].hd_devtype & 1) ? 0x80 : 0; + inq.version = SCSI_REV_2; + inq.response_format = 2; + inq.additional_length = 32; + inq.flags = SID_CmdQue | SID_Sync; + strncpy(inq.vendor, gdt->oem_name, sizeof(inq.vendor)); + snprintf(inq.product, sizeof(inq.product), + "Host Drive #%02d", t); + strncpy(inq.revision, " ", sizeof(inq.revision)); + bcopy(&inq, ccb->csio.data_ptr, copylen ); + if( ccb->csio.dxfer_len > copylen ) + bzero( ccb->csio.data_ptr+copylen, + ccb->csio.dxfer_len - copylen ); break; } case MODE_SENSE_6: @@ -1182,18 +1187,24 @@ struct scsi_mode_hdr_6 hd; struct scsi_mode_block_descr bd; struct scsi_control_page cp; - } *mpd; + } mpd; + size_t copylen = MIN(sizeof(mpd), ccb->csio.dxfer_len); u_int8_t page; - mpd = (struct mpd_data *)ccb->csio.data_ptr; - bzero(mpd, sizeof(struct mpd_data)); - mpd->hd.datalen = sizeof(struct scsi_mode_hdr_6) + + /*mpd = (struct mpd_data *)ccb->csio.data_ptr;*/ + bzero(&mpd, sizeof(mpd)); + mpd.hd.datalen = sizeof(struct scsi_mode_hdr_6) + sizeof(struct scsi_mode_block_descr); - mpd->hd.dev_specific = (gdt->sc_hdr[t].hd_devtype & 2) ? 0x80 : 0; - mpd->hd.block_descr_len = sizeof(struct scsi_mode_block_descr); - mpd->bd.block_len[0] = (GDT_SECTOR_SIZE & 0x00ff0000) >> 16; - mpd->bd.block_len[1] = (GDT_SECTOR_SIZE & 0x0000ff00) >> 8; - mpd->bd.block_len[2] = (GDT_SECTOR_SIZE & 0x000000ff); + mpd.hd.dev_specific = (gdt->sc_hdr[t].hd_devtype & 2) ? 0x80 : 0; + mpd.hd.block_descr_len = sizeof(struct scsi_mode_block_descr); + mpd.bd.block_len[0] = (GDT_SECTOR_SIZE & 0x00ff0000) >> 16; + mpd.bd.block_len[1] = (GDT_SECTOR_SIZE & 0x0000ff00) >> 8; + mpd.bd.block_len[2] = (GDT_SECTOR_SIZE & 0x000000ff); + + bcopy(&mpd, ccb->csio.data_ptr, copylen ); + if( ccb->csio.dxfer_len > copylen ) + bzero( ccb->csio.data_ptr+copylen, + ccb->csio.dxfer_len - copylen ); page=((struct scsi_mode_sense_6 *)ccb->csio.cdb_io.cdb_bytes)->page; switch (page) { default: @@ -1204,12 +1215,17 @@ } case READ_CAPACITY: { - struct scsi_read_capacity_data *rcd; + struct scsi_read_capacity_data rcd; + size_t copylen = MIN(sizeof(rcd), ccb->csio.dxfer_len); - rcd = (struct scsi_read_capacity_data *)ccb->csio.data_ptr; - bzero(rcd, sizeof(struct scsi_read_capacity_data)); - scsi_ulto4b(gdt->sc_hdr[t].hd_size - 1, rcd->addr); - scsi_ulto4b(GDT_SECTOR_SIZE, rcd->length); + /*rcd = (struct scsi_read_capacity_data *)ccb->csio.data_ptr;*/ + bzero(&rcd, sizeof(rcd)); + scsi_ulto4b(gdt->sc_hdr[t].hd_size - 1, rcd.addr); + scsi_ulto4b(GDT_SECTOR_SIZE, rcd.length); + bcopy(&rcd, ccb->csio.data_ptr, copylen ); + if( ccb->csio.dxfer_len > copylen ) + bzero( ccb->csio.data_ptr+copylen, + ccb->csio.dxfer_len - copylen ); break; } default: >Release-Note: >Audit-Trail: >Unformatted: