aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_input.c
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2012-07-17 04:13:05 -0400
committerDavid S. Miller <davem@davemloft.net>2012-07-17 04:36:20 -0400
commit282f23c6ee343126156dd41218b22ece96d747e3 (patch)
tree9a306d99ed77d760078d29699edd3007507d709b /net/ipv4/tcp_input.c
parenta858d64b7709ca7bd2ee71d66ef3b7190cdcbb7d (diff)
tcp: implement RFC 5961 3.2
Implement the RFC 5691 mitigation against Blind Reset attack using RST bit. Idea is to validate incoming RST sequence, to match RCV.NXT value, instead of previouly accepted window : (RCV.NXT <= SEG.SEQ < RCV.NXT+RCV.WND) If sequence is in window but not an exact match, send a "challenge ACK", so that the other part can resend an RST with the appropriate sequence. Add a new sysctl, tcp_challenge_ack_limit, to limit number of challenge ACK sent per second. Add a new SNMP counter to count number of challenge acks sent. (netstat -s | grep TCPChallengeACK) Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Kiran Kumar Kella <kkiran@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_input.c')
-rw-r--r--net/ipv4/tcp_input.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index cc4e12f1f2f..c841a899037 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -88,6 +88,9 @@ int sysctl_tcp_app_win __read_mostly = 31;
88int sysctl_tcp_adv_win_scale __read_mostly = 1; 88int sysctl_tcp_adv_win_scale __read_mostly = 1;
89EXPORT_SYMBOL(sysctl_tcp_adv_win_scale); 89EXPORT_SYMBOL(sysctl_tcp_adv_win_scale);
90 90
91/* rfc5961 challenge ack rate limiting */
92int sysctl_tcp_challenge_ack_limit = 100;
93
91int sysctl_tcp_stdurg __read_mostly; 94int sysctl_tcp_stdurg __read_mostly;
92int sysctl_tcp_rfc1337 __read_mostly; 95int sysctl_tcp_rfc1337 __read_mostly;
93int sysctl_tcp_max_orphans __read_mostly = NR_FILE; 96int sysctl_tcp_max_orphans __read_mostly = NR_FILE;
@@ -5247,6 +5250,23 @@ out:
5247} 5250}
5248#endif /* CONFIG_NET_DMA */ 5251#endif /* CONFIG_NET_DMA */
5249 5252
5253static void tcp_send_challenge_ack(struct sock *sk)
5254{
5255 /* unprotected vars, we dont care of overwrites */
5256 static u32 challenge_timestamp;
5257 static unsigned int challenge_count;
5258 u32 now = jiffies / HZ;
5259
5260 if (now != challenge_timestamp) {
5261 challenge_timestamp = now;
5262 challenge_count = 0;
5263 }
5264 if (++challenge_count <= sysctl_tcp_challenge_ack_limit) {
5265 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK);
5266 tcp_send_ack(sk);
5267 }
5268}
5269
5250/* Does PAWS and seqno based validation of an incoming segment, flags will 5270/* Does PAWS and seqno based validation of an incoming segment, flags will
5251 * play significant role here. 5271 * play significant role here.
5252 */ 5272 */
@@ -5283,7 +5303,16 @@ static int tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
5283 5303
5284 /* Step 2: check RST bit */ 5304 /* Step 2: check RST bit */
5285 if (th->rst) { 5305 if (th->rst) {
5286 tcp_reset(sk); 5306 /* RFC 5961 3.2 :
5307 * If sequence number exactly matches RCV.NXT, then
5308 * RESET the connection
5309 * else
5310 * Send a challenge ACK
5311 */
5312 if (TCP_SKB_CB(skb)->seq == tp->rcv_nxt)
5313 tcp_reset(sk);
5314 else
5315 tcp_send_challenge_ack(sk);
5287 goto discard; 5316 goto discard;
5288 } 5317 }
5289 5318