summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2016-05-21 02:20:12 +0300
committerDavid S. Miller <davem@davemloft.net>2016-05-21 02:20:12 +0300
commit9a0351dfca14b44443a98c0cafe4de234d1ba469 (patch)
tree6f7e5d447ec8020d67980cd51e5ff6b798b4086f
parentfc64869c48494a401b1fb627c9ecc4e6c1d74b0d (diff)
parentc948bb5c2cc4d63f9d76fc02baf5a8331e3cd27f (diff)
downloadlinux-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.c13
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;
}