Commit 02db81a7 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull SCSI fixes from James Bottomley:
 "Six fixes, all in drivers.

  The biggest are the UFS devfreq fixes which address a lock inversion
  and the two iscsi_tcp fixes which try to prevent a use after free from
  userspace still accessing an area which the kernel has released (seen
  by KASAN)"

* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
  scsi: device_handler: alua: Remove a might_sleep() annotation
  scsi: iscsi_tcp: Fix UAF during login when accessing the shost ipaddress
  scsi: iscsi_tcp: Fix UAF during logout when accessing the shost ipaddress
  scsi: ufs: core: Fix devfreq deadlocks
  scsi: hpsa: Fix allocation size for scsi_host_alloc()
  scsi: target: core: Fix warning on RT kernels
parents fb6e71db 0bfe63d0
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -981,6 +981,9 @@ static void alua_rtpg_work(struct work_struct *work)
 *
 * Returns true if and only if alua_rtpg_work() will be called asynchronously.
 * That function is responsible for calling @qdata->fn().
 *
 * Context: may be called from atomic context (alua_check()) only if the caller
 *	holds an sdev reference.
 */
static bool alua_rtpg_queue(struct alua_port_group *pg,
			    struct scsi_device *sdev,
@@ -989,8 +992,6 @@ static bool alua_rtpg_queue(struct alua_port_group *pg,
	int start_queue = 0;
	unsigned long flags;

	might_sleep();

	if (WARN_ON_ONCE(!pg) || scsi_device_get(sdev))
		return false;

+1 −1
Original line number Diff line number Diff line
@@ -5850,7 +5850,7 @@ static int hpsa_scsi_host_alloc(struct ctlr_info *h)
{
	struct Scsi_Host *sh;

	sh = scsi_host_alloc(&hpsa_driver_template, sizeof(h));
	sh = scsi_host_alloc(&hpsa_driver_template, sizeof(struct ctlr_info));
	if (sh == NULL) {
		dev_err(&h->pdev->dev, "scsi_host_alloc failed\n");
		return -ENOMEM;
+15 −5
Original line number Diff line number Diff line
@@ -849,7 +849,7 @@ static int iscsi_sw_tcp_host_get_param(struct Scsi_Host *shost,
				       enum iscsi_host_param param, char *buf)
{
	struct iscsi_sw_tcp_host *tcp_sw_host = iscsi_host_priv(shost);
	struct iscsi_session *session = tcp_sw_host->session;
	struct iscsi_session *session;
	struct iscsi_conn *conn;
	struct iscsi_tcp_conn *tcp_conn;
	struct iscsi_sw_tcp_conn *tcp_sw_conn;
@@ -859,6 +859,7 @@ static int iscsi_sw_tcp_host_get_param(struct Scsi_Host *shost,

	switch (param) {
	case ISCSI_HOST_PARAM_IPADDRESS:
		session = tcp_sw_host->session;
		if (!session)
			return -ENOTCONN;

@@ -959,11 +960,13 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
	if (!cls_session)
		goto remove_host;
	session = cls_session->dd_data;
	tcp_sw_host = iscsi_host_priv(shost);
	tcp_sw_host->session = session;

	if (iscsi_tcp_r2tpool_alloc(session))
		goto remove_session;

	/* We are now fully setup so expose the session to sysfs. */
	tcp_sw_host = iscsi_host_priv(shost);
	tcp_sw_host->session = session;
	return cls_session;

remove_session:
@@ -983,10 +986,17 @@ static void iscsi_sw_tcp_session_destroy(struct iscsi_cls_session *cls_session)
	if (WARN_ON_ONCE(session->leadconn))
		return;

	iscsi_session_remove(cls_session);
	/*
	 * Our get_host_param needs to access the session, so remove the
	 * host from sysfs before freeing the session to make sure userspace
	 * is no longer accessing the callout.
	 */
	iscsi_host_remove(shost, false);

	iscsi_tcp_r2tpool_free(cls_session->dd_data);
	iscsi_session_teardown(cls_session);

	iscsi_host_remove(shost, false);
	iscsi_session_free(cls_session);
	iscsi_host_free(shost);
}

+31 −7
Original line number Diff line number Diff line
@@ -3104,17 +3104,32 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost,
}
EXPORT_SYMBOL_GPL(iscsi_session_setup);

/**
 * iscsi_session_teardown - destroy session, host, and cls_session
 * @cls_session: iscsi session
/*
 * issi_session_remove - Remove session from iSCSI class.
 */
void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
void iscsi_session_remove(struct iscsi_cls_session *cls_session)
{
	struct iscsi_session *session = cls_session->dd_data;
	struct module *owner = cls_session->transport->owner;
	struct Scsi_Host *shost = session->host;

	iscsi_remove_session(cls_session);
	/*
	 * host removal only has to wait for its children to be removed from
	 * sysfs, and iscsi_tcp needs to do iscsi_host_remove before freeing
	 * the session, so drop the session count here.
	 */
	iscsi_host_dec_session_cnt(shost);
}
EXPORT_SYMBOL_GPL(iscsi_session_remove);

/**
 * iscsi_session_free - Free iscsi session and it's resources
 * @cls_session: iscsi session
 */
void iscsi_session_free(struct iscsi_cls_session *cls_session)
{
	struct iscsi_session *session = cls_session->dd_data;
	struct module *owner = cls_session->transport->owner;

	iscsi_pool_free(&session->cmdpool);
	kfree(session->password);
@@ -3132,10 +3147,19 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
	kfree(session->discovery_parent_type);

	iscsi_free_session(cls_session);

	iscsi_host_dec_session_cnt(shost);
	module_put(owner);
}
EXPORT_SYMBOL_GPL(iscsi_session_free);

/**
 * iscsi_session_teardown - destroy session and cls_session
 * @cls_session: iscsi session
 */
void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
{
	iscsi_session_remove(cls_session);
	iscsi_session_free(cls_session);
}
EXPORT_SYMBOL_GPL(iscsi_session_teardown);

/**
+2 −2
Original line number Diff line number Diff line
@@ -73,8 +73,8 @@ static bool __target_check_io_state(struct se_cmd *se_cmd,
{
	struct se_session *sess = se_cmd->se_sess;

	assert_spin_locked(&sess->sess_cmd_lock);
	WARN_ON_ONCE(!irqs_disabled());
	lockdep_assert_held(&sess->sess_cmd_lock);

	/*
	 * If command already reached CMD_T_COMPLETE state within
	 * target_complete_cmd() or CMD_T_FABRIC_STOP due to shutdown,
Loading