From: John Dykstra <john.dykstra1@gmail.com>
To: Oliver Zheng <mailinglists+netdev@oliverzheng.com>
Cc: netdev@vger.kernel.org, Andi Kleen <andi@firstfloor.org>
Subject: [PATCH net-next-2.6] Re: TCP/IP stack interpretation of acceptable packet
Date: Thu, 19 Mar 2009 00:44:53 +0000 [thread overview]
Message-ID: <1237423493.32009.31.camel@Maple> (raw)
In-Reply-To: <2ff60cd60902241459q1de39054lb3dc5233f13b69c3@mail.gmail.com>
On Tue, 2009-02-24 at 14:59 -0800, Oliver Zheng wrote:
> When a packet is received with the correct
> sequence number but incorrect acknowledgement number (in my tests, it
> was higher than the correct acknowledgement number), the stack accepts
> the packet as a valid packet and passes the data up to the application
TCP's fast path currently accepts segments who ack data that was never
sent. The slow path and processing for states other than ESTABLISHED
discard such segments.
RFC793 says (Section 3.9) that not only should such segments be
discarded, but that an ACK should be sent to the peer. I can't see what
that accomplishes, and it seems to badly interact with fast
retransmit--under some conditions with crafted packets you can get the
two stacks ACKing each other forever. So I left that out of this patch:
[PATCH net-next-2.6] tcp: Discard segments that ack data not yet sent
Discard incoming packets whose ack field iincludes data not yet sent.
This is consistent with RFC 793 Section 3.9.
Change tcp_ack() to distinguish between too-small and too-large ack
field values. Keep segments with too-large ack fields out of the fast
path, and change slow path to discard them.
Reported-by: Oliver Zheng <mailinglists+netdev@oliverzheng.com>
Signed-off-by: John Dykstra <john.dykstra1@gmail.com>
---
net/ipv4/tcp_input.c | 31 +++++++++++++++++++------------
1 files changed, 19 insertions(+), 12 deletions(-)
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index fae78e3..01544cd 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -3587,16 +3587,19 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
u32 prior_fackets;
int prior_packets;
int frto_cwnd = 0;
-
- /* If the ack is newer than sent or older than previous acks
+
+ /* If the ack is older than previous acks
* then we can probably ignore it.
*/
- if (after(ack, tp->snd_nxt))
- goto uninteresting_ack;
-
if (before(ack, prior_snd_una))
goto old_ack;
+ /* If the ack includes data we haven't sent yet, discard
+ * this segment (RFC793 Section 3.9).
+ */
+ if (after(ack, tp->snd_nxt))
+ goto invalid_ack;
+
if (after(ack, prior_snd_una))
flag |= FLAG_SND_UNA_ADVANCED;
@@ -3686,6 +3689,10 @@ no_queue:
tcp_ack_probe(sk);
return 1;
+invalid_ack:
+ SOCK_DEBUG(sk, "Ack %u after %u:%u\n", ack, tp->snd_una, tp->snd_nxt);
+ return -1;
+
old_ack:
if (TCP_SKB_CB(skb)->sacked) {
tcp_sacktag_write_queue(sk, skb, prior_snd_una);
@@ -3693,9 +3700,8 @@ old_ack:
tcp_try_keep_open(sk);
}
-uninteresting_ack:
- SOCK_DEBUG(sk, "Ack %u out of %u:%u\n", ack, tp->snd_una, tp->snd_nxt);
- return 0;
+ SOCK_DEBUG(sk, "Ack %u before %u:%u\n", ack, tp->snd_una, tp->snd_nxt);
+ return 0;
}
/* Look for tcp options. Normally only called on SYN and SYNACK packets.
@@ -5158,7 +5164,8 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
*/
if ((tcp_flag_word(th) & TCP_HP_BITS) == tp->pred_flags &&
- TCP_SKB_CB(skb)->seq == tp->rcv_nxt) {
+ TCP_SKB_CB(skb)->seq == tp->rcv_nxt &&
+ !after(TCP_SKB_CB(skb)->ack_seq, tp->snd_nxt)) {
int tcp_header_len = tp->tcp_header_len;
/* Timestamp header prediction: tcp_header_len
@@ -5311,8 +5318,8 @@ slow_path:
return -res;
step5:
- if (th->ack)
- tcp_ack(sk, skb, FLAG_SLOWPATH);
+ if (th->ack && tcp_ack(sk, skb, FLAG_SLOWPATH) < 0)
+ goto discard;
tcp_rcv_rtt_measure_ts(sk, skb);
@@ -5649,7 +5656,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
/* step 5: check the ACK field */
if (th->ack) {
- int acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH);
+ int acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH) > 0;
switch (sk->sk_state) {
case TCP_SYN_RECV:
--
1.5.4.3
next prev parent reply other threads:[~2009-03-19 0:44 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-02-24 22:59 TCP/IP stack interpretation of acceptable packet Oliver Zheng
2009-02-28 15:50 ` Andi Kleen
2009-03-19 0:44 ` John Dykstra [this message]
2009-03-19 1:47 ` [PATCH net-next-2.6] " Oliver Zheng
2009-03-23 4:50 ` David Miller
2009-03-23 12:28 ` Andi Kleen
2009-03-23 15:13 ` John Dykstra
2009-03-23 18:58 ` David Miller
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1237423493.32009.31.camel@Maple \
--to=john.dykstra1@gmail.com \
--cc=andi@firstfloor.org \
--cc=mailinglists+netdev@oliverzheng.com \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).