diff options
author | David S. Miller <davem@davemloft.net> | 2016-05-21 02:20:12 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-05-21 02:20:12 +0300 |
commit | 9a0351dfca14b44443a98c0cafe4de234d1ba469 (patch) | |
tree | 6f7e5d447ec8020d67980cd51e5ff6b798b4086f | |
parent | fc64869c48494a401b1fb627c9ecc4e6c1d74b0d (diff) | |
parent | c948bb5c2cc4d63f9d76fc02baf5a8331e3cd27f (diff) | |
download | linux-9a0351dfca14b44443a98c0cafe4de234d1ba469.tar.xz |
Merge branch 'rds-conn-spamming'
Sowmini Varadhan says:
====================
RDS: TCP: connection spamming fixes
We have been testing the RDS-TCP code with a connection spammer
that sends incoming SYNs to the RDS listen port well after
an rds-tcp connection has been established, and found a few
race-windows that are fixed by this patch series.
Patch 1 avoids a null pointer deref when an incoming SYN
shows up when a netns is being dismantled, or when the
rds-tcp module is being unloaded.
Patch 2 addresses the case when a SYN is received after the
connection arbitration algorithm has converged: the incoming
SYN should not needlessly quiesce the transmit path, and it
should not result in needless TCP connection resets due to
re-execution of the connection arbitration logic.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/rds/tcp_listen.c | 13 |
1 files changed, 9 insertions, 4 deletions
diff --git a/net/rds/tcp_listen.c b/net/rds/tcp_listen.c index 3fa367945105..4bf4befe5066 100644 --- a/net/rds/tcp_listen.c +++ b/net/rds/tcp_listen.c @@ -80,6 +80,9 @@ int rds_tcp_accept_one(struct socket *sock) int conn_state; struct sock *nsk; + if (!sock) /* module unload or netns delete in progress */ + return -ENETUNREACH; + ret = sock_create_kern(sock_net(sock->sk), sock->sk->sk_family, sock->sk->sk_type, sock->sk->sk_protocol, &new_sock); @@ -129,11 +132,13 @@ int rds_tcp_accept_one(struct socket *sock) * so we must quiesce any send threads before resetting * c_transport_data. */ - wait_event(conn->c_waitq, - !test_bit(RDS_IN_XMIT, &conn->c_flags)); - if (ntohl(inet->inet_saddr) < ntohl(inet->inet_daddr)) { + if (ntohl(inet->inet_saddr) < ntohl(inet->inet_daddr) || + !conn->c_outgoing) { goto rst_nsk; - } else if (rs_tcp->t_sock) { + } else { + atomic_set(&conn->c_state, RDS_CONN_CONNECTING); + wait_event(conn->c_waitq, + !test_bit(RDS_IN_XMIT, &conn->c_flags)); rds_tcp_restore_callbacks(rs_tcp->t_sock, rs_tcp); conn->c_outgoing = 0; } |