Commit d3df6dcc authored by Jon Grimm's avatar Jon Grimm

sctp: in sendmsg: on err, only free asoc if init failed. (jgrimm)

In sendmsg(), the lower layers own the association cleanup after
the ASSOCIATE call has succeeded, so the error path should _only_
free the asoc if we've failed to pass this responsibility to
the lower layer (otherwise we double-free the asoc). 
parent ef010578
...@@ -726,9 +726,9 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout) ...@@ -726,9 +726,9 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout)
* flags - flags sent or received with the user message, see Section * flags - flags sent or received with the user message, see Section
* 5 for complete description of the flags. * 5 for complete description of the flags.
* *
* NB: The argument 'msg' is a user space address. * Note: This function could use a rewrite especially when explicit
* connect support comes in.
*/ */
/* BUG: We do not implement timeouts. */
/* BUG: We do not implement the equivalent of wait_for_tcp_memory(). */ /* BUG: We do not implement the equivalent of wait_for_tcp_memory(). */
SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *, sctp_cmsgs_t *); SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *, sctp_cmsgs_t *);
...@@ -737,7 +737,7 @@ SCTP_STATIC int sctp_sendmsg(struct sock *sk, struct msghdr *msg, int size) ...@@ -737,7 +737,7 @@ SCTP_STATIC int sctp_sendmsg(struct sock *sk, struct msghdr *msg, int size)
{ {
sctp_opt_t *sp; sctp_opt_t *sp;
sctp_endpoint_t *ep; sctp_endpoint_t *ep;
sctp_association_t *asoc = NULL; sctp_association_t *new_asoc=NULL, *asoc=NULL;
sctp_transport_t *transport; sctp_transport_t *transport;
sctp_chunk_t *chunk = NULL; sctp_chunk_t *chunk = NULL;
sockaddr_storage_t to; sockaddr_storage_t to;
...@@ -906,11 +906,12 @@ SCTP_STATIC int sctp_sendmsg(struct sock *sk, struct msghdr *msg, int size) ...@@ -906,11 +906,12 @@ SCTP_STATIC int sctp_sendmsg(struct sock *sk, struct msghdr *msg, int size)
} }
scope = sctp_scope(&to); scope = sctp_scope(&to);
asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); new_asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL);
if (!asoc) { if (!new_asoc) {
err = -ENOMEM; err = -ENOMEM;
goto out_unlock; goto out_unlock;
} }
asoc = new_asoc;
/* If the SCTP_INIT ancillary data is specified, set all /* If the SCTP_INIT ancillary data is specified, set all
* the association init values accordingly. * the association init values accordingly.
...@@ -945,7 +946,7 @@ SCTP_STATIC int sctp_sendmsg(struct sock *sk, struct msghdr *msg, int size) ...@@ -945,7 +946,7 @@ SCTP_STATIC int sctp_sendmsg(struct sock *sk, struct msghdr *msg, int size)
} }
/* ASSERT: we have a valid association at this point. */ /* ASSERT: we have a valid association at this point. */
SCTP_DEBUG_PRINTK("We have a valid association. \n"); SCTP_DEBUG_PRINTK("We have a valid association.\n");
/* API 7.1.7, the sndbuf size per association bounds the /* API 7.1.7, the sndbuf size per association bounds the
* maximum size of data that can be sent in a single send call. * maximum size of data that can be sent in a single send call.
...@@ -1053,10 +1054,16 @@ SCTP_STATIC int sctp_sendmsg(struct sock *sk, struct msghdr *msg, int size) ...@@ -1053,10 +1054,16 @@ SCTP_STATIC int sctp_sendmsg(struct sock *sk, struct msghdr *msg, int size)
err = msg_len; err = msg_len;
goto out_unlock; goto out_unlock;
} }
/* If we are already past ASSOCIATE, the lower
* layers are responsible for its cleanup.
*/
goto out_free_chunk;
out_free: out_free:
if (SCTP_STATE_CLOSED == asoc->state) if (new_asoc)
sctp_association_free(asoc); sctp_association_free(asoc);
out_free_chunk:
if (chunk) if (chunk)
sctp_free_chunk(chunk); sctp_free_chunk(chunk);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment