Skip to content

Commit

Permalink
net: sctp: decouple cleaning some socket data from endpoint
Browse files Browse the repository at this point in the history
Rather instead of having the endpoint clean the garbage from the
socket, use a sk_destruct handler sctp_destruct_sock(), that does
the job for that when there are no more references on the socket.
At least do this for our crypto transform through crypto_free_hash()
that is allocated when in listening state.

Also, perform sctp_put_port() only when sk is valid. At a later
point in time we can still determine if there's an option of
placing this into sk_prot->unhash() or sctp_endpoint_free() without
any races. For now, leave it in sctp_endpoint_destroy() though.

Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
Acked-by: Vlad Yasevich <vyasevich@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Daniel Borkmann authored and David S. Miller committed Jun 25, 2013
1 parent b527fe6 commit 0a2fbac
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 10 deletions.
19 changes: 10 additions & 9 deletions net/sctp/endpointola.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,10 +247,9 @@ void sctp_endpoint_free(struct sctp_endpoint *ep)
/* Final destructor for endpoint. */
static void sctp_endpoint_destroy(struct sctp_endpoint *ep)
{
SCTP_ASSERT(ep->base.dead, "Endpoint is not dead", return);
struct sock *sk;

/* Free up the HMAC transform. */
crypto_free_hash(sctp_sk(ep->base.sk)->hmac);
SCTP_ASSERT(ep->base.dead, "Endpoint is not dead", return);

/* Free the digest buffer */
kfree(ep->digest);
Expand All @@ -271,13 +270,15 @@ static void sctp_endpoint_destroy(struct sctp_endpoint *ep)

memset(ep->secret_key, 0, sizeof(ep->secret_key));

/* Remove and free the port */
if (sctp_sk(ep->base.sk)->bind_hash)
sctp_put_port(ep->base.sk);

/* Give up our hold on the sock. */
if (ep->base.sk)
sock_put(ep->base.sk);
sk = ep->base.sk;
if (sk != NULL) {
/* Remove and free the port */
if (sctp_sk(sk)->bind_hash)
sctp_put_port(sk);

sock_put(sk);
}

kfree(ep);
SCTP_DBG_OBJCNT_DEC(ep);
Expand Down
16 changes: 15 additions & 1 deletion net/sctp/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ static int sctp_wait_for_packet(struct sock * sk, int *err, long *timeo_p);
static int sctp_wait_for_connect(struct sctp_association *, long *timeo_p);
static int sctp_wait_for_accept(struct sock *sk, long timeo);
static void sctp_wait_for_close(struct sock *sk, long timeo);
static void sctp_destruct_sock(struct sock *sk);
static struct sctp_af *sctp_sockaddr_af(struct sctp_sock *opt,
union sctp_addr *addr, int len);
static int sctp_bindx_add(struct sock *, struct sockaddr *, int);
Expand Down Expand Up @@ -3966,6 +3967,8 @@ static int sctp_init_sock(struct sock *sk)

sp->hmac = NULL;

sk->sk_destruct = sctp_destruct_sock;

SCTP_DBG_OBJCNT_INC(sock);

local_bh_disable();
Expand Down Expand Up @@ -4008,6 +4011,17 @@ static void sctp_destroy_sock(struct sock *sk)
local_bh_enable();
}

/* Triggered when there are no references on the socket anymore */
static void sctp_destruct_sock(struct sock *sk)
{
struct sctp_sock *sp = sctp_sk(sk);

/* Free up the HMAC transform. */
crypto_free_hash(sp->hmac);

inet_sock_destruct(sk);
}

/* API 4.1.7 shutdown() - TCP Style Syntax
* int shutdown(int socket, int how);
*
Expand Down Expand Up @@ -6848,7 +6862,7 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk,
newsk->sk_reuse = sk->sk_reuse;

newsk->sk_shutdown = sk->sk_shutdown;
newsk->sk_destruct = inet_sock_destruct;
newsk->sk_destruct = sctp_destruct_sock;
newsk->sk_family = sk->sk_family;
newsk->sk_protocol = IPPROTO_SCTP;
newsk->sk_backlog_rcv = sk->sk_prot->backlog_rcv;
Expand Down

0 comments on commit 0a2fbac

Please sign in to comment.