aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2012-07-16 21:41:30 -0400
committerDavid S. Miller <davem@davemloft.net>2012-07-17 10:40:46 -0400
commit0c24604b68fc7810d429d6c3657b6f148270e528 (patch)
treef5dd9deb10cfbcf8742483ecda7d07899ccb57f9 /net
parent5f3600ebe252aa5fe782e9f9115c66c639f62ac0 (diff)
tcp: implement RFC 5961 4.2
Implement the RFC 5691 mitigation against Blind Reset attack using SYN bit. Section 4.2 of RFC 5961 advises to send a Challenge ACK and drop incoming packet, instead of resetting the session. Add a new SNMP counter to count number of challenge acks sent in response to SYN packets. (netstat -s | grep TCPSYNChallenge) Remove obsolete TCPAbortOnSyn, since we no longer abort a TCP session because of a SYN flag. 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')
-rw-r--r--net/ipv4/proc.c2
-rw-r--r--net/ipv4/tcp_input.c32
2 files changed, 16 insertions, 18 deletions
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index 3e8e78f12a38..2a5240b2ea61 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -232,7 +232,6 @@ static const struct snmp_mib snmp4_net_list[] = {
232 SNMP_MIB_ITEM("TCPDSACKOfoSent", LINUX_MIB_TCPDSACKOFOSENT), 232 SNMP_MIB_ITEM("TCPDSACKOfoSent", LINUX_MIB_TCPDSACKOFOSENT),
233 SNMP_MIB_ITEM("TCPDSACKRecv", LINUX_MIB_TCPDSACKRECV), 233 SNMP_MIB_ITEM("TCPDSACKRecv", LINUX_MIB_TCPDSACKRECV),
234 SNMP_MIB_ITEM("TCPDSACKOfoRecv", LINUX_MIB_TCPDSACKOFORECV), 234 SNMP_MIB_ITEM("TCPDSACKOfoRecv", LINUX_MIB_TCPDSACKOFORECV),
235 SNMP_MIB_ITEM("TCPAbortOnSyn", LINUX_MIB_TCPABORTONSYN),
236 SNMP_MIB_ITEM("TCPAbortOnData", LINUX_MIB_TCPABORTONDATA), 235 SNMP_MIB_ITEM("TCPAbortOnData", LINUX_MIB_TCPABORTONDATA),
237 SNMP_MIB_ITEM("TCPAbortOnClose", LINUX_MIB_TCPABORTONCLOSE), 236 SNMP_MIB_ITEM("TCPAbortOnClose", LINUX_MIB_TCPABORTONCLOSE),
238 SNMP_MIB_ITEM("TCPAbortOnMemory", LINUX_MIB_TCPABORTONMEMORY), 237 SNMP_MIB_ITEM("TCPAbortOnMemory", LINUX_MIB_TCPABORTONMEMORY),
@@ -262,6 +261,7 @@ static const struct snmp_mib snmp4_net_list[] = {
262 SNMP_MIB_ITEM("TCPOFODrop", LINUX_MIB_TCPOFODROP), 261 SNMP_MIB_ITEM("TCPOFODrop", LINUX_MIB_TCPOFODROP),
263 SNMP_MIB_ITEM("TCPOFOMerge", LINUX_MIB_TCPOFOMERGE), 262 SNMP_MIB_ITEM("TCPOFOMerge", LINUX_MIB_TCPOFOMERGE),
264 SNMP_MIB_ITEM("TCPChallengeACK", LINUX_MIB_TCPCHALLENGEACK), 263 SNMP_MIB_ITEM("TCPChallengeACK", LINUX_MIB_TCPCHALLENGEACK),
264 SNMP_MIB_ITEM("TCPSYNChallenge", LINUX_MIB_TCPSYNCHALLENGE),
265 SNMP_MIB_SENTINEL 265 SNMP_MIB_SENTINEL
266}; 266};
267 267
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index c841a8990377..8aaec5536111 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -5270,8 +5270,8 @@ static void tcp_send_challenge_ack(struct sock *sk)
5270/* 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
5271 * play significant role here. 5271 * play significant role here.
5272 */ 5272 */
5273static int tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, 5273static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
5274 const struct tcphdr *th, int syn_inerr) 5274 const struct tcphdr *th, int syn_inerr)
5275{ 5275{
5276 const u8 *hash_location; 5276 const u8 *hash_location;
5277 struct tcp_sock *tp = tcp_sk(sk); 5277 struct tcp_sock *tp = tcp_sk(sk);
@@ -5323,20 +5323,22 @@ static int tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
5323 5323
5324 /* step 3: check security and precedence [ignored] */ 5324 /* step 3: check security and precedence [ignored] */
5325 5325
5326 /* step 4: Check for a SYN in window. */ 5326 /* step 4: Check for a SYN
5327 if (th->syn && !before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) { 5327 * RFC 5691 4.2 : Send a challenge ack
5328 */
5329 if (th->syn) {
5328 if (syn_inerr) 5330 if (syn_inerr)
5329 TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS); 5331 TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS);
5330 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONSYN); 5332 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSYNCHALLENGE);
5331 tcp_reset(sk); 5333 tcp_send_challenge_ack(sk);
5332 return -1; 5334 goto discard;
5333 } 5335 }
5334 5336
5335 return 1; 5337 return true;
5336 5338
5337discard: 5339discard:
5338 __kfree_skb(skb); 5340 __kfree_skb(skb);
5339 return 0; 5341 return false;
5340} 5342}
5341 5343
5342/* 5344/*
@@ -5366,7 +5368,6 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
5366 const struct tcphdr *th, unsigned int len) 5368 const struct tcphdr *th, unsigned int len)
5367{ 5369{
5368 struct tcp_sock *tp = tcp_sk(sk); 5370 struct tcp_sock *tp = tcp_sk(sk);
5369 int res;
5370 5371
5371 if (sk->sk_rx_dst) { 5372 if (sk->sk_rx_dst) {
5372 struct dst_entry *dst = sk->sk_rx_dst; 5373 struct dst_entry *dst = sk->sk_rx_dst;
@@ -5555,9 +5556,8 @@ slow_path:
5555 * Standard slow path. 5556 * Standard slow path.
5556 */ 5557 */
5557 5558
5558 res = tcp_validate_incoming(sk, skb, th, 1); 5559 if (!tcp_validate_incoming(sk, skb, th, 1))
5559 if (res <= 0) 5560 return 0;
5560 return -res;
5561 5561
5562step5: 5562step5:
5563 if (th->ack && tcp_ack(sk, skb, FLAG_SLOWPATH) < 0) 5563 if (th->ack && tcp_ack(sk, skb, FLAG_SLOWPATH) < 0)
@@ -5877,7 +5877,6 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
5877 struct tcp_sock *tp = tcp_sk(sk); 5877 struct tcp_sock *tp = tcp_sk(sk);
5878 struct inet_connection_sock *icsk = inet_csk(sk); 5878 struct inet_connection_sock *icsk = inet_csk(sk);
5879 int queued = 0; 5879 int queued = 0;
5880 int res;
5881 5880
5882 tp->rx_opt.saw_tstamp = 0; 5881 tp->rx_opt.saw_tstamp = 0;
5883 5882
@@ -5932,9 +5931,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
5932 return 0; 5931 return 0;
5933 } 5932 }
5934 5933
5935 res = tcp_validate_incoming(sk, skb, th, 0); 5934 if (!tcp_validate_incoming(sk, skb, th, 0))
5936 if (res <= 0) 5935 return 0;
5937 return -res;
5938 5936
5939 /* step 5: check the ACK field */ 5937 /* step 5: check the ACK field */
5940 if (th->ack) { 5938 if (th->ack) {