Blob Blame History Raw
From 7627b7136546892ed803c6f41153d0674c05fc1f Mon Sep 17 00:00:00 2001
From: Joe Lawrence <joe.lawrence@redhat.com>
Date: Fri, 26 Mar 2021 13:24:17 -0400
Subject: [PATCH] scsi: iscsi: kpatch fixes for CVE-2021-27364 and
 CVE-2021-27365

Notes: backport CVE-2021-27363 to simplify patchset
       see [JL] notes in commit msgs below correcting CVE numbers

Kernels:
3.10.0-1160.el7
3.10.0-1160.2.1.el7
3.10.0-1160.2.2.el7
3.10.0-1160.6.1.el7
3.10.0-1160.11.1.el7
3.10.0-1160.15.2.el7
3.10.0-1160.21.1.el7

Changes since last build:
arches: x86_64 ppc64le
libiscsi.o: changed function: iscsi_conn_get_addr_param
libiscsi.o: changed function: iscsi_conn_get_param
libiscsi.o: changed function: iscsi_host_get_param
libiscsi.o: changed function: iscsi_session_get_param
scsi_transport_iscsi.o: changed function: iscsi_if_recv_msg
scsi_transport_iscsi.o: changed function: show_ep_handle
scsi_transport_iscsi.o: changed function: show_priv_session_creator
scsi_transport_iscsi.o: changed function: show_priv_session_recovery_tmo
scsi_transport_iscsi.o: changed function: show_priv_session_state
scsi_transport_iscsi.o: changed function: show_priv_session_target_id
scsi_transport_iscsi.o: changed function: show_transport_caps
scsi_transport_iscsi.o: changed function: show_transport_handle
---------------------------

Modifications: none

commit b307f0f6090743a904454f6ecc54d290ca18a693
Author: Chris Leech <cleech@redhat.com>
Date:   Thu Mar 4 09:55:32 2021 -0800

    scsi: iscsi: Restrict sessions and handles to admin capabilities

    Bugzilla: http://bugzilla.redhat.com/1930807
    CVE: CVE-2021-27364		<< [JL] should be CVE-2021-27363

    commit 688e8128b7a92df982709a4137ea4588d16f24aa
    Author: Lee Duncan <lduncan@suse.com>
    Date:   Tue Feb 23 13:06:24 2021 -0800

        scsi: iscsi: Restrict sessions and handles to admin capabilities

        Protect the iSCSI transport handle, available in sysfs, by requiring
        CAP_SYS_ADMIN to read it. Also protect the netlink socket by restricting
        reception of messages to ones sent with CAP_SYS_ADMIN. This disables
        normal users from being able to end arbitrary iSCSI sessions.

        Cc: stable@vger.kernel.org
        Reported-by: Adam Nichols <adam@grimm-co.com>
        Reviewed-by: Chris Leech <cleech@redhat.com>
        Reviewed-by: Mike Christie <michael.christie@oracle.com>
        Signed-off-by: Lee Duncan <lduncan@suse.com>
        Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

    Signed-off-by: Chris Leech <cleech@redhat.com>

commit af581fe518f4d6a6f28064f932d9374e0444d706
Author: Chris Leech <cleech@redhat.com>
Date:   Thu Mar 4 09:57:23 2021 -0800

    scsi: iscsi: Ensure sysfs attributes are limited to PAGE_SIZE

    Bugzilla: http://bugzilla.redhat.com/1930849
    CVE: CVE-2021-27363		<< [JL] should be CVE-2021-27365

    Conflicts: The sysfs_emit helper doesn't exist for backports, but other
    than a sanity check on buf it's just a call to scnprintf with a
    PAGE_SIZE limit.
    converted with s/sysfs_emit(buf,/scnprintf(buf, PAGE_SIZE,/

    commit ec98ea7070e94cc25a422ec97d1421e28d97b7ee
    Author: Chris Leech <cleech@redhat.com>
    Date:   Tue Feb 23 18:00:17 2021 -0800

        scsi: iscsi: Ensure sysfs attributes are limited to PAGE_SIZE

        As the iSCSI parameters are exported back through sysfs, it should be
        enforcing that they never are more than PAGE_SIZE (which should be more
        than enough) before accepting updates through netlink.

        Change all iSCSI sysfs attributes to use sysfs_emit().

        Cc: stable@vger.kernel.org
        Reported-by: Adam Nichols <adam@grimm-co.com>
        Reviewed-by: Lee Duncan <lduncan@suse.com>
        Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
        Reviewed-by: Mike Christie <michael.christie@oracle.com>
        Signed-off-by: Chris Leech <cleech@redhat.com>
        Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

    Signed-off-by: Chris Leech <cleech@redhat.com>

commit 8026ca13e283db6175377fccf309e8c5239033be
Author: Chris Leech <cleech@redhat.com>
Date:   Thu Mar 4 09:58:33 2021 -0800

    scsi: iscsi: Verify lengths on passthrough PDUs

    Bugzilla: http://bugzilla.redhat.com/1930826
    CVE: CVE-2021-27365		<< [JL] should be CVE-2021-27364

    commit f9dbdf97a5bd92b1a49cee3d591b55b11fd7a6d5
    Author: Chris Leech <cleech@redhat.com>
    Date:   Tue Feb 23 21:39:01 2021 -0800

        scsi: iscsi: Verify lengths on passthrough PDUs

        Open-iSCSI sends passthrough PDUs over netlink, but the kernel should be
        verifying that the provided PDU header and data lengths fall within the
        netlink message to prevent accessing beyond that in memory.

        Cc: stable@vger.kernel.org
        Reported-by: Adam Nichols <adam@grimm-co.com>
        Reviewed-by: Lee Duncan <lduncan@suse.com>
        Reviewed-by: Mike Christie <michael.christie@oracle.com>
        Signed-off-by: Chris Leech <cleech@redhat.com>
        Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

    Signed-off-by: Chris Leech <cleech@redhat.com>

Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
Acked-by: Artem Savkov <asavkov@redhat.com>
---
 drivers/scsi/libiscsi.c             | 148 ++++++++++++++--------------
 drivers/scsi/scsi_transport_iscsi.c |  38 +++++--
 2 files changed, 104 insertions(+), 82 deletions(-)

diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index bd36ead89f9d..5530662bd9ed 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -3323,125 +3323,125 @@ int iscsi_session_get_param(struct iscsi_cls_session *cls_session,
 
 	switch(param) {
 	case ISCSI_PARAM_FAST_ABORT:
-		len = sprintf(buf, "%d\n", session->fast_abort);
+		len = scnprintf(buf, PAGE_SIZE, "%d\n", session->fast_abort);
 		break;
 	case ISCSI_PARAM_ABORT_TMO:
-		len = sprintf(buf, "%d\n", session->abort_timeout);
+		len = scnprintf(buf, PAGE_SIZE, "%d\n", session->abort_timeout);
 		break;
 	case ISCSI_PARAM_LU_RESET_TMO:
-		len = sprintf(buf, "%d\n", session->lu_reset_timeout);
+		len = scnprintf(buf, PAGE_SIZE, "%d\n", session->lu_reset_timeout);
 		break;
 	case ISCSI_PARAM_TGT_RESET_TMO:
-		len = sprintf(buf, "%d\n", session->tgt_reset_timeout);
+		len = scnprintf(buf, PAGE_SIZE, "%d\n", session->tgt_reset_timeout);
 		break;
 	case ISCSI_PARAM_INITIAL_R2T_EN:
-		len = sprintf(buf, "%d\n", session->initial_r2t_en);
+		len = scnprintf(buf, PAGE_SIZE, "%d\n", session->initial_r2t_en);
 		break;
 	case ISCSI_PARAM_MAX_R2T:
-		len = sprintf(buf, "%hu\n", session->max_r2t);
+		len = scnprintf(buf, PAGE_SIZE, "%hu\n", session->max_r2t);
 		break;
 	case ISCSI_PARAM_IMM_DATA_EN:
-		len = sprintf(buf, "%d\n", session->imm_data_en);
+		len = scnprintf(buf, PAGE_SIZE, "%d\n", session->imm_data_en);
 		break;
 	case ISCSI_PARAM_FIRST_BURST:
-		len = sprintf(buf, "%u\n", session->first_burst);
+		len = scnprintf(buf, PAGE_SIZE, "%u\n", session->first_burst);
 		break;
 	case ISCSI_PARAM_MAX_BURST:
-		len = sprintf(buf, "%u\n", session->max_burst);
+		len = scnprintf(buf, PAGE_SIZE, "%u\n", session->max_burst);
 		break;
 	case ISCSI_PARAM_PDU_INORDER_EN:
-		len = sprintf(buf, "%d\n", session->pdu_inorder_en);
+		len = scnprintf(buf, PAGE_SIZE, "%d\n", session->pdu_inorder_en);
 		break;
 	case ISCSI_PARAM_DATASEQ_INORDER_EN:
-		len = sprintf(buf, "%d\n", session->dataseq_inorder_en);
+		len = scnprintf(buf, PAGE_SIZE, "%d\n", session->dataseq_inorder_en);
 		break;
 	case ISCSI_PARAM_DEF_TASKMGMT_TMO:
-		len = sprintf(buf, "%d\n", session->def_taskmgmt_tmo);
+		len = scnprintf(buf, PAGE_SIZE, "%d\n", session->def_taskmgmt_tmo);
 		break;
 	case ISCSI_PARAM_ERL:
-		len = sprintf(buf, "%d\n", session->erl);
+		len = scnprintf(buf, PAGE_SIZE, "%d\n", session->erl);
 		break;
 	case ISCSI_PARAM_TARGET_NAME:
-		len = sprintf(buf, "%s\n", session->targetname);
+		len = scnprintf(buf, PAGE_SIZE, "%s\n", session->targetname);
 		break;
 	case ISCSI_PARAM_TARGET_ALIAS:
-		len = sprintf(buf, "%s\n", session->targetalias);
+		len = scnprintf(buf, PAGE_SIZE, "%s\n", session->targetalias);
 		break;
 	case ISCSI_PARAM_TPGT:
-		len = sprintf(buf, "%d\n", session->tpgt);
+		len = scnprintf(buf, PAGE_SIZE, "%d\n", session->tpgt);
 		break;
 	case ISCSI_PARAM_USERNAME:
-		len = sprintf(buf, "%s\n", session->username);
+		len = scnprintf(buf, PAGE_SIZE, "%s\n", session->username);
 		break;
 	case ISCSI_PARAM_USERNAME_IN:
-		len = sprintf(buf, "%s\n", session->username_in);
+		len = scnprintf(buf, PAGE_SIZE, "%s\n", session->username_in);
 		break;
 	case ISCSI_PARAM_PASSWORD:
-		len = sprintf(buf, "%s\n", session->password);
+		len = scnprintf(buf, PAGE_SIZE, "%s\n", session->password);
 		break;
 	case ISCSI_PARAM_PASSWORD_IN:
-		len = sprintf(buf, "%s\n", session->password_in);
+		len = scnprintf(buf, PAGE_SIZE, "%s\n", session->password_in);
 		break;
 	case ISCSI_PARAM_IFACE_NAME:
-		len = sprintf(buf, "%s\n", session->ifacename);
+		len = scnprintf(buf, PAGE_SIZE, "%s\n", session->ifacename);
 		break;
 	case ISCSI_PARAM_INITIATOR_NAME:
-		len = sprintf(buf, "%s\n", session->initiatorname);
+		len = scnprintf(buf, PAGE_SIZE, "%s\n", session->initiatorname);
 		break;
 	case ISCSI_PARAM_BOOT_ROOT:
-		len = sprintf(buf, "%s\n", session->boot_root);
+		len = scnprintf(buf, PAGE_SIZE, "%s\n", session->boot_root);
 		break;
 	case ISCSI_PARAM_BOOT_NIC:
-		len = sprintf(buf, "%s\n", session->boot_nic);
+		len = scnprintf(buf, PAGE_SIZE, "%s\n", session->boot_nic);
 		break;
 	case ISCSI_PARAM_BOOT_TARGET:
-		len = sprintf(buf, "%s\n", session->boot_target);
+		len = scnprintf(buf, PAGE_SIZE, "%s\n", session->boot_target);
 		break;
 	case ISCSI_PARAM_AUTO_SND_TGT_DISABLE:
-		len = sprintf(buf, "%u\n", session->auto_snd_tgt_disable);
+		len = scnprintf(buf, PAGE_SIZE, "%u\n", session->auto_snd_tgt_disable);
 		break;
 	case ISCSI_PARAM_DISCOVERY_SESS:
-		len = sprintf(buf, "%u\n", session->discovery_sess);
+		len = scnprintf(buf, PAGE_SIZE, "%u\n", session->discovery_sess);
 		break;
 	case ISCSI_PARAM_PORTAL_TYPE:
-		len = sprintf(buf, "%s\n", session->portal_type);
+		len = scnprintf(buf, PAGE_SIZE, "%s\n", session->portal_type);
 		break;
 	case ISCSI_PARAM_CHAP_AUTH_EN:
-		len = sprintf(buf, "%u\n", session->chap_auth_en);
+		len = scnprintf(buf, PAGE_SIZE, "%u\n", session->chap_auth_en);
 		break;
 	case ISCSI_PARAM_DISCOVERY_LOGOUT_EN:
-		len = sprintf(buf, "%u\n", session->discovery_logout_en);
+		len = scnprintf(buf, PAGE_SIZE, "%u\n", session->discovery_logout_en);
 		break;
 	case ISCSI_PARAM_BIDI_CHAP_EN:
-		len = sprintf(buf, "%u\n", session->bidi_chap_en);
+		len = scnprintf(buf, PAGE_SIZE, "%u\n", session->bidi_chap_en);
 		break;
 	case ISCSI_PARAM_DISCOVERY_AUTH_OPTIONAL:
-		len = sprintf(buf, "%u\n", session->discovery_auth_optional);
+		len = scnprintf(buf, PAGE_SIZE, "%u\n", session->discovery_auth_optional);
 		break;
 	case ISCSI_PARAM_DEF_TIME2WAIT:
-		len = sprintf(buf, "%d\n", session->time2wait);
+		len = scnprintf(buf, PAGE_SIZE, "%d\n", session->time2wait);
 		break;
 	case ISCSI_PARAM_DEF_TIME2RETAIN:
-		len = sprintf(buf, "%d\n", session->time2retain);
+		len = scnprintf(buf, PAGE_SIZE, "%d\n", session->time2retain);
 		break;
 	case ISCSI_PARAM_TSID:
-		len = sprintf(buf, "%u\n", session->tsid);
+		len = scnprintf(buf, PAGE_SIZE, "%u\n", session->tsid);
 		break;
 	case ISCSI_PARAM_ISID:
-		len = sprintf(buf, "%02x%02x%02x%02x%02x%02x\n",
+		len = scnprintf(buf, PAGE_SIZE, "%02x%02x%02x%02x%02x%02x\n",
 			      session->isid[0], session->isid[1],
 			      session->isid[2], session->isid[3],
 			      session->isid[4], session->isid[5]);
 		break;
 	case ISCSI_PARAM_DISCOVERY_PARENT_IDX:
-		len = sprintf(buf, "%u\n", session->discovery_parent_idx);
+		len = scnprintf(buf, PAGE_SIZE, "%u\n", session->discovery_parent_idx);
 		break;
 	case ISCSI_PARAM_DISCOVERY_PARENT_TYPE:
 		if (session->discovery_parent_type)
-			len = sprintf(buf, "%s\n",
+			len = scnprintf(buf, PAGE_SIZE, "%s\n",
 				      session->discovery_parent_type);
 		else
-			len = sprintf(buf, "\n");
+			len = scnprintf(buf, PAGE_SIZE, "\n");
 		break;
 	default:
 		return -ENOSYS;
@@ -3473,16 +3473,16 @@ int iscsi_conn_get_addr_param(struct sockaddr_storage *addr,
 	case ISCSI_PARAM_CONN_ADDRESS:
 	case ISCSI_HOST_PARAM_IPADDRESS:
 		if (sin)
-			len = sprintf(buf, "%pI4\n", &sin->sin_addr.s_addr);
+			len = scnprintf(buf, PAGE_SIZE, "%pI4\n", &sin->sin_addr.s_addr);
 		else
-			len = sprintf(buf, "%pI6\n", &sin6->sin6_addr);
+			len = scnprintf(buf, PAGE_SIZE, "%pI6\n", &sin6->sin6_addr);
 		break;
 	case ISCSI_PARAM_CONN_PORT:
 	case ISCSI_PARAM_LOCAL_PORT:
 		if (sin)
-			len = sprintf(buf, "%hu\n", be16_to_cpu(sin->sin_port));
+			len = scnprintf(buf, PAGE_SIZE, "%hu\n", be16_to_cpu(sin->sin_port));
 		else
-			len = sprintf(buf, "%hu\n",
+			len = scnprintf(buf, PAGE_SIZE, "%hu\n",
 				      be16_to_cpu(sin6->sin6_port));
 		break;
 	default:
@@ -3501,88 +3501,88 @@ int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
 
 	switch(param) {
 	case ISCSI_PARAM_PING_TMO:
-		len = sprintf(buf, "%u\n", conn->ping_timeout);
+		len = scnprintf(buf, PAGE_SIZE, "%u\n", conn->ping_timeout);
 		break;
 	case ISCSI_PARAM_RECV_TMO:
-		len = sprintf(buf, "%u\n", conn->recv_timeout);
+		len = scnprintf(buf, PAGE_SIZE, "%u\n", conn->recv_timeout);
 		break;
 	case ISCSI_PARAM_MAX_RECV_DLENGTH:
-		len = sprintf(buf, "%u\n", conn->max_recv_dlength);
+		len = scnprintf(buf, PAGE_SIZE, "%u\n", conn->max_recv_dlength);
 		break;
 	case ISCSI_PARAM_MAX_XMIT_DLENGTH:
-		len = sprintf(buf, "%u\n", conn->max_xmit_dlength);
+		len = scnprintf(buf, PAGE_SIZE, "%u\n", conn->max_xmit_dlength);
 		break;
 	case ISCSI_PARAM_HDRDGST_EN:
-		len = sprintf(buf, "%d\n", conn->hdrdgst_en);
+		len = scnprintf(buf, PAGE_SIZE, "%d\n", conn->hdrdgst_en);
 		break;
 	case ISCSI_PARAM_DATADGST_EN:
-		len = sprintf(buf, "%d\n", conn->datadgst_en);
+		len = scnprintf(buf, PAGE_SIZE, "%d\n", conn->datadgst_en);
 		break;
 	case ISCSI_PARAM_IFMARKER_EN:
-		len = sprintf(buf, "%d\n", conn->ifmarker_en);
+		len = scnprintf(buf, PAGE_SIZE, "%d\n", conn->ifmarker_en);
 		break;
 	case ISCSI_PARAM_OFMARKER_EN:
-		len = sprintf(buf, "%d\n", conn->ofmarker_en);
+		len = scnprintf(buf, PAGE_SIZE, "%d\n", conn->ofmarker_en);
 		break;
 	case ISCSI_PARAM_EXP_STATSN:
-		len = sprintf(buf, "%u\n", conn->exp_statsn);
+		len = scnprintf(buf, PAGE_SIZE, "%u\n", conn->exp_statsn);
 		break;
 	case ISCSI_PARAM_PERSISTENT_PORT:
-		len = sprintf(buf, "%d\n", conn->persistent_port);
+		len = scnprintf(buf, PAGE_SIZE, "%d\n", conn->persistent_port);
 		break;
 	case ISCSI_PARAM_PERSISTENT_ADDRESS:
-		len = sprintf(buf, "%s\n", conn->persistent_address);
+		len = scnprintf(buf, PAGE_SIZE, "%s\n", conn->persistent_address);
 		break;
 	case ISCSI_PARAM_STATSN:
-		len = sprintf(buf, "%u\n", conn->statsn);
+		len = scnprintf(buf, PAGE_SIZE, "%u\n", conn->statsn);
 		break;
 	case ISCSI_PARAM_MAX_SEGMENT_SIZE:
-		len = sprintf(buf, "%u\n", conn->max_segment_size);
+		len = scnprintf(buf, PAGE_SIZE, "%u\n", conn->max_segment_size);
 		break;
 	case ISCSI_PARAM_KEEPALIVE_TMO:
-		len = sprintf(buf, "%u\n", conn->keepalive_tmo);
+		len = scnprintf(buf, PAGE_SIZE, "%u\n", conn->keepalive_tmo);
 		break;
 	case ISCSI_PARAM_LOCAL_PORT:
-		len = sprintf(buf, "%u\n", conn->local_port);
+		len = scnprintf(buf, PAGE_SIZE, "%u\n", conn->local_port);
 		break;
 	case ISCSI_PARAM_TCP_TIMESTAMP_STAT:
-		len = sprintf(buf, "%u\n", conn->tcp_timestamp_stat);
+		len = scnprintf(buf, PAGE_SIZE, "%u\n", conn->tcp_timestamp_stat);
 		break;
 	case ISCSI_PARAM_TCP_NAGLE_DISABLE:
-		len = sprintf(buf, "%u\n", conn->tcp_nagle_disable);
+		len = scnprintf(buf, PAGE_SIZE, "%u\n", conn->tcp_nagle_disable);
 		break;
 	case ISCSI_PARAM_TCP_WSF_DISABLE:
-		len = sprintf(buf, "%u\n", conn->tcp_wsf_disable);
+		len = scnprintf(buf, PAGE_SIZE, "%u\n", conn->tcp_wsf_disable);
 		break;
 	case ISCSI_PARAM_TCP_TIMER_SCALE:
-		len = sprintf(buf, "%u\n", conn->tcp_timer_scale);
+		len = scnprintf(buf, PAGE_SIZE, "%u\n", conn->tcp_timer_scale);
 		break;
 	case ISCSI_PARAM_TCP_TIMESTAMP_EN:
-		len = sprintf(buf, "%u\n", conn->tcp_timestamp_en);
+		len = scnprintf(buf, PAGE_SIZE, "%u\n", conn->tcp_timestamp_en);
 		break;
 	case ISCSI_PARAM_IP_FRAGMENT_DISABLE:
-		len = sprintf(buf, "%u\n", conn->fragment_disable);
+		len = scnprintf(buf, PAGE_SIZE, "%u\n", conn->fragment_disable);
 		break;
 	case ISCSI_PARAM_IPV4_TOS:
-		len = sprintf(buf, "%u\n", conn->ipv4_tos);
+		len = scnprintf(buf, PAGE_SIZE, "%u\n", conn->ipv4_tos);
 		break;
 	case ISCSI_PARAM_IPV6_TC:
-		len = sprintf(buf, "%u\n", conn->ipv6_traffic_class);
+		len = scnprintf(buf, PAGE_SIZE, "%u\n", conn->ipv6_traffic_class);
 		break;
 	case ISCSI_PARAM_IPV6_FLOW_LABEL:
-		len = sprintf(buf, "%u\n", conn->ipv6_flow_label);
+		len = scnprintf(buf, PAGE_SIZE, "%u\n", conn->ipv6_flow_label);
 		break;
 	case ISCSI_PARAM_IS_FW_ASSIGNED_IPV6:
-		len = sprintf(buf, "%u\n", conn->is_fw_assigned_ipv6);
+		len = scnprintf(buf, PAGE_SIZE, "%u\n", conn->is_fw_assigned_ipv6);
 		break;
 	case ISCSI_PARAM_TCP_XMIT_WSF:
-		len = sprintf(buf, "%u\n", conn->tcp_xmit_wsf);
+		len = scnprintf(buf, PAGE_SIZE, "%u\n", conn->tcp_xmit_wsf);
 		break;
 	case ISCSI_PARAM_TCP_RECV_WSF:
-		len = sprintf(buf, "%u\n", conn->tcp_recv_wsf);
+		len = scnprintf(buf, PAGE_SIZE, "%u\n", conn->tcp_recv_wsf);
 		break;
 	case ISCSI_PARAM_LOCAL_IPADDR:
-		len = sprintf(buf, "%s\n", conn->local_ipaddr);
+		len = scnprintf(buf, PAGE_SIZE, "%s\n", conn->local_ipaddr);
 		break;
 	default:
 		return -ENOSYS;
@@ -3600,13 +3600,13 @@ int iscsi_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param,
 
 	switch (param) {
 	case ISCSI_HOST_PARAM_NETDEV_NAME:
-		len = sprintf(buf, "%s\n", ihost->netdev);
+		len = scnprintf(buf, PAGE_SIZE, "%s\n", ihost->netdev);
 		break;
 	case ISCSI_HOST_PARAM_HWADDRESS:
-		len = sprintf(buf, "%s\n", ihost->hwaddress);
+		len = scnprintf(buf, PAGE_SIZE, "%s\n", ihost->hwaddress);
 		break;
 	case ISCSI_HOST_PARAM_INITIATOR_NAME:
-		len = sprintf(buf, "%s\n", ihost->initiatorname);
+		len = scnprintf(buf, PAGE_SIZE, "%s\n", ihost->initiatorname);
 		break;
 	default:
 		return -ENOSYS;
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 2265611b7e37..f0738bb165f2 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -119,7 +119,11 @@ show_transport_handle(struct device *dev, struct device_attribute *attr,
 		      char *buf)
 {
 	struct iscsi_internal *priv = dev_to_iscsi_internal(dev);
-	return sprintf(buf, "%llu\n", (unsigned long long)iscsi_handle(priv->iscsi_transport));
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+	return scnprintf(buf, PAGE_SIZE, "%llu\n",
+		  (unsigned long long)iscsi_handle(priv->iscsi_transport));
 }
 static DEVICE_ATTR(handle, S_IRUGO, show_transport_handle, NULL);
 
@@ -129,7 +133,7 @@ show_transport_##name(struct device *dev, 				\
 		      struct device_attribute *attr,char *buf)		\
 {									\
 	struct iscsi_internal *priv = dev_to_iscsi_internal(dev);	\
-	return sprintf(buf, format"\n", priv->iscsi_transport->name);	\
+	return scnprintf(buf, PAGE_SIZE, format"\n", priv->iscsi_transport->name);\
 }									\
 static DEVICE_ATTR(name, S_IRUGO, show_transport_##name, NULL);
 
@@ -170,7 +174,7 @@ static ssize_t
 show_ep_handle(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
-	return sprintf(buf, "%llu\n", (unsigned long long) ep->id);
+	return scnprintf(buf, PAGE_SIZE, "%llu\n", (unsigned long long) ep->id);
 }
 static ISCSI_ATTR(ep, handle, S_IRUGO, show_ep_handle, NULL);
 
@@ -2779,6 +2783,9 @@ iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev)
 	struct iscsi_cls_session *session;
 	int err = 0, value = 0;
 
+	if (ev->u.set_param.len > PAGE_SIZE)
+		return -EINVAL;
+
 	session = iscsi_session_lookup(ev->u.set_param.sid);
 	conn = iscsi_conn_lookup(ev->u.set_param.sid, ev->u.set_param.cid);
 	if (!conn || !session)
@@ -2926,6 +2933,9 @@ iscsi_set_host_param(struct iscsi_transport *transport,
 	if (!transport->set_host_param)
 		return -ENOSYS;
 
+	if (ev->u.set_host_param.len > PAGE_SIZE)
+		return -EINVAL;
+
 	shost = scsi_host_lookup(ev->u.set_host_param.host_no);
 	if (!shost) {
 		printk(KERN_ERR "set_host_param could not find host no %u\n",
@@ -3495,6 +3505,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
 {
 	int err = 0;
 	u32 portid;
+	u32 pdu_len;
 	struct iscsi_uevent *ev = nlmsg_data(nlh);
 	struct iscsi_transport *transport = NULL;
 	struct iscsi_internal *priv;
@@ -3502,6 +3513,9 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
 	struct iscsi_cls_conn *conn;
 	struct iscsi_endpoint *ep = NULL;
 
+	if (!netlink_capable(skb, CAP_SYS_ADMIN))
+		return -EPERM;
+
 	if (nlh->nlmsg_type == ISCSI_UEVENT_PATH_UPDATE)
 		*group = ISCSI_NL_GRP_UIP;
 	else
@@ -3607,6 +3621,14 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
 			err = -EINVAL;
 		break;
 	case ISCSI_UEVENT_SEND_PDU:
+		pdu_len = nlh->nlmsg_len - sizeof(*nlh) - sizeof(*ev);
+
+		if ((ev->u.send_pdu.hdr_size > pdu_len) ||
+		    (ev->u.send_pdu.data_size > (pdu_len - ev->u.send_pdu.hdr_size))) {
+			err = -EINVAL;
+			break;
+		}
+
 		conn = iscsi_conn_lookup(ev->u.send_pdu.sid, ev->u.send_pdu.cid);
 		if (conn)
 			ev->r.retcode =	transport->send_pdu(conn,
@@ -4013,7 +4035,7 @@ show_priv_session_state(struct device *dev, struct device_attribute *attr,
 			char *buf)
 {
 	struct iscsi_cls_session *session = iscsi_dev_to_session(dev->parent);
-	return sprintf(buf, "%s\n", iscsi_session_state_name(session->state));
+	return scnprintf(buf, PAGE_SIZE, "%s\n", iscsi_session_state_name(session->state));
 }
 static ISCSI_CLASS_ATTR(priv_sess, state, S_IRUGO, show_priv_session_state,
 			NULL);
@@ -4022,7 +4044,7 @@ show_priv_session_creator(struct device *dev, struct device_attribute *attr,
 			char *buf)
 {
 	struct iscsi_cls_session *session = iscsi_dev_to_session(dev->parent);
-	return sprintf(buf, "%d\n", session->creator);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", session->creator);
 }
 static ISCSI_CLASS_ATTR(priv_sess, creator, S_IRUGO, show_priv_session_creator,
 			NULL);
@@ -4031,7 +4053,7 @@ show_priv_session_target_id(struct device *dev, struct device_attribute *attr,
 			    char *buf)
 {
 	struct iscsi_cls_session *session = iscsi_dev_to_session(dev->parent);
-	return sprintf(buf, "%d\n", session->target_id);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", session->target_id);
 }
 static ISCSI_CLASS_ATTR(priv_sess, target_id, S_IRUGO,
 			show_priv_session_target_id, NULL);
@@ -4044,8 +4066,8 @@ show_priv_session_##field(struct device *dev, 				\
 	struct iscsi_cls_session *session = 				\
 			iscsi_dev_to_session(dev->parent);		\
 	if (session->field == -1)					\
-		return sprintf(buf, "off\n");				\
-	return sprintf(buf, format"\n", session->field);		\
+		return scnprintf(buf, PAGE_SIZE, "off\n");			\
+	return scnprintf(buf, PAGE_SIZE, format"\n", session->field);		\
 }
 
 #define iscsi_priv_session_attr_store(field)				\
-- 
2.26.2