hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/scsi/scsi_transport_iscsi.c
....@@ -1674,6 +1674,13 @@
16741674 return name;
16751675 }
16761676
1677
+static char *iscsi_session_target_state_name[] = {
1678
+ [ISCSI_SESSION_TARGET_UNBOUND] = "UNBOUND",
1679
+ [ISCSI_SESSION_TARGET_ALLOCATED] = "ALLOCATED",
1680
+ [ISCSI_SESSION_TARGET_SCANNED] = "SCANNED",
1681
+ [ISCSI_SESSION_TARGET_UNBINDING] = "UNBINDING",
1682
+};
1683
+
16771684 int iscsi_session_chkready(struct iscsi_cls_session *session)
16781685 {
16791686 unsigned long flags;
....@@ -1805,9 +1812,13 @@
18051812 if ((scan_data->channel == SCAN_WILD_CARD ||
18061813 scan_data->channel == 0) &&
18071814 (scan_data->id == SCAN_WILD_CARD ||
1808
- scan_data->id == id))
1815
+ scan_data->id == id)) {
18091816 scsi_scan_target(&session->dev, 0, id,
18101817 scan_data->lun, scan_data->rescan);
1818
+ spin_lock_irqsave(&session->lock, flags);
1819
+ session->target_state = ISCSI_SESSION_TARGET_SCANNED;
1820
+ spin_unlock_irqrestore(&session->lock, flags);
1821
+ }
18111822 }
18121823
18131824 user_scan_exit:
....@@ -1996,31 +2007,41 @@
19962007 struct iscsi_cls_host *ihost = shost->shost_data;
19972008 unsigned long flags;
19982009 unsigned int target_id;
2010
+ bool remove_target = true;
19992011
20002012 ISCSI_DBG_TRANS_SESSION(session, "Unbinding session\n");
20012013
20022014 /* Prevent new scans and make sure scanning is not in progress */
20032015 mutex_lock(&ihost->mutex);
20042016 spin_lock_irqsave(&session->lock, flags);
2005
- if (session->target_id == ISCSI_MAX_TARGET) {
2017
+ if (session->target_state == ISCSI_SESSION_TARGET_ALLOCATED) {
2018
+ remove_target = false;
2019
+ } else if (session->target_state != ISCSI_SESSION_TARGET_SCANNED) {
20062020 spin_unlock_irqrestore(&session->lock, flags);
20072021 mutex_unlock(&ihost->mutex);
2008
- goto unbind_session_exit;
2022
+ ISCSI_DBG_TRANS_SESSION(session,
2023
+ "Skipping target unbinding: Session is unbound/unbinding.\n");
2024
+ return;
20092025 }
20102026
2027
+ session->target_state = ISCSI_SESSION_TARGET_UNBINDING;
20112028 target_id = session->target_id;
20122029 session->target_id = ISCSI_MAX_TARGET;
20132030 spin_unlock_irqrestore(&session->lock, flags);
20142031 mutex_unlock(&ihost->mutex);
20152032
2016
- scsi_remove_target(&session->dev);
2033
+ if (remove_target)
2034
+ scsi_remove_target(&session->dev);
20172035
20182036 if (session->ida_used)
20192037 ida_simple_remove(&iscsi_sess_ida, target_id);
20202038
2021
-unbind_session_exit:
20222039 iscsi_session_event(session, ISCSI_KEVENT_UNBIND_SESSION);
20232040 ISCSI_DBG_TRANS_SESSION(session, "Completed target removal\n");
2041
+
2042
+ spin_lock_irqsave(&session->lock, flags);
2043
+ session->target_state = ISCSI_SESSION_TARGET_UNBOUND;
2044
+ spin_unlock_irqrestore(&session->lock, flags);
20242045 }
20252046
20262047 static void __iscsi_destroy_session(struct work_struct *work)
....@@ -2089,6 +2110,9 @@
20892110 session->ida_used = true;
20902111 } else
20912112 session->target_id = target_id;
2113
+ spin_lock_irqsave(&session->lock, flags);
2114
+ session->target_state = ISCSI_SESSION_TARGET_ALLOCATED;
2115
+ spin_unlock_irqrestore(&session->lock, flags);
20922116
20932117 dev_set_name(&session->dev, "session%u", session->sid);
20942118 err = device_add(&session->dev);
....@@ -2967,19 +2991,24 @@
29672991 }
29682992
29692993 static int
2970
-iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev)
2994
+iscsi_if_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev, u32 rlen)
29712995 {
29722996 char *data = (char*)ev + sizeof(*ev);
29732997 struct iscsi_cls_conn *conn;
29742998 struct iscsi_cls_session *session;
29752999 int err = 0, value = 0, state;
29763000
2977
- if (ev->u.set_param.len > PAGE_SIZE)
3001
+ if (ev->u.set_param.len > rlen ||
3002
+ ev->u.set_param.len > PAGE_SIZE)
29783003 return -EINVAL;
29793004
29803005 session = iscsi_session_lookup(ev->u.set_param.sid);
29813006 conn = iscsi_conn_lookup(ev->u.set_param.sid, ev->u.set_param.cid);
29823007 if (!conn || !session)
3008
+ return -EINVAL;
3009
+
3010
+ /* data will be regarded as NULL-ended string, do length check */
3011
+ if (strlen(data) > ev->u.set_param.len)
29833012 return -EINVAL;
29843013
29853014 switch (ev->u.set_param.param) {
....@@ -3071,7 +3100,7 @@
30713100
30723101 static int
30733102 iscsi_if_transport_ep(struct iscsi_transport *transport,
3074
- struct iscsi_uevent *ev, int msg_type)
3103
+ struct iscsi_uevent *ev, int msg_type, u32 rlen)
30753104 {
30763105 struct iscsi_endpoint *ep;
30773106 int rc = 0;
....@@ -3079,7 +3108,10 @@
30793108 switch (msg_type) {
30803109 case ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST:
30813110 case ISCSI_UEVENT_TRANSPORT_EP_CONNECT:
3082
- rc = iscsi_if_ep_connect(transport, ev, msg_type);
3111
+ if (rlen < sizeof(struct sockaddr))
3112
+ rc = -EINVAL;
3113
+ else
3114
+ rc = iscsi_if_ep_connect(transport, ev, msg_type);
30833115 break;
30843116 case ISCSI_UEVENT_TRANSPORT_EP_POLL:
30853117 if (!transport->ep_poll)
....@@ -3103,11 +3135,14 @@
31033135
31043136 static int
31053137 iscsi_tgt_dscvr(struct iscsi_transport *transport,
3106
- struct iscsi_uevent *ev)
3138
+ struct iscsi_uevent *ev, u32 rlen)
31073139 {
31083140 struct Scsi_Host *shost;
31093141 struct sockaddr *dst_addr;
31103142 int err;
3143
+
3144
+ if (rlen < sizeof(*dst_addr))
3145
+ return -EINVAL;
31113146
31123147 if (!transport->tgt_dscvr)
31133148 return -EINVAL;
....@@ -3129,7 +3164,7 @@
31293164
31303165 static int
31313166 iscsi_set_host_param(struct iscsi_transport *transport,
3132
- struct iscsi_uevent *ev)
3167
+ struct iscsi_uevent *ev, u32 rlen)
31333168 {
31343169 char *data = (char*)ev + sizeof(*ev);
31353170 struct Scsi_Host *shost;
....@@ -3138,7 +3173,8 @@
31383173 if (!transport->set_host_param)
31393174 return -ENOSYS;
31403175
3141
- if (ev->u.set_host_param.len > PAGE_SIZE)
3176
+ if (ev->u.set_host_param.len > rlen ||
3177
+ ev->u.set_host_param.len > PAGE_SIZE)
31423178 return -EINVAL;
31433179
31443180 shost = scsi_host_lookup(ev->u.set_host_param.host_no);
....@@ -3148,6 +3184,10 @@
31483184 return -ENODEV;
31493185 }
31503186
3187
+ /* see similar check in iscsi_if_set_param() */
3188
+ if (strlen(data) > ev->u.set_host_param.len)
3189
+ return -EINVAL;
3190
+
31513191 err = transport->set_host_param(shost, ev->u.set_host_param.param,
31523192 data, ev->u.set_host_param.len);
31533193 scsi_host_put(shost);
....@@ -3155,11 +3195,14 @@
31553195 }
31563196
31573197 static int
3158
-iscsi_set_path(struct iscsi_transport *transport, struct iscsi_uevent *ev)
3198
+iscsi_set_path(struct iscsi_transport *transport, struct iscsi_uevent *ev, u32 rlen)
31593199 {
31603200 struct Scsi_Host *shost;
31613201 struct iscsi_path *params;
31623202 int err;
3203
+
3204
+ if (rlen < sizeof(*params))
3205
+ return -EINVAL;
31633206
31643207 if (!transport->set_path)
31653208 return -ENOSYS;
....@@ -3220,11 +3263,14 @@
32203263 }
32213264
32223265 static int
3223
-iscsi_send_ping(struct iscsi_transport *transport, struct iscsi_uevent *ev)
3266
+iscsi_send_ping(struct iscsi_transport *transport, struct iscsi_uevent *ev, u32 rlen)
32243267 {
32253268 struct Scsi_Host *shost;
32263269 struct sockaddr *dst_addr;
32273270 int err;
3271
+
3272
+ if (rlen < sizeof(*dst_addr))
3273
+ return -EINVAL;
32283274
32293275 if (!transport->send_ping)
32303276 return -ENOSYS;
....@@ -3723,13 +3769,12 @@
37233769 }
37243770
37253771 static int iscsi_if_transport_conn(struct iscsi_transport *transport,
3726
- struct nlmsghdr *nlh)
3772
+ struct nlmsghdr *nlh, u32 pdu_len)
37273773 {
37283774 struct iscsi_uevent *ev = nlmsg_data(nlh);
37293775 struct iscsi_cls_session *session;
37303776 struct iscsi_cls_conn *conn = NULL;
37313777 struct iscsi_endpoint *ep;
3732
- uint32_t pdu_len;
37333778 int err = 0;
37343779
37353780 switch (nlh->nlmsg_type) {
....@@ -3809,8 +3854,6 @@
38093854
38103855 break;
38113856 case ISCSI_UEVENT_SEND_PDU:
3812
- pdu_len = nlh->nlmsg_len - sizeof(*nlh) - sizeof(*ev);
3813
-
38143857 if ((ev->u.send_pdu.hdr_size > pdu_len) ||
38153858 (ev->u.send_pdu.data_size > (pdu_len - ev->u.send_pdu.hdr_size))) {
38163859 err = -EINVAL;
....@@ -3840,6 +3883,7 @@
38403883 struct iscsi_internal *priv;
38413884 struct iscsi_cls_session *session;
38423885 struct iscsi_endpoint *ep = NULL;
3886
+ u32 rlen;
38433887
38443888 if (!netlink_capable(skb, CAP_SYS_ADMIN))
38453889 return -EPERM;
....@@ -3858,6 +3902,13 @@
38583902 return -EINVAL;
38593903
38603904 portid = NETLINK_CB(skb).portid;
3905
+
3906
+ /*
3907
+ * Even though the remaining payload may not be regarded as nlattr,
3908
+ * (like address or something else), calculate the remaining length
3909
+ * here to ease following length checks.
3910
+ */
3911
+ rlen = nlmsg_attrlen(nlh, sizeof(*ev));
38613912
38623913 switch (nlh->nlmsg_type) {
38633914 case ISCSI_UEVENT_CREATE_SESSION:
....@@ -3916,7 +3967,7 @@
39163967 err = -EINVAL;
39173968 break;
39183969 case ISCSI_UEVENT_SET_PARAM:
3919
- err = iscsi_set_param(transport, ev);
3970
+ err = iscsi_if_set_param(transport, ev, rlen);
39203971 break;
39213972 case ISCSI_UEVENT_CREATE_CONN:
39223973 case ISCSI_UEVENT_DESTROY_CONN:
....@@ -3924,7 +3975,7 @@
39243975 case ISCSI_UEVENT_START_CONN:
39253976 case ISCSI_UEVENT_BIND_CONN:
39263977 case ISCSI_UEVENT_SEND_PDU:
3927
- err = iscsi_if_transport_conn(transport, nlh);
3978
+ err = iscsi_if_transport_conn(transport, nlh, rlen);
39283979 break;
39293980 case ISCSI_UEVENT_GET_STATS:
39303981 err = iscsi_if_get_stats(transport, nlh);
....@@ -3933,23 +3984,22 @@
39333984 case ISCSI_UEVENT_TRANSPORT_EP_POLL:
39343985 case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
39353986 case ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST:
3936
- err = iscsi_if_transport_ep(transport, ev, nlh->nlmsg_type);
3987
+ err = iscsi_if_transport_ep(transport, ev, nlh->nlmsg_type, rlen);
39373988 break;
39383989 case ISCSI_UEVENT_TGT_DSCVR:
3939
- err = iscsi_tgt_dscvr(transport, ev);
3990
+ err = iscsi_tgt_dscvr(transport, ev, rlen);
39403991 break;
39413992 case ISCSI_UEVENT_SET_HOST_PARAM:
3942
- err = iscsi_set_host_param(transport, ev);
3993
+ err = iscsi_set_host_param(transport, ev, rlen);
39433994 break;
39443995 case ISCSI_UEVENT_PATH_UPDATE:
3945
- err = iscsi_set_path(transport, ev);
3996
+ err = iscsi_set_path(transport, ev, rlen);
39463997 break;
39473998 case ISCSI_UEVENT_SET_IFACE_PARAMS:
3948
- err = iscsi_set_iface_params(transport, ev,
3949
- nlmsg_attrlen(nlh, sizeof(*ev)));
3999
+ err = iscsi_set_iface_params(transport, ev, rlen);
39504000 break;
39514001 case ISCSI_UEVENT_PING:
3952
- err = iscsi_send_ping(transport, ev);
4002
+ err = iscsi_send_ping(transport, ev, rlen);
39534003 break;
39544004 case ISCSI_UEVENT_GET_CHAP:
39554005 err = iscsi_get_chap(transport, nlh);
....@@ -3958,13 +4008,10 @@
39584008 err = iscsi_delete_chap(transport, ev);
39594009 break;
39604010 case ISCSI_UEVENT_SET_FLASHNODE_PARAMS:
3961
- err = iscsi_set_flashnode_param(transport, ev,
3962
- nlmsg_attrlen(nlh,
3963
- sizeof(*ev)));
4011
+ err = iscsi_set_flashnode_param(transport, ev, rlen);
39644012 break;
39654013 case ISCSI_UEVENT_NEW_FLASHNODE:
3966
- err = iscsi_new_flashnode(transport, ev,
3967
- nlmsg_attrlen(nlh, sizeof(*ev)));
4014
+ err = iscsi_new_flashnode(transport, ev, rlen);
39684015 break;
39694016 case ISCSI_UEVENT_DEL_FLASHNODE:
39704017 err = iscsi_del_flashnode(transport, ev);
....@@ -3979,8 +4026,7 @@
39794026 err = iscsi_logout_flashnode_sid(transport, ev);
39804027 break;
39814028 case ISCSI_UEVENT_SET_CHAP:
3982
- err = iscsi_set_chap(transport, ev,
3983
- nlmsg_attrlen(nlh, sizeof(*ev)));
4029
+ err = iscsi_set_chap(transport, ev, rlen);
39844030 break;
39854031 case ISCSI_UEVENT_GET_HOST_STATS:
39864032 err = iscsi_get_host_stats(transport, nlh);
....@@ -4344,6 +4390,19 @@
43444390 iscsi_session_attr(discovery_parent_type, ISCSI_PARAM_DISCOVERY_PARENT_TYPE, 0);
43454391
43464392 static ssize_t
4393
+show_priv_session_target_state(struct device *dev, struct device_attribute *attr,
4394
+ char *buf)
4395
+{
4396
+ struct iscsi_cls_session *session = iscsi_dev_to_session(dev->parent);
4397
+
4398
+ return sysfs_emit(buf, "%s\n",
4399
+ iscsi_session_target_state_name[session->target_state]);
4400
+}
4401
+
4402
+static ISCSI_CLASS_ATTR(priv_sess, target_state, S_IRUGO,
4403
+ show_priv_session_target_state, NULL);
4404
+
4405
+static ssize_t
43474406 show_priv_session_state(struct device *dev, struct device_attribute *attr,
43484407 char *buf)
43494408 {
....@@ -4445,6 +4504,7 @@
44454504 &dev_attr_sess_boot_target.attr,
44464505 &dev_attr_priv_sess_recovery_tmo.attr,
44474506 &dev_attr_priv_sess_state.attr,
4507
+ &dev_attr_priv_sess_target_state.attr,
44484508 &dev_attr_priv_sess_creator.attr,
44494509 &dev_attr_sess_chap_out_idx.attr,
44504510 &dev_attr_sess_chap_in_idx.attr,
....@@ -4558,6 +4618,8 @@
45584618 return S_IRUGO | S_IWUSR;
45594619 else if (attr == &dev_attr_priv_sess_state.attr)
45604620 return S_IRUGO;
4621
+ else if (attr == &dev_attr_priv_sess_target_state.attr)
4622
+ return S_IRUGO;
45614623 else if (attr == &dev_attr_priv_sess_creator.attr)
45624624 return S_IRUGO;
45634625 else if (attr == &dev_attr_priv_sess_target_id.attr)