Unverified Commit 743cd0c6 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!1467 Fix null-ptr-deref while calling getpeername

Merge Pull Request from: @ci-robot 
 
PR sync from: Zhong Jinghua <zhongjinghua@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/LJ33GFFSQF355SJLQXOUOLZRUVMBCUJ5/ 
Fix null-ptr-deref while calling getpeername

Mike Christie (1):
  scsi: iscsi: iscsi_tcp: Fix null-ptr-deref while calling getpeername()

Zhong Jinghua (1):
  scsi: iscsi_tcp: Check that sock is valid before iscsi_set_param()


-- 
2.31.1
 
https://gitee.com/openeuler/kernel/issues/I7L8DZ?from=project-issue
https://gitee.com/openeuler/kernel/issues/I6I8YD 
 
Link:https://gitee.com/openeuler/kernel/pulls/1467

 

Reviewed-by: default avatarYu Kuai <yukuai3@huawei.com>
Reviewed-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
Signed-off-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
parents d8b6a2cb af5834c5
Loading
Loading
Loading
Loading
+51 −21
Original line number Diff line number Diff line
@@ -566,6 +566,8 @@ iscsi_sw_tcp_conn_create(struct iscsi_cls_session *cls_session,
	tcp_conn = conn->dd_data;
	tcp_sw_conn = tcp_conn->dd_data;

	mutex_init(&tcp_sw_conn->sock_lock);

	tfm = crypto_alloc_ahash("crc32c", 0, CRYPTO_ALG_ASYNC);
	if (IS_ERR(tfm))
		goto free_conn;
@@ -600,11 +602,15 @@ iscsi_sw_tcp_conn_create(struct iscsi_cls_session *cls_session,

static void iscsi_sw_tcp_release_conn(struct iscsi_conn *conn)
{
	struct iscsi_session *session = conn->session;
	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
	struct socket *sock = tcp_sw_conn->sock;

	/*
	 * The iscsi transport class will make sure we are not called in
	 * parallel with start, stop, bind and destroys. However, this can be
	 * called twice if userspace does a stop then a destroy.
	 */
	if (!sock)
		return;

@@ -612,9 +618,9 @@ static void iscsi_sw_tcp_release_conn(struct iscsi_conn *conn)
	iscsi_sw_tcp_conn_restore_callbacks(conn);
	sock_put(sock->sk);

	spin_lock_bh(&session->frwd_lock);
	mutex_lock(&tcp_sw_conn->sock_lock);
	tcp_sw_conn->sock = NULL;
	spin_unlock_bh(&session->frwd_lock);
	mutex_unlock(&tcp_sw_conn->sock_lock);
	sockfd_put(sock);
}

@@ -666,7 +672,6 @@ iscsi_sw_tcp_conn_bind(struct iscsi_cls_session *cls_session,
		       struct iscsi_cls_conn *cls_conn, uint64_t transport_eph,
		       int is_leading)
{
	struct iscsi_session *session = cls_session->dd_data;
	struct iscsi_conn *conn = cls_conn->dd_data;
	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
@@ -686,10 +691,10 @@ iscsi_sw_tcp_conn_bind(struct iscsi_cls_session *cls_session,
	if (err)
		goto free_socket;

	spin_lock_bh(&session->frwd_lock);
	mutex_lock(&tcp_sw_conn->sock_lock);
	/* bind iSCSI connection and socket */
	tcp_sw_conn->sock = sock;
	spin_unlock_bh(&session->frwd_lock);
	mutex_unlock(&tcp_sw_conn->sock_lock);

	/* setup Socket parameters */
	sk = sock->sk;
@@ -724,9 +729,15 @@ static int iscsi_sw_tcp_conn_set_param(struct iscsi_cls_conn *cls_conn,
		iscsi_set_param(cls_conn, param, buf, buflen);
		break;
	case ISCSI_PARAM_DATADGST_EN:
		mutex_lock(&tcp_sw_conn->sock_lock);
		if (!tcp_sw_conn->sock) {
			mutex_unlock(&tcp_sw_conn->sock_lock);
			return -ENOTCONN;
		}
		iscsi_set_param(cls_conn, param, buf, buflen);
		tcp_sw_conn->sendpage = conn->datadgst_en ?
			sock_no_sendpage : tcp_sw_conn->sock->ops->sendpage;
		mutex_unlock(&tcp_sw_conn->sock_lock);
		break;
	case ISCSI_PARAM_MAX_R2T:
		return iscsi_tcp_set_max_r2t(conn, buf);
@@ -741,8 +752,8 @@ static int iscsi_sw_tcp_conn_get_param(struct iscsi_cls_conn *cls_conn,
				       enum iscsi_param param, char *buf)
{
	struct iscsi_conn *conn = cls_conn->dd_data;
	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
	struct iscsi_sw_tcp_conn *tcp_sw_conn;
	struct iscsi_tcp_conn *tcp_conn;
	struct sockaddr_in6 addr;
	struct socket *sock;
	int rc;
@@ -752,21 +763,36 @@ static int iscsi_sw_tcp_conn_get_param(struct iscsi_cls_conn *cls_conn,
	case ISCSI_PARAM_CONN_ADDRESS:
	case ISCSI_PARAM_LOCAL_PORT:
		spin_lock_bh(&conn->session->frwd_lock);
		if (!tcp_sw_conn || !tcp_sw_conn->sock) {
		if (!conn->session->leadconn) {
			spin_unlock_bh(&conn->session->frwd_lock);
			return -ENOTCONN;
		}
		sock = tcp_sw_conn->sock;
		sock_hold(sock->sk);
		/*
		 * The conn has been setup and bound, so just grab a ref
		 * incase a destroy runs while we are in the net layer.
		 */
		iscsi_get_conn(conn->cls_conn);
		spin_unlock_bh(&conn->session->frwd_lock);

		tcp_conn = conn->dd_data;
		tcp_sw_conn = tcp_conn->dd_data;

		mutex_lock(&tcp_sw_conn->sock_lock);
		sock = tcp_sw_conn->sock;
		if (!sock) {
			rc = -ENOTCONN;
			goto sock_unlock;
		}

		if (param == ISCSI_PARAM_LOCAL_PORT)
			rc = kernel_getsockname(sock,
						(struct sockaddr *)&addr);
		else
			rc = kernel_getpeername(sock,
						(struct sockaddr *)&addr);
		sock_put(sock->sk);
sock_unlock:
		mutex_unlock(&tcp_sw_conn->sock_lock);
		iscsi_put_conn(conn->cls_conn);
		if (rc < 0)
			return rc;

@@ -805,17 +831,21 @@ static int iscsi_sw_tcp_host_get_param(struct Scsi_Host *shost,
		}
		tcp_conn = conn->dd_data;
		tcp_sw_conn = tcp_conn->dd_data;
		sock = tcp_sw_conn->sock;
		if (!sock) {
			spin_unlock_bh(&session->frwd_lock);
			return -ENOTCONN;
		}
		sock_hold(sock->sk);
		/*
		 * The conn has been setup and bound, so just grab a ref
		 * incase a destroy runs while we are in the net layer.
		 */
		iscsi_get_conn(conn->cls_conn);
		spin_unlock_bh(&session->frwd_lock);

		rc = kernel_getsockname(sock,
					(struct sockaddr *)&addr);
		sock_put(sock->sk);
		mutex_lock(&tcp_sw_conn->sock_lock);
		sock = tcp_sw_conn->sock;
		if (!sock)
			rc = -ENOTCONN;
		else
			rc = kernel_getsockname(sock, (struct sockaddr *)&addr);
		mutex_unlock(&tcp_sw_conn->sock_lock);
		iscsi_put_conn(conn->cls_conn);
		if (rc < 0)
			return rc;

+2 −0
Original line number Diff line number Diff line
@@ -28,6 +28,8 @@ struct iscsi_sw_tcp_send {

struct iscsi_sw_tcp_conn {
	struct socket		*sock;
	/* Taken when accessing the sock from the netlink/sysfs interface */
	struct mutex		sock_lock;

	struct iscsi_sw_tcp_send out;
	/* old values for socket callbacks */