--- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1796,7 +1796,7 @@ static int sctp_sendmsg_to_asoc(struct sctp_association *asoc, bool wait_connect = false; struct sctp_chunk *chunk; long timeo; - int err; + int err, mem = 0; if (sinfo->sinfo_stream >= asoc->stream.outcnt) { err = -EINVAL; @@ -1807,11 +1807,12 @@ static int sctp_sendmsg_to_asoc(struct sctp_association *asoc, err = sctp_stream_init_ext(&asoc->stream, sinfo->sinfo_stream); if (err) goto err; + mem = 1; } if (sp->disable_fragments && msg_len > asoc->frag_point) { err = -EMSGSIZE; - goto err; + goto free_mem; } if (asoc->pmtu_pending) { @@ -1830,20 +1831,20 @@ static int sctp_sendmsg_to_asoc(struct sctp_association *asoc, timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT); err = sctp_wait_for_sndbuf(asoc, &timeo, msg_len); if (err) - goto err; + goto free_mem; } if (sctp_state(asoc, CLOSED)) { err = sctp_primitive_ASSOCIATE(net, asoc, NULL); if (err) - goto err; + goto free_mem; if (asoc->ep->intl_enable) { timeo = sock_sndtimeo(sk, 0); err = sctp_wait_for_connect(asoc, &timeo); if (err) { err = -ESRCH; - goto err; + goto free_mem; } } else { wait_connect = true; @@ -1855,7 +1856,7 @@ static int sctp_sendmsg_to_asoc(struct sctp_association *asoc, datamsg = sctp_datamsg_from_user(asoc, sinfo, &msg->msg_iter); if (IS_ERR(datamsg)) { err = PTR_ERR(datamsg); - goto err; + goto free_mem; } asoc->force_delay = !!(msg->msg_flags & MSG_MORE); @@ -1869,7 +1870,7 @@ static int sctp_sendmsg_to_asoc(struct sctp_association *asoc, err = sctp_primitive_SEND(net, asoc, datamsg); if (err) { sctp_datamsg_free(datamsg); - goto err; + goto free_mem; } pr_debug("%s: we sent primitively\n", __func__); @@ -1883,6 +1884,10 @@ static int sctp_sendmsg_to_asoc(struct sctp_association *asoc, err = msg_len; +free_mem: + if (mem) + sctp_stream_free(&asoc->stream); + err: return err; }