Commit 4fee35a3 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi

Pull SCSI fixes from James Bottomley:
 "Three fixes this time, two in SES picked up by KASAN for various types
  of buffer overrun.  The first is a USB array which returns page 8
  whatever is asked for and causes us to overrun with incorrect data
  format assumptions and the second is an invalid iteration of page 10
  (the additional information page).

  The final fix is a reversion of a NULL deref fix which caused
  suspend/resume not to be called in pairs leading to incorrect device
  operation (Jens has queued a more proper fix for the problem in
  block)"

* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
  ses: fix additional element traversal bug
  Revert "SCSI: Fix NULL pointer dereference in runtime PM"
  ses: Fix problems with simple enclosures
parents 76b8ebdc ed94724b
...@@ -219,13 +219,13 @@ static int sdev_runtime_suspend(struct device *dev) ...@@ -219,13 +219,13 @@ static int sdev_runtime_suspend(struct device *dev)
struct scsi_device *sdev = to_scsi_device(dev); struct scsi_device *sdev = to_scsi_device(dev);
int err = 0; int err = 0;
if (pm && pm->runtime_suspend) { err = blk_pre_runtime_suspend(sdev->request_queue);
err = blk_pre_runtime_suspend(sdev->request_queue); if (err)
if (err) return err;
return err; if (pm && pm->runtime_suspend)
err = pm->runtime_suspend(dev); err = pm->runtime_suspend(dev);
blk_post_runtime_suspend(sdev->request_queue, err); blk_post_runtime_suspend(sdev->request_queue, err);
}
return err; return err;
} }
...@@ -248,11 +248,11 @@ static int sdev_runtime_resume(struct device *dev) ...@@ -248,11 +248,11 @@ static int sdev_runtime_resume(struct device *dev)
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
int err = 0; int err = 0;
if (pm && pm->runtime_resume) { blk_pre_runtime_resume(sdev->request_queue);
blk_pre_runtime_resume(sdev->request_queue); if (pm && pm->runtime_resume)
err = pm->runtime_resume(dev); err = pm->runtime_resume(dev);
blk_post_runtime_resume(sdev->request_queue, err); blk_post_runtime_resume(sdev->request_queue, err);
}
return err; return err;
} }
......
...@@ -84,6 +84,7 @@ static void init_device_slot_control(unsigned char *dest_desc, ...@@ -84,6 +84,7 @@ static void init_device_slot_control(unsigned char *dest_desc,
static int ses_recv_diag(struct scsi_device *sdev, int page_code, static int ses_recv_diag(struct scsi_device *sdev, int page_code,
void *buf, int bufflen) void *buf, int bufflen)
{ {
int ret;
unsigned char cmd[] = { unsigned char cmd[] = {
RECEIVE_DIAGNOSTIC, RECEIVE_DIAGNOSTIC,
1, /* Set PCV bit */ 1, /* Set PCV bit */
...@@ -92,9 +93,26 @@ static int ses_recv_diag(struct scsi_device *sdev, int page_code, ...@@ -92,9 +93,26 @@ static int ses_recv_diag(struct scsi_device *sdev, int page_code,
bufflen & 0xff, bufflen & 0xff,
0 0
}; };
unsigned char recv_page_code;
return scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buf, bufflen, ret = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buf, bufflen,
NULL, SES_TIMEOUT, SES_RETRIES, NULL); NULL, SES_TIMEOUT, SES_RETRIES, NULL);
if (unlikely(!ret))
return ret;
recv_page_code = ((unsigned char *)buf)[0];
if (likely(recv_page_code == page_code))
return ret;
/* successful diagnostic but wrong page code. This happens to some
* USB devices, just print a message and pretend there was an error */
sdev_printk(KERN_ERR, sdev,
"Wrong diagnostic page; asked for %d got %u\n",
page_code, recv_page_code);
return -EINVAL;
} }
static int ses_send_diag(struct scsi_device *sdev, int page_code, static int ses_send_diag(struct scsi_device *sdev, int page_code,
...@@ -541,7 +559,15 @@ static void ses_enclosure_data_process(struct enclosure_device *edev, ...@@ -541,7 +559,15 @@ static void ses_enclosure_data_process(struct enclosure_device *edev,
if (desc_ptr) if (desc_ptr)
desc_ptr += len; desc_ptr += len;
if (addl_desc_ptr) if (addl_desc_ptr &&
/* only find additional descriptions for specific devices */
(type_ptr[0] == ENCLOSURE_COMPONENT_DEVICE ||
type_ptr[0] == ENCLOSURE_COMPONENT_ARRAY_DEVICE ||
type_ptr[0] == ENCLOSURE_COMPONENT_SAS_EXPANDER ||
/* these elements are optional */
type_ptr[0] == ENCLOSURE_COMPONENT_SCSI_TARGET_PORT ||
type_ptr[0] == ENCLOSURE_COMPONENT_SCSI_INITIATOR_PORT ||
type_ptr[0] == ENCLOSURE_COMPONENT_CONTROLLER_ELECTRONICS))
addl_desc_ptr += addl_desc_ptr[1] + 2; addl_desc_ptr += addl_desc_ptr[1] + 2;
} }
......
...@@ -29,7 +29,11 @@ ...@@ -29,7 +29,11 @@
/* A few generic types ... taken from ses-2 */ /* A few generic types ... taken from ses-2 */
enum enclosure_component_type { enum enclosure_component_type {
ENCLOSURE_COMPONENT_DEVICE = 0x01, ENCLOSURE_COMPONENT_DEVICE = 0x01,
ENCLOSURE_COMPONENT_CONTROLLER_ELECTRONICS = 0x07,
ENCLOSURE_COMPONENT_SCSI_TARGET_PORT = 0x14,
ENCLOSURE_COMPONENT_SCSI_INITIATOR_PORT = 0x15,
ENCLOSURE_COMPONENT_ARRAY_DEVICE = 0x17, ENCLOSURE_COMPONENT_ARRAY_DEVICE = 0x17,
ENCLOSURE_COMPONENT_SAS_EXPANDER = 0x18,
}; };
/* ses-2 common element status */ /* ses-2 common element status */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment