Commit 44195bd7 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull iSCSI fixes from Martin Petersen:
 "Three fixes for missed iSCSI verification checks (and make the sysfs
  files use "sysfs_emit()" - that's what it is there for)"

* tag 'mkp-scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi:
  scsi: iscsi: Verify lengths on passthrough PDUs
  scsi: iscsi: Ensure sysfs attributes are limited to PAGE_SIZE
  scsi: iscsi: Restrict sessions and handles to admin capabilities
parents 3cb60ee6 f9dbdf97
Loading
Loading
Loading
Loading
+74 −74
Original line number Diff line number Diff line
@@ -3430,125 +3430,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 = sysfs_emit(buf, "%d\n", session->fast_abort);
		break;
	case ISCSI_PARAM_ABORT_TMO:
		len = sprintf(buf, "%d\n", session->abort_timeout);
		len = sysfs_emit(buf, "%d\n", session->abort_timeout);
		break;
	case ISCSI_PARAM_LU_RESET_TMO:
		len = sprintf(buf, "%d\n", session->lu_reset_timeout);
		len = sysfs_emit(buf, "%d\n", session->lu_reset_timeout);
		break;
	case ISCSI_PARAM_TGT_RESET_TMO:
		len = sprintf(buf, "%d\n", session->tgt_reset_timeout);
		len = sysfs_emit(buf, "%d\n", session->tgt_reset_timeout);
		break;
	case ISCSI_PARAM_INITIAL_R2T_EN:
		len = sprintf(buf, "%d\n", session->initial_r2t_en);
		len = sysfs_emit(buf, "%d\n", session->initial_r2t_en);
		break;
	case ISCSI_PARAM_MAX_R2T:
		len = sprintf(buf, "%hu\n", session->max_r2t);
		len = sysfs_emit(buf, "%hu\n", session->max_r2t);
		break;
	case ISCSI_PARAM_IMM_DATA_EN:
		len = sprintf(buf, "%d\n", session->imm_data_en);
		len = sysfs_emit(buf, "%d\n", session->imm_data_en);
		break;
	case ISCSI_PARAM_FIRST_BURST:
		len = sprintf(buf, "%u\n", session->first_burst);
		len = sysfs_emit(buf, "%u\n", session->first_burst);
		break;
	case ISCSI_PARAM_MAX_BURST:
		len = sprintf(buf, "%u\n", session->max_burst);
		len = sysfs_emit(buf, "%u\n", session->max_burst);
		break;
	case ISCSI_PARAM_PDU_INORDER_EN:
		len = sprintf(buf, "%d\n", session->pdu_inorder_en);
		len = sysfs_emit(buf, "%d\n", session->pdu_inorder_en);
		break;
	case ISCSI_PARAM_DATASEQ_INORDER_EN:
		len = sprintf(buf, "%d\n", session->dataseq_inorder_en);
		len = sysfs_emit(buf, "%d\n", session->dataseq_inorder_en);
		break;
	case ISCSI_PARAM_DEF_TASKMGMT_TMO:
		len = sprintf(buf, "%d\n", session->def_taskmgmt_tmo);
		len = sysfs_emit(buf, "%d\n", session->def_taskmgmt_tmo);
		break;
	case ISCSI_PARAM_ERL:
		len = sprintf(buf, "%d\n", session->erl);
		len = sysfs_emit(buf, "%d\n", session->erl);
		break;
	case ISCSI_PARAM_TARGET_NAME:
		len = sprintf(buf, "%s\n", session->targetname);
		len = sysfs_emit(buf, "%s\n", session->targetname);
		break;
	case ISCSI_PARAM_TARGET_ALIAS:
		len = sprintf(buf, "%s\n", session->targetalias);
		len = sysfs_emit(buf, "%s\n", session->targetalias);
		break;
	case ISCSI_PARAM_TPGT:
		len = sprintf(buf, "%d\n", session->tpgt);
		len = sysfs_emit(buf, "%d\n", session->tpgt);
		break;
	case ISCSI_PARAM_USERNAME:
		len = sprintf(buf, "%s\n", session->username);
		len = sysfs_emit(buf, "%s\n", session->username);
		break;
	case ISCSI_PARAM_USERNAME_IN:
		len = sprintf(buf, "%s\n", session->username_in);
		len = sysfs_emit(buf, "%s\n", session->username_in);
		break;
	case ISCSI_PARAM_PASSWORD:
		len = sprintf(buf, "%s\n", session->password);
		len = sysfs_emit(buf, "%s\n", session->password);
		break;
	case ISCSI_PARAM_PASSWORD_IN:
		len = sprintf(buf, "%s\n", session->password_in);
		len = sysfs_emit(buf, "%s\n", session->password_in);
		break;
	case ISCSI_PARAM_IFACE_NAME:
		len = sprintf(buf, "%s\n", session->ifacename);
		len = sysfs_emit(buf, "%s\n", session->ifacename);
		break;
	case ISCSI_PARAM_INITIATOR_NAME:
		len = sprintf(buf, "%s\n", session->initiatorname);
		len = sysfs_emit(buf, "%s\n", session->initiatorname);
		break;
	case ISCSI_PARAM_BOOT_ROOT:
		len = sprintf(buf, "%s\n", session->boot_root);
		len = sysfs_emit(buf, "%s\n", session->boot_root);
		break;
	case ISCSI_PARAM_BOOT_NIC:
		len = sprintf(buf, "%s\n", session->boot_nic);
		len = sysfs_emit(buf, "%s\n", session->boot_nic);
		break;
	case ISCSI_PARAM_BOOT_TARGET:
		len = sprintf(buf, "%s\n", session->boot_target);
		len = sysfs_emit(buf, "%s\n", session->boot_target);
		break;
	case ISCSI_PARAM_AUTO_SND_TGT_DISABLE:
		len = sprintf(buf, "%u\n", session->auto_snd_tgt_disable);
		len = sysfs_emit(buf, "%u\n", session->auto_snd_tgt_disable);
		break;
	case ISCSI_PARAM_DISCOVERY_SESS:
		len = sprintf(buf, "%u\n", session->discovery_sess);
		len = sysfs_emit(buf, "%u\n", session->discovery_sess);
		break;
	case ISCSI_PARAM_PORTAL_TYPE:
		len = sprintf(buf, "%s\n", session->portal_type);
		len = sysfs_emit(buf, "%s\n", session->portal_type);
		break;
	case ISCSI_PARAM_CHAP_AUTH_EN:
		len = sprintf(buf, "%u\n", session->chap_auth_en);
		len = sysfs_emit(buf, "%u\n", session->chap_auth_en);
		break;
	case ISCSI_PARAM_DISCOVERY_LOGOUT_EN:
		len = sprintf(buf, "%u\n", session->discovery_logout_en);
		len = sysfs_emit(buf, "%u\n", session->discovery_logout_en);
		break;
	case ISCSI_PARAM_BIDI_CHAP_EN:
		len = sprintf(buf, "%u\n", session->bidi_chap_en);
		len = sysfs_emit(buf, "%u\n", session->bidi_chap_en);
		break;
	case ISCSI_PARAM_DISCOVERY_AUTH_OPTIONAL:
		len = sprintf(buf, "%u\n", session->discovery_auth_optional);
		len = sysfs_emit(buf, "%u\n", session->discovery_auth_optional);
		break;
	case ISCSI_PARAM_DEF_TIME2WAIT:
		len = sprintf(buf, "%d\n", session->time2wait);
		len = sysfs_emit(buf, "%d\n", session->time2wait);
		break;
	case ISCSI_PARAM_DEF_TIME2RETAIN:
		len = sprintf(buf, "%d\n", session->time2retain);
		len = sysfs_emit(buf, "%d\n", session->time2retain);
		break;
	case ISCSI_PARAM_TSID:
		len = sprintf(buf, "%u\n", session->tsid);
		len = sysfs_emit(buf, "%u\n", session->tsid);
		break;
	case ISCSI_PARAM_ISID:
		len = sprintf(buf, "%02x%02x%02x%02x%02x%02x\n",
		len = sysfs_emit(buf, "%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 = sysfs_emit(buf, "%u\n", session->discovery_parent_idx);
		break;
	case ISCSI_PARAM_DISCOVERY_PARENT_TYPE:
		if (session->discovery_parent_type)
			len = sprintf(buf, "%s\n",
			len = sysfs_emit(buf, "%s\n",
				      session->discovery_parent_type);
		else
			len = sprintf(buf, "\n");
			len = sysfs_emit(buf, "\n");
		break;
	default:
		return -ENOSYS;
@@ -3580,16 +3580,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 = sysfs_emit(buf, "%pI4\n", &sin->sin_addr.s_addr);
		else
			len = sprintf(buf, "%pI6\n", &sin6->sin6_addr);
			len = sysfs_emit(buf, "%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 = sysfs_emit(buf, "%hu\n", be16_to_cpu(sin->sin_port));
		else
			len = sprintf(buf, "%hu\n",
			len = sysfs_emit(buf, "%hu\n",
				      be16_to_cpu(sin6->sin6_port));
		break;
	default:
@@ -3608,88 +3608,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 = sysfs_emit(buf, "%u\n", conn->ping_timeout);
		break;
	case ISCSI_PARAM_RECV_TMO:
		len = sprintf(buf, "%u\n", conn->recv_timeout);
		len = sysfs_emit(buf, "%u\n", conn->recv_timeout);
		break;
	case ISCSI_PARAM_MAX_RECV_DLENGTH:
		len = sprintf(buf, "%u\n", conn->max_recv_dlength);
		len = sysfs_emit(buf, "%u\n", conn->max_recv_dlength);
		break;
	case ISCSI_PARAM_MAX_XMIT_DLENGTH:
		len = sprintf(buf, "%u\n", conn->max_xmit_dlength);
		len = sysfs_emit(buf, "%u\n", conn->max_xmit_dlength);
		break;
	case ISCSI_PARAM_HDRDGST_EN:
		len = sprintf(buf, "%d\n", conn->hdrdgst_en);
		len = sysfs_emit(buf, "%d\n", conn->hdrdgst_en);
		break;
	case ISCSI_PARAM_DATADGST_EN:
		len = sprintf(buf, "%d\n", conn->datadgst_en);
		len = sysfs_emit(buf, "%d\n", conn->datadgst_en);
		break;
	case ISCSI_PARAM_IFMARKER_EN:
		len = sprintf(buf, "%d\n", conn->ifmarker_en);
		len = sysfs_emit(buf, "%d\n", conn->ifmarker_en);
		break;
	case ISCSI_PARAM_OFMARKER_EN:
		len = sprintf(buf, "%d\n", conn->ofmarker_en);
		len = sysfs_emit(buf, "%d\n", conn->ofmarker_en);
		break;
	case ISCSI_PARAM_EXP_STATSN:
		len = sprintf(buf, "%u\n", conn->exp_statsn);
		len = sysfs_emit(buf, "%u\n", conn->exp_statsn);
		break;
	case ISCSI_PARAM_PERSISTENT_PORT:
		len = sprintf(buf, "%d\n", conn->persistent_port);
		len = sysfs_emit(buf, "%d\n", conn->persistent_port);
		break;
	case ISCSI_PARAM_PERSISTENT_ADDRESS:
		len = sprintf(buf, "%s\n", conn->persistent_address);
		len = sysfs_emit(buf, "%s\n", conn->persistent_address);
		break;
	case ISCSI_PARAM_STATSN:
		len = sprintf(buf, "%u\n", conn->statsn);
		len = sysfs_emit(buf, "%u\n", conn->statsn);
		break;
	case ISCSI_PARAM_MAX_SEGMENT_SIZE:
		len = sprintf(buf, "%u\n", conn->max_segment_size);
		len = sysfs_emit(buf, "%u\n", conn->max_segment_size);
		break;
	case ISCSI_PARAM_KEEPALIVE_TMO:
		len = sprintf(buf, "%u\n", conn->keepalive_tmo);
		len = sysfs_emit(buf, "%u\n", conn->keepalive_tmo);
		break;
	case ISCSI_PARAM_LOCAL_PORT:
		len = sprintf(buf, "%u\n", conn->local_port);
		len = sysfs_emit(buf, "%u\n", conn->local_port);
		break;
	case ISCSI_PARAM_TCP_TIMESTAMP_STAT:
		len = sprintf(buf, "%u\n", conn->tcp_timestamp_stat);
		len = sysfs_emit(buf, "%u\n", conn->tcp_timestamp_stat);
		break;
	case ISCSI_PARAM_TCP_NAGLE_DISABLE:
		len = sprintf(buf, "%u\n", conn->tcp_nagle_disable);
		len = sysfs_emit(buf, "%u\n", conn->tcp_nagle_disable);
		break;
	case ISCSI_PARAM_TCP_WSF_DISABLE:
		len = sprintf(buf, "%u\n", conn->tcp_wsf_disable);
		len = sysfs_emit(buf, "%u\n", conn->tcp_wsf_disable);
		break;
	case ISCSI_PARAM_TCP_TIMER_SCALE:
		len = sprintf(buf, "%u\n", conn->tcp_timer_scale);
		len = sysfs_emit(buf, "%u\n", conn->tcp_timer_scale);
		break;
	case ISCSI_PARAM_TCP_TIMESTAMP_EN:
		len = sprintf(buf, "%u\n", conn->tcp_timestamp_en);
		len = sysfs_emit(buf, "%u\n", conn->tcp_timestamp_en);
		break;
	case ISCSI_PARAM_IP_FRAGMENT_DISABLE:
		len = sprintf(buf, "%u\n", conn->fragment_disable);
		len = sysfs_emit(buf, "%u\n", conn->fragment_disable);
		break;
	case ISCSI_PARAM_IPV4_TOS:
		len = sprintf(buf, "%u\n", conn->ipv4_tos);
		len = sysfs_emit(buf, "%u\n", conn->ipv4_tos);
		break;
	case ISCSI_PARAM_IPV6_TC:
		len = sprintf(buf, "%u\n", conn->ipv6_traffic_class);
		len = sysfs_emit(buf, "%u\n", conn->ipv6_traffic_class);
		break;
	case ISCSI_PARAM_IPV6_FLOW_LABEL:
		len = sprintf(buf, "%u\n", conn->ipv6_flow_label);
		len = sysfs_emit(buf, "%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 = sysfs_emit(buf, "%u\n", conn->is_fw_assigned_ipv6);
		break;
	case ISCSI_PARAM_TCP_XMIT_WSF:
		len = sprintf(buf, "%u\n", conn->tcp_xmit_wsf);
		len = sysfs_emit(buf, "%u\n", conn->tcp_xmit_wsf);
		break;
	case ISCSI_PARAM_TCP_RECV_WSF:
		len = sprintf(buf, "%u\n", conn->tcp_recv_wsf);
		len = sysfs_emit(buf, "%u\n", conn->tcp_recv_wsf);
		break;
	case ISCSI_PARAM_LOCAL_IPADDR:
		len = sprintf(buf, "%s\n", conn->local_ipaddr);
		len = sysfs_emit(buf, "%s\n", conn->local_ipaddr);
		break;
	default:
		return -ENOSYS;
@@ -3707,13 +3707,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 = sysfs_emit(buf, "%s\n", ihost->netdev);
		break;
	case ISCSI_HOST_PARAM_HWADDRESS:
		len = sprintf(buf, "%s\n", ihost->hwaddress);
		len = sysfs_emit(buf, "%s\n", ihost->hwaddress);
		break;
	case ISCSI_HOST_PARAM_INITIATOR_NAME:
		len = sprintf(buf, "%s\n", ihost->initiatorname);
		len = sysfs_emit(buf, "%s\n", ihost->initiatorname);
		break;
	default:
		return -ENOSYS;
+31 −9
Original line number Diff line number Diff line
@@ -132,7 +132,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 sysfs_emit(buf, "%llu\n",
		  (unsigned long long)iscsi_handle(priv->iscsi_transport));
}
static DEVICE_ATTR(handle, S_IRUGO, show_transport_handle, NULL);

@@ -142,7 +146,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 sysfs_emit(buf, format"\n", priv->iscsi_transport->name);\
}									\
static DEVICE_ATTR(name, S_IRUGO, show_transport_##name, NULL);

@@ -183,7 +187,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 sysfs_emit(buf, "%llu\n", (unsigned long long) ep->id);
}
static ISCSI_ATTR(ep, handle, S_IRUGO, show_ep_handle, NULL);

@@ -2880,6 +2884,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)
@@ -3027,6 +3034,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",
@@ -3614,6 +3624,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;
@@ -3621,6 +3632,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
@@ -3753,6 +3767,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) {
			mutex_lock(&conn_mutex);
@@ -3957,7 +3979,7 @@ static ssize_t show_conn_state(struct device *dev,
	    conn->state < ARRAY_SIZE(connection_state_names))
		state = connection_state_names[conn->state];

	return sprintf(buf, "%s\n", state);
	return sysfs_emit(buf, "%s\n", state);
}
static ISCSI_CLASS_ATTR(conn, state, S_IRUGO, show_conn_state,
			NULL);
@@ -4185,7 +4207,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 sysfs_emit(buf, "%s\n", iscsi_session_state_name(session->state));
}
static ISCSI_CLASS_ATTR(priv_sess, state, S_IRUGO, show_priv_session_state,
			NULL);
@@ -4194,7 +4216,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 sysfs_emit(buf, "%d\n", session->creator);
}
static ISCSI_CLASS_ATTR(priv_sess, creator, S_IRUGO, show_priv_session_creator,
			NULL);
@@ -4203,7 +4225,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 sysfs_emit(buf, "%d\n", session->target_id);
}
static ISCSI_CLASS_ATTR(priv_sess, target_id, S_IRUGO,
			show_priv_session_target_id, NULL);
@@ -4216,8 +4238,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 sysfs_emit(buf, "off\n");			\
	return sysfs_emit(buf, format"\n", session->field);		\
}

#define iscsi_priv_session_attr_store(field)				\