diff options
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas.h | 2 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas_base.c | 15 | ||||
-rw-r--r-- | drivers/scsi/ses.c | 30 |
3 files changed, 42 insertions, 5 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index b52121358385..280e769a1686 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -300,6 +300,8 @@ enum MR_EVT_ARGS { MR_EVT_ARGS_GENERIC, }; + +#define SGE_BUFFER_SIZE 4096 /* * define constants for device list query options */ diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 78b4fe845245..e6dfa8108301 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -3602,7 +3602,7 @@ static int megasas_init_fw(struct megasas_instance *instance) } instance->max_sectors_per_req = instance->max_num_sge * - PAGE_SIZE / 512; + SGE_BUFFER_SIZE / 512; if (tmp_sectors && (instance->max_sectors_per_req > tmp_sectors)) instance->max_sectors_per_req = tmp_sectors; @@ -5051,6 +5051,9 @@ static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg) int i; int error = 0; compat_uptr_t ptr; + unsigned long local_raw_ptr; + u32 local_sense_off; + u32 local_sense_len; if (clear_user(ioc, sizeof(*ioc))) return -EFAULT; @@ -5068,9 +5071,15 @@ static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg) * sense_len is not null, so prepare the 64bit value under * the same condition. */ - if (ioc->sense_len) { + if (get_user(local_raw_ptr, ioc->frame.raw) || + get_user(local_sense_off, &ioc->sense_off) || + get_user(local_sense_len, &ioc->sense_len)) + return -EFAULT; + + + if (local_sense_len) { void __user **sense_ioc_ptr = - (void __user **)(ioc->frame.raw + ioc->sense_off); + (void __user **)((u8*)local_raw_ptr + local_sense_off); compat_uptr_t *sense_cioc_ptr = (compat_uptr_t *)(cioc->frame.raw + cioc->sense_off); if (get_user(ptr, sense_cioc_ptr) || diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c index eba183c428cf..3643bbf5456d 100644 --- a/drivers/scsi/ses.c +++ b/drivers/scsi/ses.c @@ -70,6 +70,7 @@ static int ses_probe(struct device *dev) static int ses_recv_diag(struct scsi_device *sdev, int page_code, void *buf, int bufflen) { + int ret; unsigned char cmd[] = { RECEIVE_DIAGNOSTIC, 1, /* Set PCV bit */ @@ -78,9 +79,26 @@ static int ses_recv_diag(struct scsi_device *sdev, int page_code, bufflen & 0xff, 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); + 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, @@ -436,7 +454,15 @@ static void ses_enclosure_data_process(struct enclosure_device *edev, if (desc_ptr) 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; } |