sctp: free msg->chunks when sctp_primitive_SEND return err
[cascardo/linux.git] / net / sctp / socket.c
index 8812e1b..6cdc61c 100644 (file)
@@ -1958,6 +1958,8 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len)
 
        /* Now send the (possibly) fragmented message. */
        list_for_each_entry(chunk, &datamsg->chunks, frag_list) {
+               sctp_chunk_hold(chunk);
+
                /* Do accounting for the write space.  */
                sctp_set_owner_w(chunk);
 
@@ -1970,13 +1972,15 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len)
         * breaks.
         */
        err = sctp_primitive_SEND(net, asoc, datamsg);
-       sctp_datamsg_put(datamsg);
        /* Did the lower layer accept the chunk? */
-       if (err)
+       if (err) {
+               sctp_datamsg_free(datamsg);
                goto out_free;
+       }
 
        pr_debug("%s: we sent primitively\n", __func__);
 
+       sctp_datamsg_put(datamsg);
        err = msg_len;
 
        if (unlikely(wait_connect)) {
@@ -2079,7 +2083,7 @@ static int sctp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
        lock_sock(sk);
 
        if (sctp_style(sk, TCP) && !sctp_sstate(sk, ESTABLISHED) &&
-           !sctp_sstate(sk, CLOSING)) {
+           !sctp_sstate(sk, CLOSING) && !sctp_sstate(sk, CLOSED)) {
                err = -ENOTCONN;
                goto out;
        }