Commit 51359bfc authored by David S. Miller's avatar David S. Miller

Merge branch 'sctp-accept-deadlock'

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: default avatarDavid S. Miller <davem@davemloft.net>
parents 43ae93a9 635682a1
...@@ -244,12 +244,13 @@ void sctp_generate_t3_rtx_event(unsigned long peer) ...@@ -244,12 +244,13 @@ void sctp_generate_t3_rtx_event(unsigned long peer)
int error; int error;
struct sctp_transport *transport = (struct sctp_transport *) peer; struct sctp_transport *transport = (struct sctp_transport *) peer;
struct sctp_association *asoc = transport->asoc; 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. */ /* Check whether a task is in the sock. */
bh_lock_sock(asoc->base.sk); bh_lock_sock(sk);
if (sock_owned_by_user(asoc->base.sk)) { if (sock_owned_by_user(sk)) {
pr_debug("%s: sock is busy\n", __func__); pr_debug("%s: sock is busy\n", __func__);
/* Try again later. */ /* Try again later. */
...@@ -272,10 +273,10 @@ void sctp_generate_t3_rtx_event(unsigned long peer) ...@@ -272,10 +273,10 @@ void sctp_generate_t3_rtx_event(unsigned long peer)
transport, GFP_ATOMIC); transport, GFP_ATOMIC);
if (error) if (error)
asoc->base.sk->sk_err = -error; sk->sk_err = -error;
out_unlock: out_unlock:
bh_unlock_sock(asoc->base.sk); bh_unlock_sock(sk);
sctp_transport_put(transport); sctp_transport_put(transport);
} }
...@@ -285,11 +286,12 @@ void sctp_generate_t3_rtx_event(unsigned long peer) ...@@ -285,11 +286,12 @@ void sctp_generate_t3_rtx_event(unsigned long peer)
static void sctp_generate_timeout_event(struct sctp_association *asoc, static void sctp_generate_timeout_event(struct sctp_association *asoc,
sctp_event_timeout_t timeout_type) 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; int error = 0;
bh_lock_sock(asoc->base.sk); bh_lock_sock(sk);
if (sock_owned_by_user(asoc->base.sk)) { if (sock_owned_by_user(sk)) {
pr_debug("%s: sock is busy: timer %d\n", __func__, pr_debug("%s: sock is busy: timer %d\n", __func__,
timeout_type); timeout_type);
...@@ -312,10 +314,10 @@ static void sctp_generate_timeout_event(struct sctp_association *asoc, ...@@ -312,10 +314,10 @@ static void sctp_generate_timeout_event(struct sctp_association *asoc,
(void *)timeout_type, GFP_ATOMIC); (void *)timeout_type, GFP_ATOMIC);
if (error) if (error)
asoc->base.sk->sk_err = -error; sk->sk_err = -error;
out_unlock: out_unlock:
bh_unlock_sock(asoc->base.sk); bh_unlock_sock(sk);
sctp_association_put(asoc); sctp_association_put(asoc);
} }
...@@ -365,10 +367,11 @@ void sctp_generate_heartbeat_event(unsigned long data) ...@@ -365,10 +367,11 @@ void sctp_generate_heartbeat_event(unsigned long data)
int error = 0; int error = 0;
struct sctp_transport *transport = (struct sctp_transport *) data; struct sctp_transport *transport = (struct sctp_transport *) data;
struct sctp_association *asoc = transport->asoc; 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); bh_lock_sock(sk);
if (sock_owned_by_user(asoc->base.sk)) { if (sock_owned_by_user(sk)) {
pr_debug("%s: sock is busy\n", __func__); pr_debug("%s: sock is busy\n", __func__);
/* Try again later. */ /* Try again later. */
...@@ -389,10 +392,10 @@ void sctp_generate_heartbeat_event(unsigned long data) ...@@ -389,10 +392,10 @@ void sctp_generate_heartbeat_event(unsigned long data)
transport, GFP_ATOMIC); transport, GFP_ATOMIC);
if (error) if (error)
asoc->base.sk->sk_err = -error; sk->sk_err = -error;
out_unlock: out_unlock:
bh_unlock_sock(asoc->base.sk); bh_unlock_sock(sk);
sctp_transport_put(transport); sctp_transport_put(transport);
} }
...@@ -403,10 +406,11 @@ void sctp_generate_proto_unreach_event(unsigned long data) ...@@ -403,10 +406,11 @@ void sctp_generate_proto_unreach_event(unsigned long data)
{ {
struct sctp_transport *transport = (struct sctp_transport *) data; struct sctp_transport *transport = (struct sctp_transport *) data;
struct sctp_association *asoc = transport->asoc; 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); bh_lock_sock(sk);
if (sock_owned_by_user(asoc->base.sk)) { if (sock_owned_by_user(sk)) {
pr_debug("%s: sock is busy\n", __func__); pr_debug("%s: sock is busy\n", __func__);
/* Try again later. */ /* Try again later. */
...@@ -427,7 +431,7 @@ void sctp_generate_proto_unreach_event(unsigned long data) ...@@ -427,7 +431,7 @@ void sctp_generate_proto_unreach_event(unsigned long data)
asoc->state, asoc->ep, asoc, transport, GFP_ATOMIC); asoc->state, asoc->ep, asoc, transport, GFP_ATOMIC);
out_unlock: out_unlock:
bh_unlock_sock(asoc->base.sk); bh_unlock_sock(sk);
sctp_association_put(asoc); sctp_association_put(asoc);
} }
......
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