Skip to content

Commit

Permalink
Merge branch 'sctp-accept-deadlock'
Browse files Browse the repository at this point in the history
Karl Heiss says:

====================
sctp: Fix SCTP deadlock

These patches fix a deadlock during accept() of an SCTP connection.

The first patch fixes whitespace issues.

The second patch actually fixes the deadlock race.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Sep 29, 2015
2 parents 43ae93a + 635682a commit 51359bf
Showing 1 changed file with 24 additions and 20 deletions.
44 changes: 24 additions & 20 deletions net/sctp/sm_sideeffect.c
Original file line number Diff line number Diff line change
Expand Up @@ -244,12 +244,13 @@ void sctp_generate_t3_rtx_event(unsigned long peer)
int error;
struct sctp_transport *transport = (struct sctp_transport *) peer;
struct sctp_association *asoc = transport->asoc;
struct net *net = sock_net(asoc->base.sk);
struct sock *sk = asoc->base.sk;
struct net *net = sock_net(sk);

/* Check whether a task is in the sock. */

bh_lock_sock(asoc->base.sk);
if (sock_owned_by_user(asoc->base.sk)) {
bh_lock_sock(sk);
if (sock_owned_by_user(sk)) {
pr_debug("%s: sock is busy\n", __func__);

/* Try again later. */
Expand All @@ -272,10 +273,10 @@ void sctp_generate_t3_rtx_event(unsigned long peer)
transport, GFP_ATOMIC);

if (error)
asoc->base.sk->sk_err = -error;
sk->sk_err = -error;

out_unlock:
bh_unlock_sock(asoc->base.sk);
bh_unlock_sock(sk);
sctp_transport_put(transport);
}

Expand All @@ -285,11 +286,12 @@ void sctp_generate_t3_rtx_event(unsigned long peer)
static void sctp_generate_timeout_event(struct sctp_association *asoc,
sctp_event_timeout_t timeout_type)
{
struct net *net = sock_net(asoc->base.sk);
struct sock *sk = asoc->base.sk;
struct net *net = sock_net(sk);
int error = 0;

bh_lock_sock(asoc->base.sk);
if (sock_owned_by_user(asoc->base.sk)) {
bh_lock_sock(sk);
if (sock_owned_by_user(sk)) {
pr_debug("%s: sock is busy: timer %d\n", __func__,
timeout_type);

Expand All @@ -312,10 +314,10 @@ static void sctp_generate_timeout_event(struct sctp_association *asoc,
(void *)timeout_type, GFP_ATOMIC);

if (error)
asoc->base.sk->sk_err = -error;
sk->sk_err = -error;

out_unlock:
bh_unlock_sock(asoc->base.sk);
bh_unlock_sock(sk);
sctp_association_put(asoc);
}

Expand Down Expand Up @@ -365,10 +367,11 @@ void sctp_generate_heartbeat_event(unsigned long data)
int error = 0;
struct sctp_transport *transport = (struct sctp_transport *) data;
struct sctp_association *asoc = transport->asoc;
struct net *net = sock_net(asoc->base.sk);
struct sock *sk = asoc->base.sk;
struct net *net = sock_net(sk);

bh_lock_sock(asoc->base.sk);
if (sock_owned_by_user(asoc->base.sk)) {
bh_lock_sock(sk);
if (sock_owned_by_user(sk)) {
pr_debug("%s: sock is busy\n", __func__);

/* Try again later. */
Expand All @@ -388,11 +391,11 @@ void sctp_generate_heartbeat_event(unsigned long data)
asoc->state, asoc->ep, asoc,
transport, GFP_ATOMIC);

if (error)
asoc->base.sk->sk_err = -error;
if (error)
sk->sk_err = -error;

out_unlock:
bh_unlock_sock(asoc->base.sk);
bh_unlock_sock(sk);
sctp_transport_put(transport);
}

Expand All @@ -403,10 +406,11 @@ void sctp_generate_proto_unreach_event(unsigned long data)
{
struct sctp_transport *transport = (struct sctp_transport *) data;
struct sctp_association *asoc = transport->asoc;
struct net *net = sock_net(asoc->base.sk);
struct sock *sk = asoc->base.sk;
struct net *net = sock_net(sk);

bh_lock_sock(asoc->base.sk);
if (sock_owned_by_user(asoc->base.sk)) {
bh_lock_sock(sk);
if (sock_owned_by_user(sk)) {
pr_debug("%s: sock is busy\n", __func__);

/* Try again later. */
Expand All @@ -427,7 +431,7 @@ void sctp_generate_proto_unreach_event(unsigned long data)
asoc->state, asoc->ep, asoc, transport, GFP_ATOMIC);

out_unlock:
bh_unlock_sock(asoc->base.sk);
bh_unlock_sock(sk);
sctp_association_put(asoc);
}

Expand Down

0 comments on commit 51359bf

Please sign in to comment.