SCSI fixes on 20171215
The most important one is the bfa fix because it's easy to oops the kernel with this driver (this includes the commit that corrects the compiler warning in the original), a regression in the new timespec conversion in aacraid and a regression in the Fibre Channel ELS handling patch. The other three are a theoretical problem with termination in the vendor/host matching code and a use after free in lpfc. The additional patches are a fix for an I/O hang in the mq code under certain circumstances and a rare oops in some debugging code. Signed-off-by: James E.J. Bottomley <jejb@linux.vnet.ibm.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABAgAGBQJaM/8tAAoJEAVr7HOZEZN4tqIP/ijN1H+K6LQ2lID8ocfBXfUC wWFplIjuIOsFzo17o6U3TetRClU2JMLkd7aUnvYiyIadzQxGSGbWTBxW13vobZWg uJd3oMjyRzP0DGgY5F0JWT3/DGKKthnNnsam7DDPUfY20h959aPhq0jayo274Dps DnZb6KtJhdKS3l/Bu7FEA8cOmh4pJyPfKf4lft25dFDUpJIt1f/iIA8SUbnq9hpA VwiZherXoDikOx9eEwAurvQLQ98emBaI085QusxV7d3aii4nKTnKelillSeaY7rd mhRAGPiz/8d6HlMxBLu0XVd+I7lj/9hmhJbQsy7ytW1I/oLhAt9FoHvDLzWxMHZj Zhraj3WAXQNIMWBf2n4CfvLKWsl3O+rCUESE3a7UHOlT2sMz5roYBPcpJ3yIfaPs YyDc6gwTORm9YHArKMccQN+aWYez3ysx33Su+mdYKTMK9HlqSMtoSLAxcobeUaqr nQdV4LQ6qeK9ILJSFv9BcKW/tA6s7CHFzflD/9PoxmI8jdiUV4DebMeh7Kkcw5m3 yeXOeUnYPebisK73z5DtgKZ8GJT2rIftGaitIilGXq8Q0GG5mkOOU+ng3skXKO+R DHHMOHURnzyg27cBcanb5MYTkvkNb1i/f84tBrdQ5AoZycmmzU44nDCf+4peHE8g k5THgzBVQXeXJ3Vq+cJV =9sav -----END PGP SIGNATURE----- Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi Pull SCSI fixes from James Bottomley: "The most important one is the bfa fix because it's easy to oops the kernel with this driver (this includes the commit that corrects the compiler warning in the original), a regression in the new timespec conversion in aacraid and a regression in the Fibre Channel ELS handling patch. The other three are a theoretical problem with termination in the vendor/host matching code and a use after free in lpfc. The additional patches are a fix for an I/O hang in the mq code under certain circumstances and a rare oops in some debugging code" * tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: scsi: core: Fix a scsi_show_rq() NULL pointer dereference scsi: MAINTAINERS: change FCoE list to linux-scsi scsi: libsas: fix length error in sas_smp_handler() scsi: bfa: fix type conversion warning scsi: core: run queue if SCSI device queue isn't ready and queue is idle scsi: scsi_devinfo: cleanly zero-pad devinfo strings scsi: scsi_devinfo: handle non-terminated strings scsi: bfa: fix access to bfad_im_port_s scsi: aacraid: address UBSAN warning regression scsi: libfc: fix ELS request handling scsi: lpfc: Use after free in lpfc_rq_buf_free()
This commit is contained in:
commit
66dbbd7200
|
@ -5431,7 +5431,7 @@ F: drivers/media/tuners/fc2580*
|
|||
|
||||
FCOE SUBSYSTEM (libfc, libfcoe, fcoe)
|
||||
M: Johannes Thumshirn <jth@kernel.org>
|
||||
L: fcoe-devel@open-fcoe.org
|
||||
L: linux-scsi@vger.kernel.org
|
||||
W: www.Open-FCoE.org
|
||||
S: Supported
|
||||
F: drivers/scsi/libfc/
|
||||
|
|
|
@ -2482,8 +2482,8 @@ int aac_command_thread(void *data)
|
|||
/* Synchronize our watches */
|
||||
if (((NSEC_PER_SEC - (NSEC_PER_SEC / HZ)) > now.tv_nsec)
|
||||
&& (now.tv_nsec > (NSEC_PER_SEC / HZ)))
|
||||
difference = (((NSEC_PER_SEC - now.tv_nsec) * HZ)
|
||||
+ NSEC_PER_SEC / 2) / NSEC_PER_SEC;
|
||||
difference = HZ + HZ / 2 -
|
||||
now.tv_nsec / (NSEC_PER_SEC / HZ);
|
||||
else {
|
||||
if (now.tv_nsec > NSEC_PER_SEC / 2)
|
||||
++now.tv_sec;
|
||||
|
@ -2507,6 +2507,10 @@ int aac_command_thread(void *data)
|
|||
if (kthread_should_stop())
|
||||
break;
|
||||
|
||||
/*
|
||||
* we probably want usleep_range() here instead of the
|
||||
* jiffies computation
|
||||
*/
|
||||
schedule_timeout(difference);
|
||||
|
||||
if (kthread_should_stop())
|
||||
|
|
|
@ -3135,7 +3135,8 @@ bfad_im_bsg_vendor_request(struct bsg_job *job)
|
|||
struct fc_bsg_request *bsg_request = job->request;
|
||||
struct fc_bsg_reply *bsg_reply = job->reply;
|
||||
uint32_t vendor_cmd = bsg_request->rqst_data.h_vendor.vendor_cmd[0];
|
||||
struct bfad_im_port_s *im_port = shost_priv(fc_bsg_to_shost(job));
|
||||
struct Scsi_Host *shost = fc_bsg_to_shost(job);
|
||||
struct bfad_im_port_s *im_port = bfad_get_im_port(shost);
|
||||
struct bfad_s *bfad = im_port->bfad;
|
||||
void *payload_kbuf;
|
||||
int rc = -EINVAL;
|
||||
|
@ -3350,7 +3351,8 @@ int
|
|||
bfad_im_bsg_els_ct_request(struct bsg_job *job)
|
||||
{
|
||||
struct bfa_bsg_data *bsg_data;
|
||||
struct bfad_im_port_s *im_port = shost_priv(fc_bsg_to_shost(job));
|
||||
struct Scsi_Host *shost = fc_bsg_to_shost(job);
|
||||
struct bfad_im_port_s *im_port = bfad_get_im_port(shost);
|
||||
struct bfad_s *bfad = im_port->bfad;
|
||||
bfa_bsg_fcpt_t *bsg_fcpt;
|
||||
struct bfad_fcxp *drv_fcxp;
|
||||
|
|
|
@ -546,6 +546,7 @@ int
|
|||
bfad_im_scsi_host_alloc(struct bfad_s *bfad, struct bfad_im_port_s *im_port,
|
||||
struct device *dev)
|
||||
{
|
||||
struct bfad_im_port_pointer *im_portp;
|
||||
int error = 1;
|
||||
|
||||
mutex_lock(&bfad_mutex);
|
||||
|
@ -564,7 +565,8 @@ bfad_im_scsi_host_alloc(struct bfad_s *bfad, struct bfad_im_port_s *im_port,
|
|||
goto out_free_idr;
|
||||
}
|
||||
|
||||
im_port->shost->hostdata[0] = (unsigned long)im_port;
|
||||
im_portp = shost_priv(im_port->shost);
|
||||
im_portp->p = im_port;
|
||||
im_port->shost->unique_id = im_port->idr_id;
|
||||
im_port->shost->this_id = -1;
|
||||
im_port->shost->max_id = MAX_FCP_TARGET;
|
||||
|
@ -748,7 +750,7 @@ bfad_scsi_host_alloc(struct bfad_im_port_s *im_port, struct bfad_s *bfad)
|
|||
|
||||
sht->sg_tablesize = bfad->cfg_data.io_max_sge;
|
||||
|
||||
return scsi_host_alloc(sht, sizeof(unsigned long));
|
||||
return scsi_host_alloc(sht, sizeof(struct bfad_im_port_pointer));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -69,6 +69,16 @@ struct bfad_im_port_s {
|
|||
struct fc_vport *fc_vport;
|
||||
};
|
||||
|
||||
struct bfad_im_port_pointer {
|
||||
struct bfad_im_port_s *p;
|
||||
};
|
||||
|
||||
static inline struct bfad_im_port_s *bfad_get_im_port(struct Scsi_Host *host)
|
||||
{
|
||||
struct bfad_im_port_pointer *im_portp = shost_priv(host);
|
||||
return im_portp->p;
|
||||
}
|
||||
|
||||
enum bfad_itnim_state {
|
||||
ITNIM_STATE_NONE,
|
||||
ITNIM_STATE_ONLINE,
|
||||
|
|
|
@ -904,10 +904,14 @@ static void fc_lport_recv_els_req(struct fc_lport *lport,
|
|||
case ELS_FLOGI:
|
||||
if (!lport->point_to_multipoint)
|
||||
fc_lport_recv_flogi_req(lport, fp);
|
||||
else
|
||||
fc_rport_recv_req(lport, fp);
|
||||
break;
|
||||
case ELS_LOGO:
|
||||
if (fc_frame_sid(fp) == FC_FID_FLOGI)
|
||||
fc_lport_recv_logo_req(lport, fp);
|
||||
else
|
||||
fc_rport_recv_req(lport, fp);
|
||||
break;
|
||||
case ELS_RSCN:
|
||||
lport->tt.disc_recv_req(lport, fp);
|
||||
|
|
|
@ -2145,7 +2145,7 @@ void sas_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
|
|||
struct sas_rphy *rphy)
|
||||
{
|
||||
struct domain_device *dev;
|
||||
unsigned int reslen = 0;
|
||||
unsigned int rcvlen = 0;
|
||||
int ret = -EINVAL;
|
||||
|
||||
/* no rphy means no smp target support (ie aic94xx host) */
|
||||
|
@ -2179,12 +2179,12 @@ void sas_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
|
|||
|
||||
ret = smp_execute_task_sg(dev, job->request_payload.sg_list,
|
||||
job->reply_payload.sg_list);
|
||||
if (ret > 0) {
|
||||
/* positive number is the untransferred residual */
|
||||
reslen = ret;
|
||||
if (ret >= 0) {
|
||||
/* bsg_job_done() requires the length received */
|
||||
rcvlen = job->reply_payload.payload_len - ret;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
out:
|
||||
bsg_job_done(job, ret, reslen);
|
||||
bsg_job_done(job, ret, rcvlen);
|
||||
}
|
||||
|
|
|
@ -753,12 +753,12 @@ lpfc_rq_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp)
|
|||
drqe.address_hi = putPaddrHigh(rqb_entry->dbuf.phys);
|
||||
rc = lpfc_sli4_rq_put(rqb_entry->hrq, rqb_entry->drq, &hrqe, &drqe);
|
||||
if (rc < 0) {
|
||||
(rqbp->rqb_free_buffer)(phba, rqb_entry);
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||
"6409 Cannot post to RQ %d: %x %x\n",
|
||||
rqb_entry->hrq->queue_id,
|
||||
rqb_entry->hrq->host_index,
|
||||
rqb_entry->hrq->hba_index);
|
||||
(rqbp->rqb_free_buffer)(phba, rqb_entry);
|
||||
} else {
|
||||
list_add_tail(&rqb_entry->hbuf.list, &rqbp->rqb_buffer_list);
|
||||
rqbp->buffer_count++;
|
||||
|
|
|
@ -8,9 +8,11 @@ void scsi_show_rq(struct seq_file *m, struct request *rq)
|
|||
{
|
||||
struct scsi_cmnd *cmd = container_of(scsi_req(rq), typeof(*cmd), req);
|
||||
int msecs = jiffies_to_msecs(jiffies - cmd->jiffies_at_alloc);
|
||||
char buf[80];
|
||||
const u8 *const cdb = READ_ONCE(cmd->cmnd);
|
||||
char buf[80] = "(?)";
|
||||
|
||||
__scsi_format_command(buf, sizeof(buf), cmd->cmnd, cmd->cmd_len);
|
||||
if (cdb)
|
||||
__scsi_format_command(buf, sizeof(buf), cdb, cmd->cmd_len);
|
||||
seq_printf(m, ", .cmd=%s, .retries=%d, allocated %d.%03d s ago", buf,
|
||||
cmd->retries, msecs / 1000, msecs % 1000);
|
||||
}
|
||||
|
|
|
@ -34,7 +34,6 @@ struct scsi_dev_info_list_table {
|
|||
};
|
||||
|
||||
|
||||
static const char spaces[] = " "; /* 16 of them */
|
||||
static blist_flags_t scsi_default_dev_flags;
|
||||
static LIST_HEAD(scsi_dev_info_list);
|
||||
static char scsi_dev_flags[256];
|
||||
|
@ -298,20 +297,13 @@ static void scsi_strcpy_devinfo(char *name, char *to, size_t to_length,
|
|||
size_t from_length;
|
||||
|
||||
from_length = strlen(from);
|
||||
strncpy(to, from, min(to_length, from_length));
|
||||
if (from_length < to_length) {
|
||||
if (compatible) {
|
||||
/*
|
||||
* NUL terminate the string if it is short.
|
||||
*/
|
||||
to[from_length] = '\0';
|
||||
} else {
|
||||
/*
|
||||
* space pad the string if it is short.
|
||||
*/
|
||||
strncpy(&to[from_length], spaces,
|
||||
to_length - from_length);
|
||||
}
|
||||
/* This zero-pads the destination */
|
||||
strncpy(to, from, to_length);
|
||||
if (from_length < to_length && !compatible) {
|
||||
/*
|
||||
* space pad the string if it is short.
|
||||
*/
|
||||
memset(&to[from_length], ' ', to_length - from_length);
|
||||
}
|
||||
if (from_length > to_length)
|
||||
printk(KERN_WARNING "%s: %s string '%s' is too long\n",
|
||||
|
@ -458,7 +450,8 @@ static struct scsi_dev_info_list *scsi_dev_info_list_find(const char *vendor,
|
|||
/*
|
||||
* vendor strings must be an exact match
|
||||
*/
|
||||
if (vmax != strlen(devinfo->vendor) ||
|
||||
if (vmax != strnlen(devinfo->vendor,
|
||||
sizeof(devinfo->vendor)) ||
|
||||
memcmp(devinfo->vendor, vskip, vmax))
|
||||
continue;
|
||||
|
||||
|
@ -466,7 +459,7 @@ static struct scsi_dev_info_list *scsi_dev_info_list_find(const char *vendor,
|
|||
* @model specifies the full string, and
|
||||
* must be larger or equal to devinfo->model
|
||||
*/
|
||||
mlen = strlen(devinfo->model);
|
||||
mlen = strnlen(devinfo->model, sizeof(devinfo->model));
|
||||
if (mmax < mlen || memcmp(devinfo->model, mskip, mlen))
|
||||
continue;
|
||||
return devinfo;
|
||||
|
|
|
@ -1967,6 +1967,8 @@ static bool scsi_mq_get_budget(struct blk_mq_hw_ctx *hctx)
|
|||
out_put_device:
|
||||
put_device(&sdev->sdev_gendev);
|
||||
out:
|
||||
if (atomic_read(&sdev->device_busy) == 0 && !scsi_device_blocked(sdev))
|
||||
blk_mq_delay_run_hw_queue(hctx, SCSI_QUEUE_DELAY);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1312,6 +1312,7 @@ static int sd_init_command(struct scsi_cmnd *cmd)
|
|||
static void sd_uninit_command(struct scsi_cmnd *SCpnt)
|
||||
{
|
||||
struct request *rq = SCpnt->request;
|
||||
u8 *cmnd;
|
||||
|
||||
if (SCpnt->flags & SCMD_ZONE_WRITE_LOCK)
|
||||
sd_zbc_write_unlock_zone(SCpnt);
|
||||
|
@ -1320,9 +1321,10 @@ static void sd_uninit_command(struct scsi_cmnd *SCpnt)
|
|||
__free_page(rq->special_vec.bv_page);
|
||||
|
||||
if (SCpnt->cmnd != scsi_req(rq)->cmd) {
|
||||
mempool_free(SCpnt->cmnd, sd_cdb_pool);
|
||||
cmnd = SCpnt->cmnd;
|
||||
SCpnt->cmnd = NULL;
|
||||
SCpnt->cmd_len = 0;
|
||||
mempool_free(cmnd, sd_cdb_pool);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue