| .. | .. |
|---|
| 1674 | 1674 | return name; |
|---|
| 1675 | 1675 | } |
|---|
| 1676 | 1676 | |
|---|
| 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 | + |
|---|
| 1677 | 1684 | int iscsi_session_chkready(struct iscsi_cls_session *session) |
|---|
| 1678 | 1685 | { |
|---|
| 1679 | 1686 | unsigned long flags; |
|---|
| .. | .. |
|---|
| 1805 | 1812 | if ((scan_data->channel == SCAN_WILD_CARD || |
|---|
| 1806 | 1813 | scan_data->channel == 0) && |
|---|
| 1807 | 1814 | (scan_data->id == SCAN_WILD_CARD || |
|---|
| 1808 | | - scan_data->id == id)) |
|---|
| 1815 | + scan_data->id == id)) { |
|---|
| 1809 | 1816 | scsi_scan_target(&session->dev, 0, id, |
|---|
| 1810 | 1817 | 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 | + } |
|---|
| 1811 | 1822 | } |
|---|
| 1812 | 1823 | |
|---|
| 1813 | 1824 | user_scan_exit: |
|---|
| .. | .. |
|---|
| 1996 | 2007 | struct iscsi_cls_host *ihost = shost->shost_data; |
|---|
| 1997 | 2008 | unsigned long flags; |
|---|
| 1998 | 2009 | unsigned int target_id; |
|---|
| 2010 | + bool remove_target = true; |
|---|
| 1999 | 2011 | |
|---|
| 2000 | 2012 | ISCSI_DBG_TRANS_SESSION(session, "Unbinding session\n"); |
|---|
| 2001 | 2013 | |
|---|
| 2002 | 2014 | /* Prevent new scans and make sure scanning is not in progress */ |
|---|
| 2003 | 2015 | mutex_lock(&ihost->mutex); |
|---|
| 2004 | 2016 | 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) { |
|---|
| 2006 | 2020 | spin_unlock_irqrestore(&session->lock, flags); |
|---|
| 2007 | 2021 | 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; |
|---|
| 2009 | 2025 | } |
|---|
| 2010 | 2026 | |
|---|
| 2027 | + session->target_state = ISCSI_SESSION_TARGET_UNBINDING; |
|---|
| 2011 | 2028 | target_id = session->target_id; |
|---|
| 2012 | 2029 | session->target_id = ISCSI_MAX_TARGET; |
|---|
| 2013 | 2030 | spin_unlock_irqrestore(&session->lock, flags); |
|---|
| 2014 | 2031 | mutex_unlock(&ihost->mutex); |
|---|
| 2015 | 2032 | |
|---|
| 2016 | | - scsi_remove_target(&session->dev); |
|---|
| 2033 | + if (remove_target) |
|---|
| 2034 | + scsi_remove_target(&session->dev); |
|---|
| 2017 | 2035 | |
|---|
| 2018 | 2036 | if (session->ida_used) |
|---|
| 2019 | 2037 | ida_simple_remove(&iscsi_sess_ida, target_id); |
|---|
| 2020 | 2038 | |
|---|
| 2021 | | -unbind_session_exit: |
|---|
| 2022 | 2039 | iscsi_session_event(session, ISCSI_KEVENT_UNBIND_SESSION); |
|---|
| 2023 | 2040 | 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); |
|---|
| 2024 | 2045 | } |
|---|
| 2025 | 2046 | |
|---|
| 2026 | 2047 | static void __iscsi_destroy_session(struct work_struct *work) |
|---|
| .. | .. |
|---|
| 2089 | 2110 | session->ida_used = true; |
|---|
| 2090 | 2111 | } else |
|---|
| 2091 | 2112 | 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); |
|---|
| 2092 | 2116 | |
|---|
| 2093 | 2117 | dev_set_name(&session->dev, "session%u", session->sid); |
|---|
| 2094 | 2118 | err = device_add(&session->dev); |
|---|
| .. | .. |
|---|
| 2967 | 2991 | } |
|---|
| 2968 | 2992 | |
|---|
| 2969 | 2993 | 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) |
|---|
| 2971 | 2995 | { |
|---|
| 2972 | 2996 | char *data = (char*)ev + sizeof(*ev); |
|---|
| 2973 | 2997 | struct iscsi_cls_conn *conn; |
|---|
| 2974 | 2998 | struct iscsi_cls_session *session; |
|---|
| 2975 | 2999 | int err = 0, value = 0, state; |
|---|
| 2976 | 3000 | |
|---|
| 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) |
|---|
| 2978 | 3003 | return -EINVAL; |
|---|
| 2979 | 3004 | |
|---|
| 2980 | 3005 | session = iscsi_session_lookup(ev->u.set_param.sid); |
|---|
| 2981 | 3006 | conn = iscsi_conn_lookup(ev->u.set_param.sid, ev->u.set_param.cid); |
|---|
| 2982 | 3007 | 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) |
|---|
| 2983 | 3012 | return -EINVAL; |
|---|
| 2984 | 3013 | |
|---|
| 2985 | 3014 | switch (ev->u.set_param.param) { |
|---|
| .. | .. |
|---|
| 3071 | 3100 | |
|---|
| 3072 | 3101 | static int |
|---|
| 3073 | 3102 | 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) |
|---|
| 3075 | 3104 | { |
|---|
| 3076 | 3105 | struct iscsi_endpoint *ep; |
|---|
| 3077 | 3106 | int rc = 0; |
|---|
| .. | .. |
|---|
| 3079 | 3108 | switch (msg_type) { |
|---|
| 3080 | 3109 | case ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST: |
|---|
| 3081 | 3110 | 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); |
|---|
| 3083 | 3115 | break; |
|---|
| 3084 | 3116 | case ISCSI_UEVENT_TRANSPORT_EP_POLL: |
|---|
| 3085 | 3117 | if (!transport->ep_poll) |
|---|
| .. | .. |
|---|
| 3103 | 3135 | |
|---|
| 3104 | 3136 | static int |
|---|
| 3105 | 3137 | iscsi_tgt_dscvr(struct iscsi_transport *transport, |
|---|
| 3106 | | - struct iscsi_uevent *ev) |
|---|
| 3138 | + struct iscsi_uevent *ev, u32 rlen) |
|---|
| 3107 | 3139 | { |
|---|
| 3108 | 3140 | struct Scsi_Host *shost; |
|---|
| 3109 | 3141 | struct sockaddr *dst_addr; |
|---|
| 3110 | 3142 | int err; |
|---|
| 3143 | + |
|---|
| 3144 | + if (rlen < sizeof(*dst_addr)) |
|---|
| 3145 | + return -EINVAL; |
|---|
| 3111 | 3146 | |
|---|
| 3112 | 3147 | if (!transport->tgt_dscvr) |
|---|
| 3113 | 3148 | return -EINVAL; |
|---|
| .. | .. |
|---|
| 3129 | 3164 | |
|---|
| 3130 | 3165 | static int |
|---|
| 3131 | 3166 | iscsi_set_host_param(struct iscsi_transport *transport, |
|---|
| 3132 | | - struct iscsi_uevent *ev) |
|---|
| 3167 | + struct iscsi_uevent *ev, u32 rlen) |
|---|
| 3133 | 3168 | { |
|---|
| 3134 | 3169 | char *data = (char*)ev + sizeof(*ev); |
|---|
| 3135 | 3170 | struct Scsi_Host *shost; |
|---|
| .. | .. |
|---|
| 3138 | 3173 | if (!transport->set_host_param) |
|---|
| 3139 | 3174 | return -ENOSYS; |
|---|
| 3140 | 3175 | |
|---|
| 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) |
|---|
| 3142 | 3178 | return -EINVAL; |
|---|
| 3143 | 3179 | |
|---|
| 3144 | 3180 | shost = scsi_host_lookup(ev->u.set_host_param.host_no); |
|---|
| .. | .. |
|---|
| 3148 | 3184 | return -ENODEV; |
|---|
| 3149 | 3185 | } |
|---|
| 3150 | 3186 | |
|---|
| 3187 | + /* see similar check in iscsi_if_set_param() */ |
|---|
| 3188 | + if (strlen(data) > ev->u.set_host_param.len) |
|---|
| 3189 | + return -EINVAL; |
|---|
| 3190 | + |
|---|
| 3151 | 3191 | err = transport->set_host_param(shost, ev->u.set_host_param.param, |
|---|
| 3152 | 3192 | data, ev->u.set_host_param.len); |
|---|
| 3153 | 3193 | scsi_host_put(shost); |
|---|
| .. | .. |
|---|
| 3155 | 3195 | } |
|---|
| 3156 | 3196 | |
|---|
| 3157 | 3197 | 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) |
|---|
| 3159 | 3199 | { |
|---|
| 3160 | 3200 | struct Scsi_Host *shost; |
|---|
| 3161 | 3201 | struct iscsi_path *params; |
|---|
| 3162 | 3202 | int err; |
|---|
| 3203 | + |
|---|
| 3204 | + if (rlen < sizeof(*params)) |
|---|
| 3205 | + return -EINVAL; |
|---|
| 3163 | 3206 | |
|---|
| 3164 | 3207 | if (!transport->set_path) |
|---|
| 3165 | 3208 | return -ENOSYS; |
|---|
| .. | .. |
|---|
| 3220 | 3263 | } |
|---|
| 3221 | 3264 | |
|---|
| 3222 | 3265 | 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) |
|---|
| 3224 | 3267 | { |
|---|
| 3225 | 3268 | struct Scsi_Host *shost; |
|---|
| 3226 | 3269 | struct sockaddr *dst_addr; |
|---|
| 3227 | 3270 | int err; |
|---|
| 3271 | + |
|---|
| 3272 | + if (rlen < sizeof(*dst_addr)) |
|---|
| 3273 | + return -EINVAL; |
|---|
| 3228 | 3274 | |
|---|
| 3229 | 3275 | if (!transport->send_ping) |
|---|
| 3230 | 3276 | return -ENOSYS; |
|---|
| .. | .. |
|---|
| 3723 | 3769 | } |
|---|
| 3724 | 3770 | |
|---|
| 3725 | 3771 | static int iscsi_if_transport_conn(struct iscsi_transport *transport, |
|---|
| 3726 | | - struct nlmsghdr *nlh) |
|---|
| 3772 | + struct nlmsghdr *nlh, u32 pdu_len) |
|---|
| 3727 | 3773 | { |
|---|
| 3728 | 3774 | struct iscsi_uevent *ev = nlmsg_data(nlh); |
|---|
| 3729 | 3775 | struct iscsi_cls_session *session; |
|---|
| 3730 | 3776 | struct iscsi_cls_conn *conn = NULL; |
|---|
| 3731 | 3777 | struct iscsi_endpoint *ep; |
|---|
| 3732 | | - uint32_t pdu_len; |
|---|
| 3733 | 3778 | int err = 0; |
|---|
| 3734 | 3779 | |
|---|
| 3735 | 3780 | switch (nlh->nlmsg_type) { |
|---|
| .. | .. |
|---|
| 3809 | 3854 | |
|---|
| 3810 | 3855 | break; |
|---|
| 3811 | 3856 | case ISCSI_UEVENT_SEND_PDU: |
|---|
| 3812 | | - pdu_len = nlh->nlmsg_len - sizeof(*nlh) - sizeof(*ev); |
|---|
| 3813 | | - |
|---|
| 3814 | 3857 | if ((ev->u.send_pdu.hdr_size > pdu_len) || |
|---|
| 3815 | 3858 | (ev->u.send_pdu.data_size > (pdu_len - ev->u.send_pdu.hdr_size))) { |
|---|
| 3816 | 3859 | err = -EINVAL; |
|---|
| .. | .. |
|---|
| 3840 | 3883 | struct iscsi_internal *priv; |
|---|
| 3841 | 3884 | struct iscsi_cls_session *session; |
|---|
| 3842 | 3885 | struct iscsi_endpoint *ep = NULL; |
|---|
| 3886 | + u32 rlen; |
|---|
| 3843 | 3887 | |
|---|
| 3844 | 3888 | if (!netlink_capable(skb, CAP_SYS_ADMIN)) |
|---|
| 3845 | 3889 | return -EPERM; |
|---|
| .. | .. |
|---|
| 3858 | 3902 | return -EINVAL; |
|---|
| 3859 | 3903 | |
|---|
| 3860 | 3904 | 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)); |
|---|
| 3861 | 3912 | |
|---|
| 3862 | 3913 | switch (nlh->nlmsg_type) { |
|---|
| 3863 | 3914 | case ISCSI_UEVENT_CREATE_SESSION: |
|---|
| .. | .. |
|---|
| 3916 | 3967 | err = -EINVAL; |
|---|
| 3917 | 3968 | break; |
|---|
| 3918 | 3969 | case ISCSI_UEVENT_SET_PARAM: |
|---|
| 3919 | | - err = iscsi_set_param(transport, ev); |
|---|
| 3970 | + err = iscsi_if_set_param(transport, ev, rlen); |
|---|
| 3920 | 3971 | break; |
|---|
| 3921 | 3972 | case ISCSI_UEVENT_CREATE_CONN: |
|---|
| 3922 | 3973 | case ISCSI_UEVENT_DESTROY_CONN: |
|---|
| .. | .. |
|---|
| 3924 | 3975 | case ISCSI_UEVENT_START_CONN: |
|---|
| 3925 | 3976 | case ISCSI_UEVENT_BIND_CONN: |
|---|
| 3926 | 3977 | case ISCSI_UEVENT_SEND_PDU: |
|---|
| 3927 | | - err = iscsi_if_transport_conn(transport, nlh); |
|---|
| 3978 | + err = iscsi_if_transport_conn(transport, nlh, rlen); |
|---|
| 3928 | 3979 | break; |
|---|
| 3929 | 3980 | case ISCSI_UEVENT_GET_STATS: |
|---|
| 3930 | 3981 | err = iscsi_if_get_stats(transport, nlh); |
|---|
| .. | .. |
|---|
| 3933 | 3984 | case ISCSI_UEVENT_TRANSPORT_EP_POLL: |
|---|
| 3934 | 3985 | case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT: |
|---|
| 3935 | 3986 | 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); |
|---|
| 3937 | 3988 | break; |
|---|
| 3938 | 3989 | case ISCSI_UEVENT_TGT_DSCVR: |
|---|
| 3939 | | - err = iscsi_tgt_dscvr(transport, ev); |
|---|
| 3990 | + err = iscsi_tgt_dscvr(transport, ev, rlen); |
|---|
| 3940 | 3991 | break; |
|---|
| 3941 | 3992 | case ISCSI_UEVENT_SET_HOST_PARAM: |
|---|
| 3942 | | - err = iscsi_set_host_param(transport, ev); |
|---|
| 3993 | + err = iscsi_set_host_param(transport, ev, rlen); |
|---|
| 3943 | 3994 | break; |
|---|
| 3944 | 3995 | case ISCSI_UEVENT_PATH_UPDATE: |
|---|
| 3945 | | - err = iscsi_set_path(transport, ev); |
|---|
| 3996 | + err = iscsi_set_path(transport, ev, rlen); |
|---|
| 3946 | 3997 | break; |
|---|
| 3947 | 3998 | 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); |
|---|
| 3950 | 4000 | break; |
|---|
| 3951 | 4001 | case ISCSI_UEVENT_PING: |
|---|
| 3952 | | - err = iscsi_send_ping(transport, ev); |
|---|
| 4002 | + err = iscsi_send_ping(transport, ev, rlen); |
|---|
| 3953 | 4003 | break; |
|---|
| 3954 | 4004 | case ISCSI_UEVENT_GET_CHAP: |
|---|
| 3955 | 4005 | err = iscsi_get_chap(transport, nlh); |
|---|
| .. | .. |
|---|
| 3958 | 4008 | err = iscsi_delete_chap(transport, ev); |
|---|
| 3959 | 4009 | break; |
|---|
| 3960 | 4010 | 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); |
|---|
| 3964 | 4012 | break; |
|---|
| 3965 | 4013 | 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); |
|---|
| 3968 | 4015 | break; |
|---|
| 3969 | 4016 | case ISCSI_UEVENT_DEL_FLASHNODE: |
|---|
| 3970 | 4017 | err = iscsi_del_flashnode(transport, ev); |
|---|
| .. | .. |
|---|
| 3979 | 4026 | err = iscsi_logout_flashnode_sid(transport, ev); |
|---|
| 3980 | 4027 | break; |
|---|
| 3981 | 4028 | 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); |
|---|
| 3984 | 4030 | break; |
|---|
| 3985 | 4031 | case ISCSI_UEVENT_GET_HOST_STATS: |
|---|
| 3986 | 4032 | err = iscsi_get_host_stats(transport, nlh); |
|---|
| .. | .. |
|---|
| 4344 | 4390 | iscsi_session_attr(discovery_parent_type, ISCSI_PARAM_DISCOVERY_PARENT_TYPE, 0); |
|---|
| 4345 | 4391 | |
|---|
| 4346 | 4392 | 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 |
|---|
| 4347 | 4406 | show_priv_session_state(struct device *dev, struct device_attribute *attr, |
|---|
| 4348 | 4407 | char *buf) |
|---|
| 4349 | 4408 | { |
|---|
| .. | .. |
|---|
| 4445 | 4504 | &dev_attr_sess_boot_target.attr, |
|---|
| 4446 | 4505 | &dev_attr_priv_sess_recovery_tmo.attr, |
|---|
| 4447 | 4506 | &dev_attr_priv_sess_state.attr, |
|---|
| 4507 | + &dev_attr_priv_sess_target_state.attr, |
|---|
| 4448 | 4508 | &dev_attr_priv_sess_creator.attr, |
|---|
| 4449 | 4509 | &dev_attr_sess_chap_out_idx.attr, |
|---|
| 4450 | 4510 | &dev_attr_sess_chap_in_idx.attr, |
|---|
| .. | .. |
|---|
| 4558 | 4618 | return S_IRUGO | S_IWUSR; |
|---|
| 4559 | 4619 | else if (attr == &dev_attr_priv_sess_state.attr) |
|---|
| 4560 | 4620 | return S_IRUGO; |
|---|
| 4621 | + else if (attr == &dev_attr_priv_sess_target_state.attr) |
|---|
| 4622 | + return S_IRUGO; |
|---|
| 4561 | 4623 | else if (attr == &dev_attr_priv_sess_creator.attr) |
|---|
| 4562 | 4624 | return S_IRUGO; |
|---|
| 4563 | 4625 | else if (attr == &dev_attr_priv_sess_target_id.attr) |
|---|