Commit 846e8dd4 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

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

James writes:
  "SCSI fixes on 20180925

   Nine obvious bug fixes mostly in individual drivers.  The target fix
   is of particular importance because it's CVE related."

* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
  scsi: sd: don't crash the host on invalid commands
  scsi: ipr: System hung while dlpar adding primary ipr adapter back
  scsi: target: iscsi: Use bin2hex instead of a re-implementation
  scsi: target: iscsi: Use hex2bin instead of a re-implementation
  scsi: lpfc: Synchronize access to remoteport via rport
  scsi: ufs: Disable blk-mq for now
  scsi: sd: Contribute to randomness when running rotational device
  scsi: ibmvscsis: Ensure partition name is properly NUL terminated
  scsi: ibmvscsis: Fix a stringop-overflow warning
parents bfb0e9b4 f1f1fada
...@@ -3474,11 +3474,10 @@ static int ibmvscsis_probe(struct vio_dev *vdev, ...@@ -3474,11 +3474,10 @@ static int ibmvscsis_probe(struct vio_dev *vdev,
vscsi->dds.window[LOCAL].liobn, vscsi->dds.window[LOCAL].liobn,
vscsi->dds.window[REMOTE].liobn); vscsi->dds.window[REMOTE].liobn);
strcpy(vscsi->eye, "VSCSI "); snprintf(vscsi->eye, sizeof(vscsi->eye), "VSCSI %s", vdev->name);
strncat(vscsi->eye, vdev->name, MAX_EYE);
vscsi->dds.unit_id = vdev->unit_address; vscsi->dds.unit_id = vdev->unit_address;
strncpy(vscsi->dds.partition_name, partition_name, strscpy(vscsi->dds.partition_name, partition_name,
sizeof(vscsi->dds.partition_name)); sizeof(vscsi->dds.partition_name));
vscsi->dds.partition_num = partition_number; vscsi->dds.partition_num = partition_number;
......
...@@ -3335,6 +3335,65 @@ static void ipr_release_dump(struct kref *kref) ...@@ -3335,6 +3335,65 @@ static void ipr_release_dump(struct kref *kref)
LEAVE; LEAVE;
} }
static void ipr_add_remove_thread(struct work_struct *work)
{
unsigned long lock_flags;
struct ipr_resource_entry *res;
struct scsi_device *sdev;
struct ipr_ioa_cfg *ioa_cfg =
container_of(work, struct ipr_ioa_cfg, scsi_add_work_q);
u8 bus, target, lun;
int did_work;
ENTER;
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
restart:
do {
did_work = 0;
if (!ioa_cfg->hrrq[IPR_INIT_HRRQ].allow_cmds) {
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
return;
}
list_for_each_entry(res, &ioa_cfg->used_res_q, queue) {
if (res->del_from_ml && res->sdev) {
did_work = 1;
sdev = res->sdev;
if (!scsi_device_get(sdev)) {
if (!res->add_to_ml)
list_move_tail(&res->queue, &ioa_cfg->free_res_q);
else
res->del_from_ml = 0;
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
scsi_remove_device(sdev);
scsi_device_put(sdev);
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
}
break;
}
}
} while (did_work);
list_for_each_entry(res, &ioa_cfg->used_res_q, queue) {
if (res->add_to_ml) {
bus = res->bus;
target = res->target;
lun = res->lun;
res->add_to_ml = 0;
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
scsi_add_device(ioa_cfg->host, bus, target, lun);
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
goto restart;
}
}
ioa_cfg->scan_done = 1;
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
kobject_uevent(&ioa_cfg->host->shost_dev.kobj, KOBJ_CHANGE);
LEAVE;
}
/** /**
* ipr_worker_thread - Worker thread * ipr_worker_thread - Worker thread
* @work: ioa config struct * @work: ioa config struct
...@@ -3349,13 +3408,9 @@ static void ipr_release_dump(struct kref *kref) ...@@ -3349,13 +3408,9 @@ static void ipr_release_dump(struct kref *kref)
static void ipr_worker_thread(struct work_struct *work) static void ipr_worker_thread(struct work_struct *work)
{ {
unsigned long lock_flags; unsigned long lock_flags;
struct ipr_resource_entry *res;
struct scsi_device *sdev;
struct ipr_dump *dump; struct ipr_dump *dump;
struct ipr_ioa_cfg *ioa_cfg = struct ipr_ioa_cfg *ioa_cfg =
container_of(work, struct ipr_ioa_cfg, work_q); container_of(work, struct ipr_ioa_cfg, work_q);
u8 bus, target, lun;
int did_work;
ENTER; ENTER;
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
...@@ -3393,49 +3448,9 @@ static void ipr_worker_thread(struct work_struct *work) ...@@ -3393,49 +3448,9 @@ static void ipr_worker_thread(struct work_struct *work)
return; return;
} }
restart: schedule_work(&ioa_cfg->scsi_add_work_q);
do {
did_work = 0;
if (!ioa_cfg->hrrq[IPR_INIT_HRRQ].allow_cmds) {
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
return;
}
list_for_each_entry(res, &ioa_cfg->used_res_q, queue) {
if (res->del_from_ml && res->sdev) {
did_work = 1;
sdev = res->sdev;
if (!scsi_device_get(sdev)) {
if (!res->add_to_ml)
list_move_tail(&res->queue, &ioa_cfg->free_res_q);
else
res->del_from_ml = 0;
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
scsi_remove_device(sdev);
scsi_device_put(sdev);
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
}
break;
}
}
} while (did_work);
list_for_each_entry(res, &ioa_cfg->used_res_q, queue) {
if (res->add_to_ml) {
bus = res->bus;
target = res->target;
lun = res->lun;
res->add_to_ml = 0;
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
scsi_add_device(ioa_cfg->host, bus, target, lun);
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
goto restart;
}
}
ioa_cfg->scan_done = 1;
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
kobject_uevent(&ioa_cfg->host->shost_dev.kobj, KOBJ_CHANGE);
LEAVE; LEAVE;
} }
...@@ -9933,6 +9948,7 @@ static void ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg, ...@@ -9933,6 +9948,7 @@ static void ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg,
INIT_LIST_HEAD(&ioa_cfg->free_res_q); INIT_LIST_HEAD(&ioa_cfg->free_res_q);
INIT_LIST_HEAD(&ioa_cfg->used_res_q); INIT_LIST_HEAD(&ioa_cfg->used_res_q);
INIT_WORK(&ioa_cfg->work_q, ipr_worker_thread); INIT_WORK(&ioa_cfg->work_q, ipr_worker_thread);
INIT_WORK(&ioa_cfg->scsi_add_work_q, ipr_add_remove_thread);
init_waitqueue_head(&ioa_cfg->reset_wait_q); init_waitqueue_head(&ioa_cfg->reset_wait_q);
init_waitqueue_head(&ioa_cfg->msi_wait_q); init_waitqueue_head(&ioa_cfg->msi_wait_q);
init_waitqueue_head(&ioa_cfg->eeh_wait_q); init_waitqueue_head(&ioa_cfg->eeh_wait_q);
......
...@@ -1575,6 +1575,7 @@ struct ipr_ioa_cfg { ...@@ -1575,6 +1575,7 @@ struct ipr_ioa_cfg {
u8 saved_mode_page_len; u8 saved_mode_page_len;
struct work_struct work_q; struct work_struct work_q;
struct work_struct scsi_add_work_q;
struct workqueue_struct *reset_work_q; struct workqueue_struct *reset_work_q;
wait_queue_head_t reset_wait_q; wait_queue_head_t reset_wait_q;
......
...@@ -360,12 +360,12 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr, ...@@ -360,12 +360,12 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
goto buffer_done; goto buffer_done;
list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
nrport = NULL;
spin_lock(&vport->phba->hbalock);
rport = lpfc_ndlp_get_nrport(ndlp); rport = lpfc_ndlp_get_nrport(ndlp);
if (!rport) if (rport)
continue; nrport = rport->remoteport;
spin_unlock(&vport->phba->hbalock);
/* local short-hand pointer. */
nrport = rport->remoteport;
if (!nrport) if (!nrport)
continue; continue;
...@@ -3386,6 +3386,7 @@ lpfc_update_rport_devloss_tmo(struct lpfc_vport *vport) ...@@ -3386,6 +3386,7 @@ lpfc_update_rport_devloss_tmo(struct lpfc_vport *vport)
struct lpfc_nodelist *ndlp; struct lpfc_nodelist *ndlp;
#if (IS_ENABLED(CONFIG_NVME_FC)) #if (IS_ENABLED(CONFIG_NVME_FC))
struct lpfc_nvme_rport *rport; struct lpfc_nvme_rport *rport;
struct nvme_fc_remote_port *remoteport = NULL;
#endif #endif
shost = lpfc_shost_from_vport(vport); shost = lpfc_shost_from_vport(vport);
...@@ -3396,8 +3397,12 @@ lpfc_update_rport_devloss_tmo(struct lpfc_vport *vport) ...@@ -3396,8 +3397,12 @@ lpfc_update_rport_devloss_tmo(struct lpfc_vport *vport)
if (ndlp->rport) if (ndlp->rport)
ndlp->rport->dev_loss_tmo = vport->cfg_devloss_tmo; ndlp->rport->dev_loss_tmo = vport->cfg_devloss_tmo;
#if (IS_ENABLED(CONFIG_NVME_FC)) #if (IS_ENABLED(CONFIG_NVME_FC))
spin_lock(&vport->phba->hbalock);
rport = lpfc_ndlp_get_nrport(ndlp); rport = lpfc_ndlp_get_nrport(ndlp);
if (rport) if (rport)
remoteport = rport->remoteport;
spin_unlock(&vport->phba->hbalock);
if (remoteport)
nvme_fc_set_remoteport_devloss(rport->remoteport, nvme_fc_set_remoteport_devloss(rport->remoteport,
vport->cfg_devloss_tmo); vport->cfg_devloss_tmo);
#endif #endif
......
...@@ -551,7 +551,7 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size) ...@@ -551,7 +551,7 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
unsigned char *statep; unsigned char *statep;
struct nvme_fc_local_port *localport; struct nvme_fc_local_port *localport;
struct lpfc_nvmet_tgtport *tgtp; struct lpfc_nvmet_tgtport *tgtp;
struct nvme_fc_remote_port *nrport; struct nvme_fc_remote_port *nrport = NULL;
struct lpfc_nvme_rport *rport; struct lpfc_nvme_rport *rport;
cnt = (LPFC_NODELIST_SIZE / LPFC_NODELIST_ENTRY_SIZE); cnt = (LPFC_NODELIST_SIZE / LPFC_NODELIST_ENTRY_SIZE);
...@@ -696,11 +696,11 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size) ...@@ -696,11 +696,11 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
len += snprintf(buf + len, size - len, "\tRport List:\n"); len += snprintf(buf + len, size - len, "\tRport List:\n");
list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
/* local short-hand pointer. */ /* local short-hand pointer. */
spin_lock(&phba->hbalock);
rport = lpfc_ndlp_get_nrport(ndlp); rport = lpfc_ndlp_get_nrport(ndlp);
if (!rport) if (rport)
continue; nrport = rport->remoteport;
spin_unlock(&phba->hbalock);
nrport = rport->remoteport;
if (!nrport) if (!nrport)
continue; continue;
......
...@@ -2725,7 +2725,9 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) ...@@ -2725,7 +2725,9 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
rpinfo.port_name = wwn_to_u64(ndlp->nlp_portname.u.wwn); rpinfo.port_name = wwn_to_u64(ndlp->nlp_portname.u.wwn);
rpinfo.node_name = wwn_to_u64(ndlp->nlp_nodename.u.wwn); rpinfo.node_name = wwn_to_u64(ndlp->nlp_nodename.u.wwn);
spin_lock_irq(&vport->phba->hbalock);
oldrport = lpfc_ndlp_get_nrport(ndlp); oldrport = lpfc_ndlp_get_nrport(ndlp);
spin_unlock_irq(&vport->phba->hbalock);
if (!oldrport) if (!oldrport)
lpfc_nlp_get(ndlp); lpfc_nlp_get(ndlp);
...@@ -2840,7 +2842,7 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) ...@@ -2840,7 +2842,7 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
struct nvme_fc_local_port *localport; struct nvme_fc_local_port *localport;
struct lpfc_nvme_lport *lport; struct lpfc_nvme_lport *lport;
struct lpfc_nvme_rport *rport; struct lpfc_nvme_rport *rport;
struct nvme_fc_remote_port *remoteport; struct nvme_fc_remote_port *remoteport = NULL;
localport = vport->localport; localport = vport->localport;
...@@ -2854,11 +2856,14 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) ...@@ -2854,11 +2856,14 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
if (!lport) if (!lport)
goto input_err; goto input_err;
spin_lock_irq(&vport->phba->hbalock);
rport = lpfc_ndlp_get_nrport(ndlp); rport = lpfc_ndlp_get_nrport(ndlp);
if (!rport) if (rport)
remoteport = rport->remoteport;
spin_unlock_irq(&vport->phba->hbalock);
if (!remoteport)
goto input_err; goto input_err;
remoteport = rport->remoteport;
lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC, lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC,
"6033 Unreg nvme remoteport %p, portname x%llx, " "6033 Unreg nvme remoteport %p, portname x%llx, "
"port_id x%06x, portstate x%x port type x%x\n", "port_id x%06x, portstate x%x port type x%x\n",
......
...@@ -1276,7 +1276,8 @@ static int sd_init_command(struct scsi_cmnd *cmd) ...@@ -1276,7 +1276,8 @@ static int sd_init_command(struct scsi_cmnd *cmd)
case REQ_OP_ZONE_RESET: case REQ_OP_ZONE_RESET:
return sd_zbc_setup_reset_cmnd(cmd); return sd_zbc_setup_reset_cmnd(cmd);
default: default:
BUG(); WARN_ON_ONCE(1);
return BLKPREP_KILL;
} }
} }
...@@ -2959,6 +2960,9 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp) ...@@ -2959,6 +2960,9 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp)
if (rot == 1) { if (rot == 1) {
blk_queue_flag_set(QUEUE_FLAG_NONROT, q); blk_queue_flag_set(QUEUE_FLAG_NONROT, q);
blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, q); blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, q);
} else {
blk_queue_flag_clear(QUEUE_FLAG_NONROT, q);
blk_queue_flag_set(QUEUE_FLAG_ADD_RANDOM, q);
} }
if (sdkp->device->type == TYPE_ZBC) { if (sdkp->device->type == TYPE_ZBC) {
......
...@@ -7940,6 +7940,13 @@ int ufshcd_alloc_host(struct device *dev, struct ufs_hba **hba_handle) ...@@ -7940,6 +7940,13 @@ int ufshcd_alloc_host(struct device *dev, struct ufs_hba **hba_handle)
err = -ENOMEM; err = -ENOMEM;
goto out_error; goto out_error;
} }
/*
* Do not use blk-mq at this time because blk-mq does not support
* runtime pm.
*/
host->use_blk_mq = false;
hba = shost_priv(host); hba = shost_priv(host);
hba->host = host; hba->host = host;
hba->dev = dev; hba->dev = dev;
......
...@@ -26,27 +26,6 @@ ...@@ -26,27 +26,6 @@
#include "iscsi_target_nego.h" #include "iscsi_target_nego.h"
#include "iscsi_target_auth.h" #include "iscsi_target_auth.h"
static int chap_string_to_hex(unsigned char *dst, unsigned char *src, int len)
{
int j = DIV_ROUND_UP(len, 2), rc;
rc = hex2bin(dst, src, j);
if (rc < 0)
pr_debug("CHAP string contains non hex digit symbols\n");
dst[j] = '\0';
return j;
}
static void chap_binaryhex_to_asciihex(char *dst, char *src, int src_len)
{
int i;
for (i = 0; i < src_len; i++) {
sprintf(&dst[i*2], "%02x", (int) src[i] & 0xff);
}
}
static int chap_gen_challenge( static int chap_gen_challenge(
struct iscsi_conn *conn, struct iscsi_conn *conn,
int caller, int caller,
...@@ -62,7 +41,7 @@ static int chap_gen_challenge( ...@@ -62,7 +41,7 @@ static int chap_gen_challenge(
ret = get_random_bytes_wait(chap->challenge, CHAP_CHALLENGE_LENGTH); ret = get_random_bytes_wait(chap->challenge, CHAP_CHALLENGE_LENGTH);
if (unlikely(ret)) if (unlikely(ret))
return ret; return ret;
chap_binaryhex_to_asciihex(challenge_asciihex, chap->challenge, bin2hex(challenge_asciihex, chap->challenge,
CHAP_CHALLENGE_LENGTH); CHAP_CHALLENGE_LENGTH);
/* /*
* Set CHAP_C, and copy the generated challenge into c_str. * Set CHAP_C, and copy the generated challenge into c_str.
...@@ -248,9 +227,16 @@ static int chap_server_compute_md5( ...@@ -248,9 +227,16 @@ static int chap_server_compute_md5(
pr_err("Could not find CHAP_R.\n"); pr_err("Could not find CHAP_R.\n");
goto out; goto out;
} }
if (strlen(chap_r) != MD5_SIGNATURE_SIZE * 2) {
pr_err("Malformed CHAP_R\n");
goto out;
}
if (hex2bin(client_digest, chap_r, MD5_SIGNATURE_SIZE) < 0) {
pr_err("Malformed CHAP_R\n");
goto out;
}
pr_debug("[server] Got CHAP_R=%s\n", chap_r); pr_debug("[server] Got CHAP_R=%s\n", chap_r);
chap_string_to_hex(client_digest, chap_r, strlen(chap_r));
tfm = crypto_alloc_shash("md5", 0, 0); tfm = crypto_alloc_shash("md5", 0, 0);
if (IS_ERR(tfm)) { if (IS_ERR(tfm)) {
...@@ -294,7 +280,7 @@ static int chap_server_compute_md5( ...@@ -294,7 +280,7 @@ static int chap_server_compute_md5(
goto out; goto out;
} }
chap_binaryhex_to_asciihex(response, server_digest, MD5_SIGNATURE_SIZE); bin2hex(response, server_digest, MD5_SIGNATURE_SIZE);
pr_debug("[server] MD5 Server Digest: %s\n", response); pr_debug("[server] MD5 Server Digest: %s\n", response);
if (memcmp(server_digest, client_digest, MD5_SIGNATURE_SIZE) != 0) { if (memcmp(server_digest, client_digest, MD5_SIGNATURE_SIZE) != 0) {
...@@ -349,9 +335,7 @@ static int chap_server_compute_md5( ...@@ -349,9 +335,7 @@ static int chap_server_compute_md5(
pr_err("Could not find CHAP_C.\n"); pr_err("Could not find CHAP_C.\n");
goto out; goto out;
} }
pr_debug("[server] Got CHAP_C=%s\n", challenge); challenge_len = DIV_ROUND_UP(strlen(challenge), 2);
challenge_len = chap_string_to_hex(challenge_binhex, challenge,
strlen(challenge));
if (!challenge_len) { if (!challenge_len) {
pr_err("Unable to convert incoming challenge\n"); pr_err("Unable to convert incoming challenge\n");
goto out; goto out;
...@@ -360,6 +344,11 @@ static int chap_server_compute_md5( ...@@ -360,6 +344,11 @@ static int chap_server_compute_md5(
pr_err("CHAP_C exceeds maximum binary size of 1024 bytes\n"); pr_err("CHAP_C exceeds maximum binary size of 1024 bytes\n");
goto out; goto out;
} }
if (hex2bin(challenge_binhex, challenge, challenge_len) < 0) {
pr_err("Malformed CHAP_C\n");
goto out;
}
pr_debug("[server] Got CHAP_C=%s\n", challenge);
/* /*
* During mutual authentication, the CHAP_C generated by the * During mutual authentication, the CHAP_C generated by the
* initiator must not match the original CHAP_C generated by * initiator must not match the original CHAP_C generated by
...@@ -413,7 +402,7 @@ static int chap_server_compute_md5( ...@@ -413,7 +402,7 @@ static int chap_server_compute_md5(
/* /*
* Convert response from binary hex to ascii hext. * Convert response from binary hex to ascii hext.
*/ */
chap_binaryhex_to_asciihex(response, digest, MD5_SIGNATURE_SIZE); bin2hex(response, digest, MD5_SIGNATURE_SIZE);
*nr_out_len += sprintf(nr_out_ptr + *nr_out_len, "CHAP_R=0x%s", *nr_out_len += sprintf(nr_out_ptr + *nr_out_len, "CHAP_R=0x%s",
response); response);
*nr_out_len += 1; *nr_out_len += 1;
......
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