aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_input.c
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2012-12-26 07:44:34 -0500
committerDavid S. Miller <davem@davemloft.net>2012-12-26 18:08:55 -0500
commitc3ae62af8e755ea68380fb5ce682e60079a4c388 (patch)
treeef786563e00bac6b58b96cc7f0ebbaf487982fa6 /net/ipv4/tcp_input.c
parent3d0dcfbd8fa2a1e63fabb5f8edac8b8a27860d98 (diff)
tcp: should drop incoming frames without ACK flag set
In commit 96e0bf4b5193d (tcp: Discard segments that ack data not yet sent) John Dykstra enforced a check against ack sequences. In commit 354e4aa391ed5 (tcp: RFC 5961 5.2 Blind Data Injection Attack Mitigation) I added more safety tests. But we missed fact that these tests are not performed if ACK bit is not set. RFC 793 3.9 mandates TCP should drop a frame without ACK flag set. " fifth check the ACK field, if the ACK bit is off drop the segment and return" Not doing so permits an attacker to only guess an acceptable sequence number, evading stronger checks. Many thanks to Zhiyun Qian for bringing this issue to our attention. See : http://web.eecs.umich.edu/~zhiyunq/pub/ccs12_TCP_sequence_number_inference.pdf Reported-by: Zhiyun Qian <zhiyunq@umich.edu> Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Nandita Dukkipati <nanditad@google.com> Cc: Neal Cardwell <ncardwell@google.com> Cc: John Dykstra <john.dykstra1@gmail.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.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index a13692560e63..a28e4db8a952 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -5543,6 +5543,9 @@ slow_path:
5543 if (len < (th->doff << 2) || tcp_checksum_complete_user(sk, skb)) 5543 if (len < (th->doff << 2) || tcp_checksum_complete_user(sk, skb))
5544 goto csum_error; 5544 goto csum_error;
5545 5545
5546 if (!th->ack)
5547 goto discard;
5548
5546 /* 5549 /*
5547 * Standard slow path. 5550 * Standard slow path.
5548 */ 5551 */
@@ -5551,7 +5554,7 @@ slow_path:
5551 return 0; 5554 return 0;
5552 5555
5553step5: 5556step5:
5554 if (th->ack && tcp_ack(sk, skb, FLAG_SLOWPATH) < 0) 5557 if (tcp_ack(sk, skb, FLAG_SLOWPATH) < 0)
5555 goto discard; 5558 goto discard;
5556 5559
5557 /* ts_recent update must be made after we are sure that the packet 5560 /* ts_recent update must be made after we are sure that the packet
@@ -5984,11 +5987,15 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
5984 if (tcp_check_req(sk, skb, req, NULL, true) == NULL) 5987 if (tcp_check_req(sk, skb, req, NULL, true) == NULL)
5985 goto discard; 5988 goto discard;
5986 } 5989 }
5990
5991 if (!th->ack)
5992 goto discard;
5993
5987 if (!tcp_validate_incoming(sk, skb, th, 0)) 5994 if (!tcp_validate_incoming(sk, skb, th, 0))
5988 return 0; 5995 return 0;
5989 5996
5990 /* step 5: check the ACK field */ 5997 /* step 5: check the ACK field */
5991 if (th->ack) { 5998 if (true) {
5992 int acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH) > 0; 5999 int acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH) > 0;
5993 6000
5994 switch (sk->sk_state) { 6001 switch (sk->sk_state) {
@@ -6138,8 +6145,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
6138 } 6145 }
6139 break; 6146 break;
6140 } 6147 }
6141 } else 6148 }
6142 goto discard;
6143 6149
6144 /* ts_recent update must be made after we are sure that the packet 6150 /* ts_recent update must be made after we are sure that the packet
6145 * is in window. 6151 * is in window.