diff --git a/share/security/advisories/FreeBSD-EN-13:03.mfi.asc b/share/security/advisories/FreeBSD-EN-13:03.mfi.asc new file mode 100644 index 0000000000..6ec02fbbfa --- /dev/null +++ b/share/security/advisories/FreeBSD-EN-13:03.mfi.asc @@ -0,0 +1,109 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA1 + +============================================================================= +FreeBSD-EN-13:03.mfi Errata Notice + The FreeBSD Project + +Topic: data corruption with mfi(4) JBOD disks > 2TB + +Category: contrib +Module: mfi +Announced: 2013-08-22 +Credits: Steven Hartland, Doug Ambrisko +Affects: FreeBSD 9.1 +Corrected: 2012-12-03 18:37:02 UTC (stable/9, 9.1-STABLE) + 2013-08-22 00:51:48 UTC (releng/9.1, 9.1-RELEASE-p6) + +For general information regarding FreeBSD Errata Notices and Security +Advisories, including descriptions of the fields above, security +branches, and the following sections, please visit +. + +I. Background + +The mfi(4) driver supports LSI's next generation PCI Express SAS RAID +controllers. The driver supports JBOD attachment through /dev/mfisyspd? +device nodes. + +Logical block addressing (LBA) is a common scheme used for specifying the +location of sectors on hard drives. + +II. Problem Description + +The way mfi(4) implements access of "syspd" or also known as JBOD always +uses READ10/WRITE10 commands for underlying disk. When writing over 2^32 +sectors, the LBA would wrap and starts writing at the beginning of the +disk. + +III. Impact + +Writing beyond 2TB to mfi(4) connected JBODs would result in data corruption. + +IV. Workaround + +No workaround is available, but systems that do not use mfi(4) as a JBOD +HBA or do not have disks with 2^32 or more sectors (2^41 or more bytes with +512-byte logical sector size) are not affected. + +V. Solution + +Perform one of the following: + +1) Upgrade your system to a supported FreeBSD stable or release / security +branch (releng) dated after the correction date. + +2) To update your present system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +# fetch http://security.FreeBSD.org/patches/EN-13:03/mfi.patch +# fetch http://security.FreeBSD.org/patches/EN-13:03/mfi.patch.asc +# gpg --verify mfi.patch.asc + +b) Apply the patch. + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile your kernel as described in + and reboot the +system. + +3) To update your system via a binary patch: + +Systems running a RELEASE version of FreeBSD on the i386 or amd64 +platforms can be updated via the freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install + +VI. Correction details + +The following list contains the revision numbers of each file that was +corrected in FreeBSD. + +Branch/path Revision +- ------------------------------------------------------------------------- +stable/9/ r243824 +releng/9.1/ r254631 +- ------------------------------------------------------------------------- + +VII. References + +http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/173291 + +The latest revision of this Errata Notice is available at +http://security.FreeBSD.org/advisories/FreeBSD-EN-13:03.mfi.asc + +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2.0.21 (FreeBSD) + +iEYEARECAAYFAlIVY1YACgkQFdaIBMps37IHmwCfZH+1Gi0u7eYMXYevu0KHaG3a +rCwAn2ecdXnLOsaC6D6i2mo4dmI4HLDk +=AwdQ +-----END PGP SIGNATURE----- diff --git a/share/security/advisories/FreeBSD-SA-13:09.ip_multicast.asc b/share/security/advisories/FreeBSD-SA-13:09.ip_multicast.asc new file mode 100644 index 0000000000..35ffd28117 --- /dev/null +++ b/share/security/advisories/FreeBSD-SA-13:09.ip_multicast.asc @@ -0,0 +1,121 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA1 + +FreeBSD-SA-13:09.ip_multicast Security Advisory + The FreeBSD Project + +Topic: integer overflow in IP_MSFILTER + +Category: core +Module: kernel +Announced: 2013-08-22 +Credits: Clement Lecigne (Google Security Team) +Affects: All supported versions of FreeBSD. +Corrected: 2013-08-22 00:51:37 UTC (stable/9, 9.2-PRERELEASE) + 2013-08-22 00:51:43 UTC (releng/9.2, 9.2-RC2-p1) + 2013-08-22 00:51:48 UTC (releng/9.1, 9.1-RELEASE-p6) + 2013-08-22 00:51:37 UTC (stable/8, 8.4-STABLE) + 2013-08-22 00:51:56 UTC (releng/8.4, 8.4-RELEASE-p3) + 2013-08-22 00:51:56 UTC (releng/8.3, 8.3-RELEASE-p10) +CVE Name: CVE-2013-3077 + +For general information regarding FreeBSD Security Advisories, +including descriptions of the fields above, security branches, and the +following sections, please visit . + +I. Background + +IP multicast is a method of sending Internet Protocol (IP) datagrams to a +group of interested receivers in a single transmission. + +II. Problem Description + +An integer overflow in computing the size of a temporary buffer can +result in a buffer which is too small for the requested operation. + +III. Impact + +An unprivileged process can read or write pages of memory which belong to +the kernel. These may lead to exposure of sensitive information or allow +privilege escalation. + +IV. Workaround + +No workaround is available. + +V. Solution + +Perform one of the following: + +1) Upgrade your vulnerable system to a supported FreeBSD stable or +release / security branch (releng) dated after the correction date. + +2) To update your vulnerable system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +# fetch http://security.FreeBSD.org/patches/SA-13:09/ip_multicast.patch +# fetch http://security.FreeBSD.org/patches/SA-13:09/ip_multicast.patch.asc +# gpg --verify ip_multicast.patch.asc + +b) Apply the patch. + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile your kernel as described in + and reboot the +system. + +3) To update your vulnerable system via a binary patch: + +Systems running a RELEASE version of FreeBSD on the i386 or amd64 +platforms can be updated via the freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install + +VI. Correction details + +The following list contains the correction revision numbers for each +affected branch. + +Branch/path Revision +- ------------------------------------------------------------------------- +stable/8/ r254629 +releng/8.3/ r254632 +releng/8.4/ r254632 +stable/9/ r254629 +releng/9.1/ r254631 +releng/9.2/ r254630 +- ------------------------------------------------------------------------- + +To see which files were modified by a particular revision, run the +following command, replacing XXXXXX with the revision number, on a +machine with Subversion installed: + +# svn diff -cXXXXXX --summarize svn://svn.freebsd.org/base + +Or visit the following URL, replacing XXXXXX with the revision number: + + + +VII. References + + + + + +The latest revision of this advisory is available at + +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2.0.21 (FreeBSD) + +iEYEARECAAYFAlIVY1YACgkQFdaIBMps37K1cwCeOwXryun/C0EceD7v1se+z8w1 +EUYAoJ7Hh/bOjyuD6oR6ZOEqtDVIL5LP +=6Ehk +-----END PGP SIGNATURE----- diff --git a/share/security/advisories/FreeBSD-SA-13:10.sctp.asc b/share/security/advisories/FreeBSD-SA-13:10.sctp.asc new file mode 100644 index 0000000000..8e0b9ae0c4 --- /dev/null +++ b/share/security/advisories/FreeBSD-SA-13:10.sctp.asc @@ -0,0 +1,133 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA1 + +============================================================================= +FreeBSD-SA-13:10.sctp Security Advisory + The FreeBSD Project + +Topic: Kernel memory disclosure in sctp(4) + +Category: core +Module: sctp +Announced: 2013-08-22 +Credits: Julian Seward, Michael Tuexen +Affects: All supported versions of FreeBSD. +Corrected: 2013-08-15 04:25:16 UTC (stable/9, 9.2-PRERELEASE) + 2013-08-15 05:14:20 UTC (releng/9.2, 9.2-RC2) + 2013-08-22 00:51:48 UTC (releng/9.1, 9.1-RELEASE-p6) + 2013-08-15 04:35:25 UTC (stable/8, 8.4-STABLE) + 2013-08-22 00:51:56 UTC (releng/8.4, 8.4-RELEASE-p3) + 2013-08-22 00:51:56 UTC (releng/8.3, 8.3-RELEASE-p10) +CVE Name: CVE-2013-5209 + +For general information regarding FreeBSD Security Advisories, +including descriptions of the fields above, security branches, and the +following sections, please visit . + +I. Background + +The SCTP protocol provides reliable, flow-controlled, two-way transmission +of data. It is a message oriented protocol and can support the SOCK_STREAM +and SOCK_SEQPACKET abstractions. + +The SCTP protocol checks the integrity of messages by validating the state +cookie information that is returned from the peer. + +II. Problem Description + +When initializing the SCTP state cookie being sent in INIT-ACK chunks, +a buffer allocated from the kernel stack is not completely initialized. + +III. Impact + +Fragments of kernel memory may be included in SCTP packets and +transmitted over the network. For each SCTP session, there are two +separate instances in which a 4-byte fragment may be transmitted. + +This memory might contain sensitive information, such as portions of the +file cache or terminal buffers. This information might be directly +useful, or it might be leveraged to obtain elevated privileges in +some way. For example, a terminal buffer might include an user-entered +password. + +IV. Workaround + +No workaround is available, but systems not using the SCTP protocol +are not vulnerable. + +V. Solution + +Perform one of the following: + +1) Upgrade your vulnerable system to a supported FreeBSD stable or +release / security branch (releng) dated after the correction date. + +2) To update your vulnerable system via a source code patch: + +The following patches have been verified to apply to the applicable +FreeBSD release branches. + +a) Download the relevant patch from the location below, and verify the +detached PGP signature using your PGP utility. + +# fetch http://security.FreeBSD.org/patches/SA-13:10/sctp.patch +# fetch http://security.FreeBSD.org/patches/SA-13:10/sctp.patch.asc +# gpg --verify sctp.patch.asc + +b) Apply the patch. + +# cd /usr/src +# patch < /path/to/patch + +c) Recompile your kernel as described in + and reboot the +system. + +3) To update your vulnerable system via a binary patch: + +Systems running a RELEASE version of FreeBSD on the i386 or amd64 +platforms can be updated via the freebsd-update(8) utility: + +# freebsd-update fetch +# freebsd-update install + +VI. Correction details + +The following list contains the correction revision numbers for each +affected branch. + +Branch/path Revision +- ------------------------------------------------------------------------- +stable/8/ r254354 +releng/8.3/ r254632 +releng/8.4/ r254632 +stable/9/ r254352 +releng/9.1/ r254631 +releng/9.2/ r254355 +- ------------------------------------------------------------------------- + +To see which files were modified by a particular revision, run the +following command, replacing XXXXXX with the revision number, on a +machine with Subversion installed: + +# svn diff -cXXXXXX --summarize svn://svn.freebsd.org/base + +Or visit the following URL, replacing XXXXXX with the revision number: + + + +VII. References + + + + + +The latest revision of this advisory is available at + +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2.0.21 (FreeBSD) + +iEYEARECAAYFAlIVY1YACgkQFdaIBMps37L0AQCgh30FZd+f+rmzMabRFkTPVEmX +tZgAnRuZptKgvlHkqnEhUj30tH6xLDCO +=KJ8k +-----END PGP SIGNATURE----- diff --git a/share/security/patches/EN-13:03/mfi.patch b/share/security/patches/EN-13:03/mfi.patch new file mode 100644 index 0000000000..2daa5bf91e --- /dev/null +++ b/share/security/patches/EN-13:03/mfi.patch @@ -0,0 +1,994 @@ +Index: sys/dev/mfi/mfi.c +=================================================================== +--- sys/dev/mfi/mfi.c (revision 254079) ++++ sys/dev/mfi/mfi.c (working copy) +@@ -107,7 +107,7 @@ static void mfi_bio_complete(struct mfi_command *) + static struct mfi_command *mfi_build_ldio(struct mfi_softc *,struct bio*); + static struct mfi_command *mfi_build_syspdio(struct mfi_softc *,struct bio*); + static int mfi_send_frame(struct mfi_softc *, struct mfi_command *); +-static int mfi_abort(struct mfi_softc *, struct mfi_command *); ++static int mfi_abort(struct mfi_softc *, struct mfi_command **); + static int mfi_linux_ioctl_int(struct cdev *, u_long, caddr_t, int, struct thread *); + static void mfi_timeout(void *); + static int mfi_user_command(struct mfi_softc *, +@@ -373,6 +373,8 @@ mfi_attach(struct mfi_softc *sc) + sx_init(&sc->mfi_config_lock, "MFI config"); + TAILQ_INIT(&sc->mfi_ld_tqh); + TAILQ_INIT(&sc->mfi_syspd_tqh); ++ TAILQ_INIT(&sc->mfi_ld_pend_tqh); ++ TAILQ_INIT(&sc->mfi_syspd_pend_tqh); + TAILQ_INIT(&sc->mfi_evt_queue); + TASK_INIT(&sc->mfi_evt_task, 0, mfi_handle_evt, sc); + TASK_INIT(&sc->mfi_map_sync_task, 0, mfi_handle_map_sync, sc); +@@ -694,6 +696,7 @@ mfi_attach(struct mfi_softc *sc) + device_printf(sc->mfi_dev, "Cannot set up interrupt\n"); + return (EINVAL); + } ++ sc->mfi_intr_ptr = mfi_intr_tbolt; + sc->mfi_enable_intr(sc); + } else { + if ((error = mfi_comms_init(sc)) != 0) +@@ -704,6 +707,7 @@ mfi_attach(struct mfi_softc *sc) + device_printf(sc->mfi_dev, "Cannot set up interrupt\n"); + return (EINVAL); + } ++ sc->mfi_intr_ptr = mfi_intr; + sc->mfi_enable_intr(sc); + } + if ((error = mfi_get_controller_info(sc)) != 0) +@@ -1278,6 +1282,17 @@ mfi_shutdown(struct mfi_softc *sc) + struct mfi_command *cm; + int error; + ++ ++ if (sc->mfi_aen_cm) ++ sc->cm_aen_abort = 1; ++ if (sc->mfi_aen_cm != NULL) ++ mfi_abort(sc, &sc->mfi_aen_cm); ++ ++ if (sc->mfi_map_sync_cm) ++ sc->cm_map_abort = 1; ++ if (sc->mfi_map_sync_cm != NULL) ++ mfi_abort(sc, &sc->mfi_map_sync_cm); ++ + mtx_lock(&sc->mfi_io_lock); + error = mfi_dcmd_command(sc, &cm, MFI_DCMD_CTRL_SHUTDOWN, NULL, 0); + if (error) { +@@ -1285,12 +1300,6 @@ mfi_shutdown(struct mfi_softc *sc) + return (error); + } + +- if (sc->mfi_aen_cm != NULL) +- mfi_abort(sc, sc->mfi_aen_cm); +- +- if (sc->mfi_map_sync_cm != NULL) +- mfi_abort(sc, sc->mfi_map_sync_cm); +- + dcmd = &cm->cm_frame->dcmd; + dcmd->header.flags = MFI_FRAME_DIR_NONE; + cm->cm_flags = MFI_CMD_POLLED; +@@ -1312,6 +1321,7 @@ mfi_syspdprobe(struct mfi_softc *sc) + struct mfi_command *cm = NULL; + struct mfi_pd_list *pdlist = NULL; + struct mfi_system_pd *syspd, *tmp; ++ struct mfi_system_pending *syspd_pend; + int error, i, found; + + sx_assert(&sc->mfi_config_lock, SA_XLOCKED); +@@ -1352,6 +1362,10 @@ mfi_syspdprobe(struct mfi_softc *sc) + if (syspd->pd_id == pdlist->addr[i].device_id) + found = 1; + } ++ TAILQ_FOREACH(syspd_pend, &sc->mfi_syspd_pend_tqh, pd_link) { ++ if (syspd_pend->pd_id == pdlist->addr[i].device_id) ++ found = 1; ++ } + if (found == 0) + mfi_add_sys_pd(sc, pdlist->addr[i].device_id); + } +@@ -1387,6 +1401,7 @@ mfi_ldprobe(struct mfi_softc *sc) + struct mfi_command *cm = NULL; + struct mfi_ld_list *list = NULL; + struct mfi_disk *ld; ++ struct mfi_disk_pending *ld_pend; + int error, i; + + sx_assert(&sc->mfi_config_lock, SA_XLOCKED); +@@ -1415,6 +1430,10 @@ mfi_ldprobe(struct mfi_softc *sc) + if (ld->ld_id == list->ld_list[i].ld.v.target_id) + goto skip_add; + } ++ TAILQ_FOREACH(ld_pend, &sc->mfi_ld_pend_tqh, ld_link) { ++ if (ld_pend->ld_id == list->ld_list[i].ld.v.target_id) ++ goto skip_add; ++ } + mfi_add_ld(sc, list->ld_list[i].ld.v.target_id); + skip_add:; + } +@@ -1617,9 +1636,7 @@ mfi_aen_register(struct mfi_softc *sc, int seq, in + < current_aen.members.evt_class) + current_aen.members.evt_class = + prior_aen.members.evt_class; +- mtx_lock(&sc->mfi_io_lock); +- mfi_abort(sc, sc->mfi_aen_cm); +- mtx_unlock(&sc->mfi_io_lock); ++ mfi_abort(sc, &sc->mfi_aen_cm); + } + } + +@@ -1811,10 +1828,17 @@ mfi_add_ld(struct mfi_softc *sc, int id) + struct mfi_command *cm; + struct mfi_dcmd_frame *dcmd = NULL; + struct mfi_ld_info *ld_info = NULL; ++ struct mfi_disk_pending *ld_pend; + int error; + + mtx_assert(&sc->mfi_io_lock, MA_OWNED); + ++ ld_pend = malloc(sizeof(*ld_pend), M_MFIBUF, M_NOWAIT | M_ZERO); ++ if (ld_pend != NULL) { ++ ld_pend->ld_id = id; ++ TAILQ_INSERT_TAIL(&sc->mfi_ld_pend_tqh, ld_pend, ld_link); ++ } ++ + error = mfi_dcmd_command(sc, &cm, MFI_DCMD_LD_GET_INFO, + (void **)&ld_info, sizeof(*ld_info)); + if (error) { +@@ -1855,11 +1879,13 @@ mfi_add_ld_complete(struct mfi_command *cm) + hdr = &cm->cm_frame->header; + ld_info = cm->cm_private; + +- if (hdr->cmd_status != MFI_STAT_OK) { ++ if (sc->cm_map_abort || hdr->cmd_status != MFI_STAT_OK) { + free(ld_info, M_MFIBUF); ++ wakeup(&sc->mfi_map_sync_cm); + mfi_release_command(cm); + return; + } ++ wakeup(&sc->mfi_map_sync_cm); + mfi_release_command(cm); + + mtx_unlock(&sc->mfi_io_lock); +@@ -1884,10 +1910,17 @@ static int mfi_add_sys_pd(struct mfi_softc *sc, in + struct mfi_command *cm; + struct mfi_dcmd_frame *dcmd = NULL; + struct mfi_pd_info *pd_info = NULL; ++ struct mfi_system_pending *syspd_pend; + int error; + + mtx_assert(&sc->mfi_io_lock, MA_OWNED); + ++ syspd_pend = malloc(sizeof(*syspd_pend), M_MFIBUF, M_NOWAIT | M_ZERO); ++ if (syspd_pend != NULL) { ++ syspd_pend->pd_id = id; ++ TAILQ_INSERT_TAIL(&sc->mfi_syspd_pend_tqh, syspd_pend, pd_link); ++ } ++ + error = mfi_dcmd_command(sc, &cm, MFI_DCMD_PD_GET_INFO, + (void **)&pd_info, sizeof(*pd_info)); + if (error) { +@@ -1981,19 +2014,87 @@ mfi_bio_command(struct mfi_softc *sc) + mfi_enqueue_bio(sc, bio); + return cm; + } ++ ++/* ++ * mostly copied from cam/scsi/scsi_all.c:scsi_read_write ++ */ ++ ++int ++mfi_build_cdb(int readop, uint8_t byte2, u_int64_t lba, u_int32_t block_count, uint8_t *cdb) ++{ ++ int cdb_len; ++ ++ if (((lba & 0x1fffff) == lba) ++ && ((block_count & 0xff) == block_count) ++ && (byte2 == 0)) { ++ /* We can fit in a 6 byte cdb */ ++ struct scsi_rw_6 *scsi_cmd; ++ ++ scsi_cmd = (struct scsi_rw_6 *)cdb; ++ scsi_cmd->opcode = readop ? READ_6 : WRITE_6; ++ scsi_ulto3b(lba, scsi_cmd->addr); ++ scsi_cmd->length = block_count & 0xff; ++ scsi_cmd->control = 0; ++ cdb_len = sizeof(*scsi_cmd); ++ } else if (((block_count & 0xffff) == block_count) && ((lba & 0xffffffff) == lba)) { ++ /* Need a 10 byte CDB */ ++ struct scsi_rw_10 *scsi_cmd; ++ ++ scsi_cmd = (struct scsi_rw_10 *)cdb; ++ scsi_cmd->opcode = readop ? READ_10 : WRITE_10; ++ scsi_cmd->byte2 = byte2; ++ scsi_ulto4b(lba, scsi_cmd->addr); ++ scsi_cmd->reserved = 0; ++ scsi_ulto2b(block_count, scsi_cmd->length); ++ scsi_cmd->control = 0; ++ cdb_len = sizeof(*scsi_cmd); ++ } else if (((block_count & 0xffffffff) == block_count) && ++ ((lba & 0xffffffff) == lba)) { ++ /* Block count is too big for 10 byte CDB use a 12 byte CDB */ ++ struct scsi_rw_12 *scsi_cmd; ++ ++ scsi_cmd = (struct scsi_rw_12 *)cdb; ++ scsi_cmd->opcode = readop ? READ_12 : WRITE_12; ++ scsi_cmd->byte2 = byte2; ++ scsi_ulto4b(lba, scsi_cmd->addr); ++ scsi_cmd->reserved = 0; ++ scsi_ulto4b(block_count, scsi_cmd->length); ++ scsi_cmd->control = 0; ++ cdb_len = sizeof(*scsi_cmd); ++ } else { ++ /* ++ * 16 byte CDB. We'll only get here if the LBA is larger ++ * than 2^32 ++ */ ++ struct scsi_rw_16 *scsi_cmd; ++ ++ scsi_cmd = (struct scsi_rw_16 *)cdb; ++ scsi_cmd->opcode = readop ? READ_16 : WRITE_16; ++ scsi_cmd->byte2 = byte2; ++ scsi_u64to8b(lba, scsi_cmd->addr); ++ scsi_cmd->reserved = 0; ++ scsi_ulto4b(block_count, scsi_cmd->length); ++ scsi_cmd->control = 0; ++ cdb_len = sizeof(*scsi_cmd); ++ } ++ ++ return cdb_len; ++} ++ + static struct mfi_command * + mfi_build_syspdio(struct mfi_softc *sc, struct bio *bio) + { + struct mfi_command *cm; + struct mfi_pass_frame *pass; +- int flags = 0, blkcount = 0; + uint32_t context = 0; ++ int flags = 0, blkcount = 0, readop; ++ uint8_t cdb_len; + + if ((cm = mfi_dequeue_free(sc)) == NULL) + return (NULL); + + /* Zero out the MFI frame */ +- context = cm->cm_frame->header.context; ++ context = cm->cm_frame->header.context; + bzero(cm->cm_frame, sizeof(union mfi_frame)); + cm->cm_frame->header.context = context; + pass = &cm->cm_frame->pass; +@@ -2001,35 +2102,31 @@ mfi_build_syspdio(struct mfi_softc *sc, struct bio + pass->header.cmd = MFI_CMD_PD_SCSI_IO; + switch (bio->bio_cmd & 0x03) { + case BIO_READ: +-#define SCSI_READ 0x28 +- pass->cdb[0] = SCSI_READ; + flags = MFI_CMD_DATAIN; ++ readop = 1; + break; + case BIO_WRITE: +-#define SCSI_WRITE 0x2a +- pass->cdb[0] = SCSI_WRITE; + flags = MFI_CMD_DATAOUT; ++ readop = 0; + break; + default: +- panic("Invalid bio command"); ++ /* TODO: what about BIO_DELETE??? */ ++ panic("Unsupported bio command %x\n", bio->bio_cmd); + } + + /* Cheat with the sector length to avoid a non-constant division */ + blkcount = (bio->bio_bcount + MFI_SECTOR_LEN - 1) / MFI_SECTOR_LEN; + /* Fill the LBA and Transfer length in CDB */ +- pass->cdb[2] = (bio->bio_pblkno & 0xff000000) >> 24; +- pass->cdb[3] = (bio->bio_pblkno & 0x00ff0000) >> 16; +- pass->cdb[4] = (bio->bio_pblkno & 0x0000ff00) >> 8; +- pass->cdb[5] = bio->bio_pblkno & 0x000000ff; +- pass->cdb[7] = (blkcount & 0xff00) >> 8; +- pass->cdb[8] = (blkcount & 0x00ff); ++ cdb_len = mfi_build_cdb(readop, 0, bio->bio_pblkno, blkcount, ++ pass->cdb); + pass->header.target_id = (uintptr_t)bio->bio_driver1; ++ pass->header.lun_id = 0; + pass->header.timeout = 0; + pass->header.flags = 0; + pass->header.scsi_status = 0; + pass->header.sense_len = MFI_SENSE_LEN; + pass->header.data_len = bio->bio_bcount; +- pass->header.cdb_len = 10; ++ pass->header.cdb_len = cdb_len; + pass->sense_addr_lo = (uint32_t)cm->cm_sense_busaddr; + pass->sense_addr_hi = (uint32_t)((uint64_t)cm->cm_sense_busaddr >> 32); + cm->cm_complete = mfi_bio_complete; +@@ -2047,7 +2144,8 @@ mfi_build_ldio(struct mfi_softc *sc, struct bio *b + { + struct mfi_io_frame *io; + struct mfi_command *cm; +- int flags, blkcount; ++ int flags; ++ uint32_t blkcount; + uint32_t context = 0; + + if ((cm = mfi_dequeue_free(sc)) == NULL) +@@ -2068,7 +2166,8 @@ mfi_build_ldio(struct mfi_softc *sc, struct bio *b + flags = MFI_CMD_DATAOUT; + break; + default: +- panic("Invalid bio command"); ++ /* TODO: what about BIO_DELETE??? */ ++ panic("Unsupported bio command %x\n", bio->bio_cmd); + } + + /* Cheat with the sector length to avoid a non-constant division */ +@@ -2358,7 +2457,7 @@ mfi_complete(struct mfi_softc *sc, struct mfi_comm + } + + static int +-mfi_abort(struct mfi_softc *sc, struct mfi_command *cm_abort) ++mfi_abort(struct mfi_softc *sc, struct mfi_command **cm_abort) + { + struct mfi_command *cm; + struct mfi_abort_frame *abort; +@@ -2365,8 +2464,7 @@ static int + int i = 0; + uint32_t context = 0; + +- mtx_assert(&sc->mfi_io_lock, MA_OWNED); +- ++ mtx_lock(&sc->mfi_io_lock); + if ((cm = mfi_dequeue_free(sc)) == NULL) { + return (EBUSY); + } +@@ -2380,29 +2478,27 @@ static int + abort->header.cmd = MFI_CMD_ABORT; + abort->header.flags = 0; + abort->header.scsi_status = 0; +- abort->abort_context = cm_abort->cm_frame->header.context; +- abort->abort_mfi_addr_lo = (uint32_t)cm_abort->cm_frame_busaddr; ++ abort->abort_context = (*cm_abort)->cm_frame->header.context; ++ abort->abort_mfi_addr_lo = (uint32_t)(*cm_abort)->cm_frame_busaddr; + abort->abort_mfi_addr_hi = +- (uint32_t)((uint64_t)cm_abort->cm_frame_busaddr >> 32); ++ (uint32_t)((uint64_t)(*cm_abort)->cm_frame_busaddr >> 32); + cm->cm_data = NULL; + cm->cm_flags = MFI_CMD_POLLED; + +- if (sc->mfi_aen_cm) +- sc->cm_aen_abort = 1; +- if (sc->mfi_map_sync_cm) +- sc->cm_map_abort = 1; + mfi_mapcmd(sc, cm); + mfi_release_command(cm); + +- while (i < 5 && sc->mfi_aen_cm != NULL) { +- msleep(&sc->mfi_aen_cm, &sc->mfi_io_lock, 0, "mfiabort", ++ mtx_unlock(&sc->mfi_io_lock); ++ while (i < 5 && *cm_abort != NULL) { ++ tsleep(cm_abort, 0, "mfiabort", + 5 * hz); + i++; + } +- while (i < 5 && sc->mfi_map_sync_cm != NULL) { +- msleep(&sc->mfi_map_sync_cm, &sc->mfi_io_lock, 0, "mfiabort", +- 5 * hz); +- i++; ++ if (*cm_abort != NULL) { ++ /* Force a complete if command didn't abort */ ++ mtx_lock(&sc->mfi_io_lock); ++ (*cm_abort)->cm_complete(*cm_abort); ++ mtx_unlock(&sc->mfi_io_lock); + } + + return (0); +@@ -2458,8 +2554,8 @@ mfi_dump_syspd_blocks(struct mfi_softc *sc, int id + { + struct mfi_command *cm; + struct mfi_pass_frame *pass; +- int error; +- int blkcount = 0; ++ int error, readop, cdb_len; ++ uint32_t blkcount; + + if ((cm = mfi_dequeue_free(sc)) == NULL) + return (EBUSY); +@@ -2467,14 +2563,10 @@ mfi_dump_syspd_blocks(struct mfi_softc *sc, int id + pass = &cm->cm_frame->pass; + bzero(pass->cdb, 16); + pass->header.cmd = MFI_CMD_PD_SCSI_IO; +- pass->cdb[0] = SCSI_WRITE; +- pass->cdb[2] = (lba & 0xff000000) >> 24; +- pass->cdb[3] = (lba & 0x00ff0000) >> 16; +- pass->cdb[4] = (lba & 0x0000ff00) >> 8; +- pass->cdb[5] = (lba & 0x000000ff); ++ ++ readop = 0; + blkcount = (len + MFI_SECTOR_LEN - 1) / MFI_SECTOR_LEN; +- pass->cdb[7] = (blkcount & 0xff00) >> 8; +- pass->cdb[8] = (blkcount & 0x00ff); ++ cdb_len = mfi_build_cdb(readop, 0, lba, blkcount, pass->cdb); + pass->header.target_id = id; + pass->header.timeout = 0; + pass->header.flags = 0; +@@ -2481,7 +2573,7 @@ mfi_dump_syspd_blocks(struct mfi_softc *sc, int id + pass->header.scsi_status = 0; + pass->header.sense_len = MFI_SENSE_LEN; + pass->header.data_len = len; +- pass->header.cdb_len = 10; ++ pass->header.cdb_len = cdb_len; + pass->sense_addr_lo = (uint32_t)cm->cm_sense_busaddr; + pass->sense_addr_hi = (uint32_t)((uint64_t)cm->cm_sense_busaddr >> 32); + cm->cm_data = virt; +@@ -2488,7 +2580,7 @@ mfi_dump_syspd_blocks(struct mfi_softc *sc, int id + cm->cm_len = len; + cm->cm_sg = &pass->sgl; + cm->cm_total_frame_size = MFI_PASS_FRAME_SIZE; +- cm->cm_flags = MFI_CMD_POLLED | MFI_CMD_DATAOUT; ++ cm->cm_flags = MFI_CMD_POLLED | MFI_CMD_DATAOUT | MFI_CMD_SCSI; + + error = mfi_mapcmd(sc, cm); + bus_dmamap_sync(sc->mfi_buffer_dmat, cm->cm_dmamap, +@@ -2687,16 +2779,24 @@ mfi_check_command_post(struct mfi_softc *sc, struc + } + } + +-static int mfi_check_for_sscd(struct mfi_softc *sc, struct mfi_command *cm) ++static int ++mfi_check_for_sscd(struct mfi_softc *sc, struct mfi_command *cm) + { +- struct mfi_config_data *conf_data=(struct mfi_config_data *)cm->cm_data; ++ struct mfi_config_data *conf_data; + struct mfi_command *ld_cm = NULL; + struct mfi_ld_info *ld_info = NULL; ++ struct mfi_ld_config *ld; ++ char *p; + int error = 0; + +- if ((cm->cm_frame->dcmd.opcode == MFI_DCMD_CFG_ADD) && +- (conf_data->ld[0].params.isSSCD == 1)) { +- error = 1; ++ conf_data = (struct mfi_config_data *)cm->cm_data; ++ ++ if (cm->cm_frame->dcmd.opcode == MFI_DCMD_CFG_ADD) { ++ p = (char *)conf_data->array; ++ p += conf_data->array_size * conf_data->array_count; ++ ld = (struct mfi_ld_config *)p; ++ if (ld->params.isSSCD == 1) ++ error = 1; + } else if (cm->cm_frame->dcmd.opcode == MFI_DCMD_LD_DELETE) { + error = mfi_dcmd_command (sc, &ld_cm, MFI_DCMD_LD_GET_INFO, + (void **)&ld_info, sizeof(*ld_info)); +Index: sys/dev/mfi/mfi_cam.c +=================================================================== +--- sys/dev/mfi/mfi_cam.c (revision 254079) ++++ sys/dev/mfi/mfi_cam.c (working copy) +@@ -79,6 +79,11 @@ static void mfip_cam_poll(struct cam_sim *); + static struct mfi_command * mfip_start(void *); + static void mfip_done(struct mfi_command *cm); + ++static int mfi_allow_disks = 0; ++TUNABLE_INT("hw.mfi.allow_cam_disk_passthrough", &mfi_allow_disks); ++SYSCTL_INT(_hw_mfi, OID_AUTO, allow_cam_disk_passthrough, CTLFLAG_RD, ++ &mfi_allow_disks, 0, "event message locale"); ++ + static devclass_t mfip_devclass; + static device_method_t mfip_methods[] = { + DEVMETHOD(device_probe, mfip_probe), +@@ -349,7 +354,8 @@ mfip_done(struct mfi_command *cm) + command = csio->cdb_io.cdb_bytes[0]; + if (command == INQUIRY) { + device = csio->data_ptr[0] & 0x1f; +- if ((device == T_DIRECT) || (device == T_PROCESSOR)) ++ if ((!mfi_allow_disks && device == T_DIRECT) || ++ (device == T_PROCESSOR)) + csio->data_ptr[0] = + (csio->data_ptr[0] & 0xe0) | T_NODEVICE; + } +@@ -392,6 +398,9 @@ mfip_done(struct mfi_command *cm) + static void + mfip_cam_poll(struct cam_sim *sim) + { +- return; ++ struct mfip_softc *sc = cam_sim_softc(sim); ++ struct mfi_softc *mfisc = sc->mfi_sc; ++ ++ mfisc->mfi_intr_ptr(mfisc); + } + +Index: sys/dev/mfi/mfi_disk.c +=================================================================== +--- sys/dev/mfi/mfi_disk.c (revision 254079) ++++ sys/dev/mfi/mfi_disk.c (working copy) +@@ -93,6 +93,7 @@ mfi_disk_attach(device_t dev) + { + struct mfi_disk *sc; + struct mfi_ld_info *ld_info; ++ struct mfi_disk_pending *ld_pend; + uint64_t sectors; + uint32_t secsize; + char *state; +@@ -111,6 +112,13 @@ mfi_disk_attach(device_t dev) + secsize = MFI_SECTOR_LEN; + mtx_lock(&sc->ld_controller->mfi_io_lock); + TAILQ_INSERT_TAIL(&sc->ld_controller->mfi_ld_tqh, sc, ld_link); ++ TAILQ_FOREACH(ld_pend, &sc->ld_controller->mfi_ld_pend_tqh, ++ ld_link) { ++ TAILQ_REMOVE(&sc->ld_controller->mfi_ld_pend_tqh, ++ ld_pend, ld_link); ++ free(ld_pend, M_MFIBUF); ++ break; ++ } + mtx_unlock(&sc->ld_controller->mfi_io_lock); + + switch (ld_info->ld_config.params.state) { +@@ -131,16 +139,16 @@ mfi_disk_attach(device_t dev) + break; + } + +- if ( strlen(ld_info->ld_config.properties.name) == 0 ) { +- device_printf(dev, +- "%juMB (%ju sectors) RAID volume (no label) is %s\n", +- sectors / (1024 * 1024 / secsize), sectors, state); +- } else { +- device_printf(dev, +- "%juMB (%ju sectors) RAID volume '%s' is %s\n", +- sectors / (1024 * 1024 / secsize), sectors, +- ld_info->ld_config.properties.name, state); +- } ++ if ( strlen(ld_info->ld_config.properties.name) == 0 ) { ++ device_printf(dev, ++ "%juMB (%ju sectors) RAID volume (no label) is %s\n", ++ sectors / (1024 * 1024 / secsize), sectors, state); ++ } else { ++ device_printf(dev, ++ "%juMB (%ju sectors) RAID volume '%s' is %s\n", ++ sectors / (1024 * 1024 / secsize), sectors, ++ ld_info->ld_config.properties.name, state); ++ } + + sc->ld_disk = disk_alloc(); + sc->ld_disk->d_drv1 = sc; +Index: sys/dev/mfi/mfi_syspd.c +=================================================================== +--- sys/dev/mfi/mfi_syspd.c (revision 254079) ++++ sys/dev/mfi/mfi_syspd.c (working copy) +@@ -89,7 +89,6 @@ DRIVER_MODULE(mfisyspd, mfi, mfi_syspd_driver, mfi + static int + mfi_syspd_probe(device_t dev) + { +- + return (0); + } + +@@ -98,12 +97,12 @@ mfi_syspd_attach(device_t dev) + { + struct mfi_system_pd *sc; + struct mfi_pd_info *pd_info; ++ struct mfi_system_pending *syspd_pend; + uint64_t sectors; + uint32_t secsize; + + sc = device_get_softc(dev); + pd_info = device_get_ivars(dev); +- + sc->pd_dev = dev; + sc->pd_id = pd_info->ref.v.device_id; + sc->pd_unit = device_get_unit(dev); +@@ -115,6 +114,13 @@ mfi_syspd_attach(device_t dev) + secsize = MFI_SECTOR_LEN; + mtx_lock(&sc->pd_controller->mfi_io_lock); + TAILQ_INSERT_TAIL(&sc->pd_controller->mfi_syspd_tqh, sc, pd_link); ++ TAILQ_FOREACH(syspd_pend, &sc->pd_controller->mfi_syspd_pend_tqh, ++ pd_link) { ++ TAILQ_REMOVE(&sc->pd_controller->mfi_syspd_pend_tqh, ++ syspd_pend, pd_link); ++ free(syspd_pend, M_MFIBUF); ++ break; ++ } + mtx_unlock(&sc->pd_controller->mfi_io_lock); + device_printf(dev, "%juMB (%ju sectors) SYSPD volume\n", + sectors / (1024 * 1024 / secsize), sectors); +@@ -139,6 +145,7 @@ mfi_syspd_attach(device_t dev) + disk_create(sc->pd_disk, DISK_VERSION); + + device_printf(dev, " SYSPD volume attached\n"); ++ + return (0); + } + +Index: sys/dev/mfi/mfi_tbolt.c +=================================================================== +--- sys/dev/mfi/mfi_tbolt.c (revision 254079) ++++ sys/dev/mfi/mfi_tbolt.c (working copy) +@@ -69,13 +69,10 @@ uint8_t + mfi_build_mpt_pass_thru(struct mfi_softc *sc, struct mfi_command *mfi_cmd); + union mfi_mpi2_request_descriptor *mfi_build_and_issue_cmd(struct mfi_softc + *sc, struct mfi_command *mfi_cmd); +-int mfi_tbolt_is_ldio(struct mfi_command *mfi_cmd); + void mfi_tbolt_build_ldio(struct mfi_softc *sc, struct mfi_command *mfi_cmd, + struct mfi_cmd_tbolt *cmd); + static int mfi_tbolt_make_sgl(struct mfi_softc *sc, struct mfi_command + *mfi_cmd, pMpi25IeeeSgeChain64_t sgl_ptr, struct mfi_cmd_tbolt *cmd); +-static int mfi_tbolt_build_cdb(struct mfi_softc *sc, struct mfi_command +- *mfi_cmd, uint8_t *cdb); + void + map_tbolt_cmd_status(struct mfi_command *mfi_cmd, uint8_t status, + uint8_t ext_status); +@@ -502,6 +499,7 @@ mfi_tbolt_alloc_cmd(struct mfi_softc *sc) + + i * MEGASAS_MAX_SZ_CHAIN_FRAME); + cmd->sg_frame_phys_addr = sc->sg_frame_busaddr + i + * MEGASAS_MAX_SZ_CHAIN_FRAME; ++ cmd->sync_cmd_idx = sc->mfi_max_fw_cmds; + + TAILQ_INSERT_TAIL(&(sc->mfi_cmd_tbolt_tqh), cmd, next); + } +@@ -574,11 +572,11 @@ void + map_tbolt_cmd_status(struct mfi_command *mfi_cmd, uint8_t status, + uint8_t ext_status) + { +- + switch (status) { + case MFI_STAT_OK: +- mfi_cmd->cm_frame->header.cmd_status = 0; +- mfi_cmd->cm_frame->dcmd.header.cmd_status = 0; ++ mfi_cmd->cm_frame->header.cmd_status = MFI_STAT_OK; ++ mfi_cmd->cm_frame->dcmd.header.cmd_status = MFI_STAT_OK; ++ mfi_cmd->cm_error = MFI_STAT_OK; + break; + + case MFI_STAT_SCSI_IO_FAILED: +@@ -618,6 +616,7 @@ mfi_tbolt_return_cmd(struct mfi_softc *sc, struct + { + mtx_assert(&sc->mfi_io_lock, MA_OWNED); + ++ cmd->sync_cmd_idx = sc->mfi_max_fw_cmds; + TAILQ_INSERT_TAIL(&sc->mfi_cmd_tbolt_tqh, cmd, next); + } + +@@ -667,16 +666,26 @@ mfi_tbolt_complete_cmd(struct mfi_softc *sc) + extStatus = cmd_mfi->cm_frame->dcmd.header.scsi_status; + map_tbolt_cmd_status(cmd_mfi, status, extStatus); + +- /* remove command from busy queue if not polled */ +- TAILQ_FOREACH(cmd_mfi_check, &sc->mfi_busy, cm_link) { +- if (cmd_mfi_check == cmd_mfi) { +- mfi_remove_busy(cmd_mfi); +- break; ++ if (cmd_mfi->cm_flags & MFI_CMD_SCSI && ++ (cmd_mfi->cm_flags & MFI_CMD_POLLED) != 0) { ++ /* polled LD/SYSPD IO command */ ++ mfi_tbolt_return_cmd(sc, cmd_tbolt); ++ /* XXX mark okay for now DJA */ ++ cmd_mfi->cm_frame->header.cmd_status = MFI_STAT_OK; ++ } else { ++ ++ /* remove command from busy queue if not polled */ ++ TAILQ_FOREACH(cmd_mfi_check, &sc->mfi_busy, cm_link) { ++ if (cmd_mfi_check == cmd_mfi) { ++ mfi_remove_busy(cmd_mfi); ++ break; ++ } + } ++ ++ /* complete the command */ ++ mfi_complete(sc, cmd_mfi); ++ mfi_tbolt_return_cmd(sc, cmd_tbolt); + } +- cmd_mfi->cm_error = 0; +- mfi_complete(sc, cmd_mfi); +- mfi_tbolt_return_cmd(sc, cmd_tbolt); + + sc->last_reply_idx++; + if (sc->last_reply_idx >= sc->mfi_max_fw_cmds) { +@@ -811,13 +820,13 @@ mfi_tbolt_build_ldio(struct mfi_softc *sc, struct + MFI_FRAME_DIR_READ) + io_info.isRead = 1; + +- io_request->RaidContext.timeoutValue +- = MFI_FUSION_FP_DEFAULT_TIMEOUT; +- io_request->Function = MPI2_FUNCTION_LD_IO_REQUEST; +- io_request->DevHandle = device_id; +- cmd->request_desc->header.RequestFlags +- = (MFI_REQ_DESCRIPT_FLAGS_LD_IO +- << MFI_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); ++ io_request->RaidContext.timeoutValue ++ = MFI_FUSION_FP_DEFAULT_TIMEOUT; ++ io_request->Function = MPI2_FUNCTION_LD_IO_REQUEST; ++ io_request->DevHandle = device_id; ++ cmd->request_desc->header.RequestFlags ++ = (MFI_REQ_DESCRIPT_FLAGS_LD_IO ++ << MFI_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); + if ((io_request->IoFlags == 6) && (io_info.numBlocks == 0)) + io_request->RaidContext.RegLockLength = 0x100; + io_request->DataLength = mfi_cmd->cm_frame->io.header.data_len +@@ -825,41 +834,37 @@ mfi_tbolt_build_ldio(struct mfi_softc *sc, struct + } + + int +-mfi_tbolt_is_ldio(struct mfi_command *mfi_cmd) +-{ +- if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_READ +- || mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE) +- return 1; +- else +- return 0; +-} +- +-int + mfi_tbolt_build_io(struct mfi_softc *sc, struct mfi_command *mfi_cmd, + struct mfi_cmd_tbolt *cmd) + { +- uint32_t device_id; ++ struct mfi_mpi2_request_raid_scsi_io *io_request; + uint32_t sge_count; +- uint8_t cdb[32], cdb_len; ++ uint8_t cdb_len; ++ int readop; ++ u_int64_t lba; + +- memset(cdb, 0, 32); +- struct mfi_mpi2_request_raid_scsi_io *io_request = cmd->io_request; ++ io_request = cmd->io_request; ++ if (!(mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_READ ++ || mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE)) ++ return 1; + +- device_id = mfi_cmd->cm_frame->header.target_id; ++ mfi_tbolt_build_ldio(sc, mfi_cmd, cmd); + +- /* Have to build CDB here for TB as BSD don't have a scsi layer */ +- if ((cdb_len = mfi_tbolt_build_cdb(sc, mfi_cmd, cdb)) == 1) +- return 1; ++ /* Convert to SCSI command CDB */ ++ bzero(io_request->CDB.CDB32, sizeof(io_request->CDB.CDB32)); ++ if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE) ++ readop = 0; ++ else ++ readop = 1; + +- /* Just the CDB length,rest of the Flags are zero */ ++ lba = mfi_cmd->cm_frame->io.lba_hi; ++ lba = (lba << 32) + mfi_cmd->cm_frame->io.lba_lo; ++ cdb_len = mfi_build_cdb(readop, 0, lba, ++ mfi_cmd->cm_frame->io.header.data_len, io_request->CDB.CDB32); ++ ++ /* Just the CDB length, rest of the Flags are zero */ + io_request->IoFlags = cdb_len; +- memcpy(io_request->CDB.CDB32, cdb, 32); + +- if (mfi_tbolt_is_ldio(mfi_cmd)) +- mfi_tbolt_build_ldio(sc, mfi_cmd , cmd); +- else +- return 1; +- + /* + * Construct SGL + */ +@@ -883,85 +888,13 @@ mfi_tbolt_build_io(struct mfi_softc *sc, struct mf + + io_request->SenseBufferLowAddress = mfi_cmd->cm_sense_busaddr; + io_request->SenseBufferLength = MFI_SENSE_LEN; ++ io_request->RaidContext.Status = MFI_STAT_INVALID_STATUS; ++ io_request->RaidContext.exStatus = MFI_STAT_INVALID_STATUS; ++ + return 0; + } + +-static int +-mfi_tbolt_build_cdb(struct mfi_softc *sc, struct mfi_command *mfi_cmd, +- uint8_t *cdb) +-{ +- uint32_t lba_lo, lba_hi, num_lba; +- uint8_t cdb_len; + +- if (mfi_cmd == NULL || cdb == NULL) +- return 1; +- num_lba = mfi_cmd->cm_frame->io.header.data_len; +- lba_lo = mfi_cmd->cm_frame->io.lba_lo; +- lba_hi = mfi_cmd->cm_frame->io.lba_hi; +- +- if (lba_hi == 0 && (num_lba <= 0xFF) && (lba_lo <= 0x1FFFFF)) { +- if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE) +- /* Read 6 or Write 6 */ +- cdb[0] = (uint8_t) (0x0A); +- else +- cdb[0] = (uint8_t) (0x08); +- +- cdb[4] = (uint8_t) num_lba; +- cdb[3] = (uint8_t) (lba_lo & 0xFF); +- cdb[2] = (uint8_t) (lba_lo >> 8); +- cdb[1] = (uint8_t) ((lba_lo >> 16) & 0x1F); +- cdb_len = 6; +- } +- else if (lba_hi == 0 && (num_lba <= 0xFFFF) && (lba_lo <= 0xFFFFFFFF)) { +- if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE) +- /* Read 10 or Write 10 */ +- cdb[0] = (uint8_t) (0x2A); +- else +- cdb[0] = (uint8_t) (0x28); +- cdb[8] = (uint8_t) (num_lba & 0xFF); +- cdb[7] = (uint8_t) (num_lba >> 8); +- cdb[5] = (uint8_t) (lba_lo & 0xFF); +- cdb[4] = (uint8_t) (lba_lo >> 8); +- cdb[3] = (uint8_t) (lba_lo >> 16); +- cdb[2] = (uint8_t) (lba_lo >> 24); +- cdb_len = 10; +- } else if ((num_lba > 0xFFFF) && (lba_hi == 0)) { +- if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE) +- /* Read 12 or Write 12 */ +- cdb[0] = (uint8_t) (0xAA); +- else +- cdb[0] = (uint8_t) (0xA8); +- cdb[9] = (uint8_t) (num_lba & 0xFF); +- cdb[8] = (uint8_t) (num_lba >> 8); +- cdb[7] = (uint8_t) (num_lba >> 16); +- cdb[6] = (uint8_t) (num_lba >> 24); +- cdb[5] = (uint8_t) (lba_lo & 0xFF); +- cdb[4] = (uint8_t) (lba_lo >> 8); +- cdb[3] = (uint8_t) (lba_lo >> 16); +- cdb[2] = (uint8_t) (lba_lo >> 24); +- cdb_len = 12; +- } else { +- if (mfi_cmd->cm_frame->header.cmd == MFI_CMD_LD_WRITE) +- cdb[0] = (uint8_t) (0x8A); +- else +- cdb[0] = (uint8_t) (0x88); +- cdb[13] = (uint8_t) (num_lba & 0xFF); +- cdb[12] = (uint8_t) (num_lba >> 8); +- cdb[11] = (uint8_t) (num_lba >> 16); +- cdb[10] = (uint8_t) (num_lba >> 24); +- cdb[9] = (uint8_t) (lba_lo & 0xFF); +- cdb[8] = (uint8_t) (lba_lo >> 8); +- cdb[7] = (uint8_t) (lba_lo >> 16); +- cdb[6] = (uint8_t) (lba_lo >> 24); +- cdb[5] = (uint8_t) (lba_hi & 0xFF); +- cdb[4] = (uint8_t) (lba_hi >> 8); +- cdb[3] = (uint8_t) (lba_hi >> 16); +- cdb[2] = (uint8_t) (lba_hi >> 24); +- cdb_len = 16; +- } +- return cdb_len; +-} +- + static int + mfi_tbolt_make_sgl(struct mfi_softc *sc, struct mfi_command *mfi_cmd, + pMpi25IeeeSgeChain64_t sgl_ptr, struct mfi_cmd_tbolt *cmd) +@@ -1100,8 +1033,7 @@ mfi_tbolt_send_frame(struct mfi_softc *sc, struct + if ((cm->cm_flags & MFI_CMD_POLLED) == 0) { + cm->cm_timestamp = time_uptime; + mfi_enqueue_busy(cm); +- } +- else { /* still get interrupts for it */ ++ } else { /* still get interrupts for it */ + hdr->cmd_status = MFI_STAT_INVALID_STATUS; + hdr->flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE; + } +@@ -1118,19 +1050,28 @@ mfi_tbolt_send_frame(struct mfi_softc *sc, struct + } + else + device_printf(sc->mfi_dev, "DJA NA XXX SYSPDIO\n"); +- } +- else if (hdr->cmd == MFI_CMD_LD_SCSI_IO || ++ } else if (hdr->cmd == MFI_CMD_LD_SCSI_IO || + hdr->cmd == MFI_CMD_LD_READ || hdr->cmd == MFI_CMD_LD_WRITE) { ++ cm->cm_flags |= MFI_CMD_SCSI; + if ((req_desc = mfi_build_and_issue_cmd(sc, cm)) == NULL) { + device_printf(sc->mfi_dev, "LDIO Failed \n"); + return 1; + } +- } else +- if ((req_desc = mfi_tbolt_build_mpt_cmd(sc, cm)) == NULL) { ++ } else if ((req_desc = mfi_tbolt_build_mpt_cmd(sc, cm)) == NULL) { + device_printf(sc->mfi_dev, "Mapping from MFI to MPT " + "Failed\n"); + return 1; +- } ++ } ++ ++ if (cm->cm_flags & MFI_CMD_SCSI) { ++ /* ++ * LD IO needs to be posted since it doesn't get ++ * acknowledged via a status update so have the ++ * controller reply via mfi_tbolt_complete_cmd. ++ */ ++ hdr->flags &= ~MFI_FRAME_DONT_POST_IN_REPLY_QUEUE; ++ } ++ + MFI_WRITE4(sc, MFI_ILQP, (req_desc->words & 0xFFFFFFFF)); + MFI_WRITE4(sc, MFI_IHQP, (req_desc->words >>0x20)); + +@@ -1137,12 +1078,21 @@ mfi_tbolt_send_frame(struct mfi_softc *sc, struct + if ((cm->cm_flags & MFI_CMD_POLLED) == 0) + return 0; + ++ if (cm->cm_flags & MFI_CMD_SCSI) { ++ /* check reply queue */ ++ mfi_tbolt_complete_cmd(sc); ++ } ++ + /* This is a polled command, so busy-wait for it to complete. */ + while (hdr->cmd_status == MFI_STAT_INVALID_STATUS) { + DELAY(1000); + tm -= 1; + if (tm <= 0) +- break; ++ break; ++ if (cm->cm_flags & MFI_CMD_SCSI) { ++ /* check reply queue */ ++ mfi_tbolt_complete_cmd(sc); ++ } + } + + if (hdr->cmd_status == MFI_STAT_INVALID_STATUS) { +@@ -1375,7 +1325,7 @@ mfi_tbolt_sync_map_info(struct mfi_softc *sc) + free(ld_sync, M_MFIBUF); + goto out; + } +- ++ + context = cmd->cm_frame->header.context; + bzero(cmd->cm_frame, sizeof(union mfi_frame)); + cmd->cm_frame->header.context = context; +Index: sys/dev/mfi/mfivar.h +=================================================================== +--- sys/dev/mfi/mfivar.h (revision 254079) ++++ sys/dev/mfi/mfivar.h (working copy) +@@ -105,6 +105,7 @@ struct mfi_command { + #define MFI_ON_MFIQ_READY (1<<6) + #define MFI_ON_MFIQ_BUSY (1<<7) + #define MFI_ON_MFIQ_MASK ((1<<5)|(1<<6)|(1<<7)) ++#define MFI_CMD_SCSI (1<<8) + uint8_t retry_for_fw_reset; + void (* cm_complete)(struct mfi_command *cm); + void *cm_private; +@@ -125,6 +126,11 @@ struct mfi_disk { + #define MFI_DISK_FLAGS_DISABLED 0x02 + }; + ++struct mfi_disk_pending { ++ TAILQ_ENTRY(mfi_disk_pending) ld_link; ++ int ld_id; ++}; ++ + struct mfi_system_pd { + TAILQ_ENTRY(mfi_system_pd) pd_link; + device_t pd_dev; +@@ -136,6 +142,11 @@ struct mfi_system_pd { + int pd_flags; + }; + ++struct mfi_system_pending { ++ TAILQ_ENTRY(mfi_system_pending) pd_link; ++ int pd_id; ++}; ++ + struct mfi_evt_queue_elm { + TAILQ_ENTRY(mfi_evt_queue_elm) link; + struct mfi_evt_detail detail; +@@ -284,6 +295,8 @@ struct mfi_softc { + + TAILQ_HEAD(,mfi_disk) mfi_ld_tqh; + TAILQ_HEAD(,mfi_system_pd) mfi_syspd_tqh; ++ TAILQ_HEAD(,mfi_disk_pending) mfi_ld_pend_tqh; ++ TAILQ_HEAD(,mfi_system_pending) mfi_syspd_pend_tqh; + eventhandler_tag mfi_eh; + struct cdev *mfi_cdev; + +@@ -302,6 +315,7 @@ struct mfi_softc { + uint32_t frame_cnt); + int (*mfi_adp_reset)(struct mfi_softc *sc); + int (*mfi_adp_check_reset)(struct mfi_softc *sc); ++ void (*mfi_intr_ptr)(void *sc); + + /* ThunderBolt */ + uint32_t mfi_tbolt; +@@ -420,7 +434,8 @@ extern int mfi_tbolt_reset(struct mfi_softc *sc); + extern void mfi_tbolt_sync_map_info(struct mfi_softc *sc); + extern void mfi_handle_map_sync(void *context, int pending); + extern int mfi_dcmd_command(struct mfi_softc *, struct mfi_command **, +- uint32_t, void **, size_t); ++ uint32_t, void **, size_t); ++extern int mfi_build_cdb(int, uint8_t, u_int64_t, u_int32_t, uint8_t *); + + #define MFIQ_ADD(sc, qname) \ + do { \ diff --git a/share/security/patches/EN-13:03/mfi.patch.asc b/share/security/patches/EN-13:03/mfi.patch.asc new file mode 100644 index 0000000000..3fd57c3721 --- /dev/null +++ b/share/security/patches/EN-13:03/mfi.patch.asc @@ -0,0 +1,7 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2.0.21 (FreeBSD) + +iEYEABECAAYFAlIVY24ACgkQFdaIBMps37JCXwCfZhVM1OjOQdzZpIxjNN80C1u1 +JskAoJxlytTc77jV6csrcPfYIFv/oTJD +=MxiW +-----END PGP SIGNATURE----- diff --git a/share/security/patches/SA-13:09/ip_multicast.patch b/share/security/patches/SA-13:09/ip_multicast.patch new file mode 100644 index 0000000000..23f68ed9c3 --- /dev/null +++ b/share/security/patches/SA-13:09/ip_multicast.patch @@ -0,0 +1,26 @@ +Index: sys/netinet/in_mcast.c +=================================================================== +--- sys/netinet/in_mcast.c (revision 254252) ++++ sys/netinet/in_mcast.c (working copy) +@@ -1648,6 +1648,8 @@ + * has asked for, but we always tell userland how big the + * buffer really needs to be. + */ ++ if (msfr.msfr_nsrcs > in_mcast_maxsocksrc) ++ msfr.msfr_nsrcs = in_mcast_maxsocksrc; + tss = NULL; + if (msfr.msfr_srcs != NULL && msfr.msfr_nsrcs > 0) { + tss = malloc(sizeof(struct sockaddr_storage) * msfr.msfr_nsrcs, +Index: sys/netinet6/in6_mcast.c +=================================================================== +--- sys/netinet6/in6_mcast.c (revision 254252) ++++ sys/netinet6/in6_mcast.c (working copy) +@@ -1625,6 +1625,8 @@ + * has asked for, but we always tell userland how big the + * buffer really needs to be. + */ ++ if (msfr.msfr_nsrcs > in6_mcast_maxsocksrc) ++ msfr.msfr_nsrcs = in6_mcast_maxsocksrc; + tss = NULL; + if (msfr.msfr_srcs != NULL && msfr.msfr_nsrcs > 0) { + tss = malloc(sizeof(struct sockaddr_storage) * msfr.msfr_nsrcs, diff --git a/share/security/patches/SA-13:09/ip_multicast.patch.asc b/share/security/patches/SA-13:09/ip_multicast.patch.asc new file mode 100644 index 0000000000..baf38f70c2 --- /dev/null +++ b/share/security/patches/SA-13:09/ip_multicast.patch.asc @@ -0,0 +1,7 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2.0.21 (FreeBSD) + +iEYEABECAAYFAlIVY24ACgkQFdaIBMps37KUkgCfU1WO0UwQEQeRo+DcgCFIf6j7 +R9YAn3m43TNCB0hft+Fmlt7ikftEOCoQ +=m93m +-----END PGP SIGNATURE----- diff --git a/share/security/patches/SA-13:10/sctp.patch b/share/security/patches/SA-13:10/sctp.patch new file mode 100644 index 0000000000..e6710e3bcb --- /dev/null +++ b/share/security/patches/SA-13:10/sctp.patch @@ -0,0 +1,19 @@ +Index: sys/netinet/sctp_output.c +=================================================================== +--- sys/netinet/sctp_output.c (revision 254337) ++++ sys/netinet/sctp_output.c (revision 254338) +@@ -5406,6 +5406,14 @@ + } + SCTP_BUF_LEN(m) = sizeof(struct sctp_init_chunk); + ++ /* ++ * We might not overwrite the identification[] completely and on ++ * some platforms time_entered will contain some padding. Therefore ++ * zero out the cookie to avoid putting uninitialized memory on the ++ * wire. ++ */ ++ memset(&stc, 0, sizeof(struct sctp_state_cookie)); ++ + /* the time I built cookie */ + (void)SCTP_GETTIME_TIMEVAL(&stc.time_entered); + diff --git a/share/security/patches/SA-13:10/sctp.patch.asc b/share/security/patches/SA-13:10/sctp.patch.asc new file mode 100644 index 0000000000..fcf586bae2 --- /dev/null +++ b/share/security/patches/SA-13:10/sctp.patch.asc @@ -0,0 +1,7 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2.0.21 (FreeBSD) + +iEYEABECAAYFAlIVY24ACgkQFdaIBMps37JspQCdHJl2JvDn4fmmqM8xLRJsHghE +onAAn1F8HgApNEcBndp/DlnyiSnPyBCw +=Qaow +-----END PGP SIGNATURE----- diff --git a/share/xml/advisories.xml b/share/xml/advisories.xml index 6ff2b8c55d..656874bf82 100644 --- a/share/xml/advisories.xml +++ b/share/xml/advisories.xml @@ -7,6 +7,22 @@ 2013 + + 8 + + + 22 + + + FreeBSD-SA-13:10.sctp + + + + FreeBSD-SA-13:09.ip_multicast + + + + 7 diff --git a/share/xml/notices.xml b/share/xml/notices.xml index b6fa79adb6..25db5f5c5b 100644 --- a/share/xml/notices.xml +++ b/share/xml/notices.xml @@ -7,6 +7,18 @@ 2013 + + 8 + + + 22 + + + FreeBSD-EN-13:03.mfi + + + + 6