--- On Mon, 3/21/11, Alan Stern <stern@xxxxxxxxxxxxxxxxxxx> wrote: > From: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx> > Subject: [PATCH] sd: Fix regression in sd_read_cache_type > To: "James Bottomley" <James.Bottomley@xxxxxxx> > Cc: "Richard Senior" <richard@xxxxxxxxxxxxxxxxxxxx>, "Luben Tuikov" <ltuikov@xxxxxxxxx>, "SCSI development list" <linux-scsi@xxxxxxxxxxxxxxx> > Date: Monday, March 21, 2011, 2:29 PM > This patch (as1454) fixes a > regression in the sd driver. Commit > 24d720b726c1a85f1962831ac30ad4d2ef8276b1 ([SCSI] Retrieve > the Caching > mode page) recently introduced the strategy of asking for > all pages > (page code 0x3F) instead of asking for the caching page > (0x08) on > devices that might not support it. This ought to be > safe, because sd > already uses page code 0x3F when checking for write > protection. > > Unfortunately, the commit did not copy the checks used by > sd_read_write_protect_flag(). Some devices don't > support page code > 0x3F, and others require a fixed transfer length of 192 > bytes. This > patch adds those checks into sd_read_cache_type(). > > Without this fix, some USB mass-storage devices crash when > they > receive a MODE SENSE command with page code 0x3F asking for > only 4 > bytes of data. > > Signed-off-by: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx> > Reported-and-tested-by: Richard Senior <richard@xxxxxxxxxxxxxxxxxxxx> > CC: Luben Tuikov <ltuikov@xxxxxxxxx> > CC: <stable@xxxxxxxxxx> Acked-by: Luben Tuikov <ltuikov@xxxxxxxxx> > > --- > > The only stable kernel requiring this fix is 2.6.38; > earlier kernels > are okay. > > > drivers/scsi/sd.c | 14 ++++++++++++-- > 1 file changed, 12 insertions(+), 2 deletions(-) > > Index: usb-2.6/drivers/scsi/sd.c > =================================================================== > --- usb-2.6.orig/drivers/scsi/sd.c > +++ usb-2.6/drivers/scsi/sd.c > @@ -1904,17 +1904,23 @@ sd_read_cache_type(struct scsi_disk > *sdk > > int dbd; > int modepage; > + int first_len; > struct scsi_mode_data data; > struct scsi_sense_hdr sshdr; > int old_wce = sdkp->WCE; > int old_rcd = sdkp->RCD; > int old_dpofua = sdkp->DPOFUA; > > + first_len = 4; > if (sdp->skip_ms_page_8) { > if (sdp->type == > TYPE_RBC) > > goto defaults; > else { > + > if (sdp->skip_ms_page_3f) > + > goto defaults; > > modepage = 0x3F; > + > if (sdp->use_192_bytes_for_3f) > + > first_len = 192; > > dbd = 0; > } > } else if (sdp->type == TYPE_RBC) { > @@ -1926,13 +1932,15 @@ sd_read_cache_type(struct scsi_disk > *sdk > } > > /* cautiously ask */ > - res = sd_do_mode_sense(sdp, dbd, > modepage, buffer, 4, &data, &sshdr); > + res = sd_do_mode_sense(sdp, dbd, > modepage, buffer, first_len, > + > &data, &sshdr); > > if (!scsi_status_is_good(res)) > goto bad_sense; > > if (!data.header_length) { > modepage = 6; > + first_len = 0; > sd_printk(KERN_ERR, > sdkp, "Missing header in MODE_SENSE response\n"); > } > > @@ -1952,7 +1960,9 @@ sd_read_cache_type(struct scsi_disk > *sdk > } > > /* Get the data */ > - res = sd_do_mode_sense(sdp, dbd, > modepage, buffer, len, &data, &sshdr); > + if (len > first_len) > + res = > sd_do_mode_sense(sdp, dbd, modepage, buffer, len, > + > &data, &sshdr); > > if (scsi_status_is_good(res)) { > int offset = > data.header_length + data.block_descriptor_length; > > -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html