}
 
 static int
-iscsi_if_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev)
+iscsi_if_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev, u32 rlen)
 {
        char *data = (char*)ev + sizeof(*ev);
        struct iscsi_cls_conn *conn;
        struct iscsi_cls_session *session;
        int err = 0, value = 0, state;
 
-       if (ev->u.set_param.len > PAGE_SIZE)
+       if (ev->u.set_param.len > rlen ||
+           ev->u.set_param.len > PAGE_SIZE)
                return -EINVAL;
 
        session = iscsi_session_lookup(ev->u.set_param.sid);
 
 static int
 iscsi_if_transport_ep(struct iscsi_transport *transport,
-                     struct iscsi_uevent *ev, int msg_type)
+                     struct iscsi_uevent *ev, int msg_type, u32 rlen)
 {
        struct iscsi_endpoint *ep;
        int rc = 0;
        switch (msg_type) {
        case ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST:
        case ISCSI_UEVENT_TRANSPORT_EP_CONNECT:
-               rc = iscsi_if_ep_connect(transport, ev, msg_type);
+               if (rlen < sizeof(struct sockaddr))
+                       rc = -EINVAL;
+               else
+                       rc = iscsi_if_ep_connect(transport, ev, msg_type);
                break;
        case ISCSI_UEVENT_TRANSPORT_EP_POLL:
                if (!transport->ep_poll)
 
 static int
 iscsi_tgt_dscvr(struct iscsi_transport *transport,
-               struct iscsi_uevent *ev)
+               struct iscsi_uevent *ev, u32 rlen)
 {
        struct Scsi_Host *shost;
        struct sockaddr *dst_addr;
        int err;
 
+       if (rlen < sizeof(*dst_addr))
+               return -EINVAL;
+
        if (!transport->tgt_dscvr)
                return -EINVAL;
 
 
 static int
 iscsi_set_host_param(struct iscsi_transport *transport,
-                    struct iscsi_uevent *ev)
+                    struct iscsi_uevent *ev, u32 rlen)
 {
        char *data = (char*)ev + sizeof(*ev);
        struct Scsi_Host *shost;
        if (!transport->set_host_param)
                return -ENOSYS;
 
-       if (ev->u.set_host_param.len > PAGE_SIZE)
+       if (ev->u.set_host_param.len > rlen ||
+           ev->u.set_host_param.len > PAGE_SIZE)
                return -EINVAL;
 
        shost = scsi_host_lookup(ev->u.set_host_param.host_no);
 }
 
 static int
-iscsi_set_path(struct iscsi_transport *transport, struct iscsi_uevent *ev)
+iscsi_set_path(struct iscsi_transport *transport, struct iscsi_uevent *ev, u32 rlen)
 {
        struct Scsi_Host *shost;
        struct iscsi_path *params;
        int err;
 
+       if (rlen < sizeof(*params))
+               return -EINVAL;
+
        if (!transport->set_path)
                return -ENOSYS;
 
 }
 
 static int
-iscsi_send_ping(struct iscsi_transport *transport, struct iscsi_uevent *ev)
+iscsi_send_ping(struct iscsi_transport *transport, struct iscsi_uevent *ev, u32 rlen)
 {
        struct Scsi_Host *shost;
        struct sockaddr *dst_addr;
        int err;
 
+       if (rlen < sizeof(*dst_addr))
+               return -EINVAL;
+
        if (!transport->send_ping)
                return -ENOSYS;
 
 }
 
 static int iscsi_if_transport_conn(struct iscsi_transport *transport,
-                                  struct nlmsghdr *nlh)
+                                  struct nlmsghdr *nlh, u32 pdu_len)
 {
        struct iscsi_uevent *ev = nlmsg_data(nlh);
        struct iscsi_cls_session *session;
        struct iscsi_cls_conn *conn = NULL;
        struct iscsi_endpoint *ep;
-       uint32_t pdu_len;
        int err = 0;
 
        switch (nlh->nlmsg_type) {
 
                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;
        struct iscsi_internal *priv;
        struct iscsi_cls_session *session;
        struct iscsi_endpoint *ep = NULL;
+       u32 rlen;
 
        if (!netlink_capable(skb, CAP_SYS_ADMIN))
                return -EPERM;
 
        portid = NETLINK_CB(skb).portid;
 
+       /*
+        * Even though the remaining payload may not be regarded as nlattr,
+        * (like address or something else), calculate the remaining length
+        * here to ease following length checks.
+        */
+       rlen = nlmsg_attrlen(nlh, sizeof(*ev));
+
        switch (nlh->nlmsg_type) {
        case ISCSI_UEVENT_CREATE_SESSION:
                err = iscsi_if_create_session(priv, ep, ev,
                        err = -EINVAL;
                break;
        case ISCSI_UEVENT_SET_PARAM:
-               err = iscsi_if_set_param(transport, ev);
+               err = iscsi_if_set_param(transport, ev, rlen);
                break;
        case ISCSI_UEVENT_CREATE_CONN:
        case ISCSI_UEVENT_DESTROY_CONN:
        case ISCSI_UEVENT_START_CONN:
        case ISCSI_UEVENT_BIND_CONN:
        case ISCSI_UEVENT_SEND_PDU:
-               err = iscsi_if_transport_conn(transport, nlh);
+               err = iscsi_if_transport_conn(transport, nlh, rlen);
                break;
        case ISCSI_UEVENT_GET_STATS:
                err = iscsi_if_get_stats(transport, nlh);
        case ISCSI_UEVENT_TRANSPORT_EP_POLL:
        case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
        case ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST:
-               err = iscsi_if_transport_ep(transport, ev, nlh->nlmsg_type);
+               err = iscsi_if_transport_ep(transport, ev, nlh->nlmsg_type, rlen);
                break;
        case ISCSI_UEVENT_TGT_DSCVR:
-               err = iscsi_tgt_dscvr(transport, ev);
+               err = iscsi_tgt_dscvr(transport, ev, rlen);
                break;
        case ISCSI_UEVENT_SET_HOST_PARAM:
-               err = iscsi_set_host_param(transport, ev);
+               err = iscsi_set_host_param(transport, ev, rlen);
                break;
        case ISCSI_UEVENT_PATH_UPDATE:
-               err = iscsi_set_path(transport, ev);
+               err = iscsi_set_path(transport, ev, rlen);
                break;
        case ISCSI_UEVENT_SET_IFACE_PARAMS:
-               err = iscsi_set_iface_params(transport, ev,
-                                            nlmsg_attrlen(nlh, sizeof(*ev)));
+               err = iscsi_set_iface_params(transport, ev, rlen);
                break;
        case ISCSI_UEVENT_PING:
-               err = iscsi_send_ping(transport, ev);
+               err = iscsi_send_ping(transport, ev, rlen);
                break;
        case ISCSI_UEVENT_GET_CHAP:
                err = iscsi_get_chap(transport, nlh);
                err = iscsi_delete_chap(transport, ev);
                break;
        case ISCSI_UEVENT_SET_FLASHNODE_PARAMS:
-               err = iscsi_set_flashnode_param(transport, ev,
-                                               nlmsg_attrlen(nlh,
-                                                             sizeof(*ev)));
+               err = iscsi_set_flashnode_param(transport, ev, rlen);
                break;
        case ISCSI_UEVENT_NEW_FLASHNODE:
-               err = iscsi_new_flashnode(transport, ev,
-                                         nlmsg_attrlen(nlh, sizeof(*ev)));
+               err = iscsi_new_flashnode(transport, ev, rlen);
                break;
        case ISCSI_UEVENT_DEL_FLASHNODE:
                err = iscsi_del_flashnode(transport, ev);
                err = iscsi_logout_flashnode_sid(transport, ev);
                break;
        case ISCSI_UEVENT_SET_CHAP:
-               err = iscsi_set_chap(transport, ev,
-                                    nlmsg_attrlen(nlh, sizeof(*ev)));
+               err = iscsi_set_chap(transport, ev, rlen);
                break;
        case ISCSI_UEVENT_GET_HOST_STATS:
                err = iscsi_get_host_stats(transport, nlh);