On Sat, 31 Mar 2007, [EMAIL PROTECTED] wrote:

> On 3/31/2007, "David Miller" <[EMAIL PROTECTED]> wrote:
> > From: Thomas Graf <[EMAIL PROTECTED]>
> > Date: Sat, 31 Mar 2007 00:10:54 +0200
> > 
> > > * David Miller <[EMAIL PROTECTED]> 2007-03-30 14:43
> > > > Let's not speculate, let's find out for sure if snd_una is
> > > > surpassing high_seq while we're in this state.
> > > >
> > > > Andrew please give this debugging patch a spin, and also what
> > > > is your workload?  I'd like to play with it too.
> > > >
> > > > I've tried to code this patch so that if the bug triggers your
> > > > machine shouldn't crash and burn completely, just spit out the
> > > > log message.
> > >
> > > I'm running into the same bug as Andew, i was able to reproduce
> > > using Dave's patch within minutes:
> > >
> > > TCP BUG: high_seq==NULL [c3c9cc54] q[c3c94edc] t[c3c9cc54]
> > >
> > > The after(snd_una, high_seq) check is not triggered.
> > 
> > So tp->high_seq points to the tail packet end sequence.
> > 
> > Ilpo does this clear things up?
> 
> Thanks for the info.
> 
> I think that the if condition before the write_queue_find should check if
> skb is valid before doing after(TCP_SKB_CB(skb)->seq, tp->high_seq), it
> is pointing to sk_write_queue rather than a valid skb when the previous
> loop exits (there might be a similar problem later in the code too). I
> apologize I cannot provide a good patch at this point of time because I
> moved on Thursday and the ISP hasn't yet activated the access link
> (writing this from a library machine).

So here it is, finally, I'm sorry for the delay (the length of the 
lines this fix is causing does not please me though)...:

[PATCH] [TCP]: Fix invalid skb referencing in LOST marker code

The after() referenced an invalid skb if loop exited when skb had
reached sk_write_queue. I chose to move this part inside the loop
where the skb is valid (so no need to check for that like I first
suggested), which also allows dropping of couple of conditions
from the if.

Signed-off-by: Ilpo Järvinen <[EMAIL PROTECTED]>
---
 net/ipv4/tcp_input.c |   25 ++++++++++++-------------
 1 files changed, 12 insertions(+), 13 deletions(-)

diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index ea196de..211bb1f 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1933,26 +1933,25 @@ static void tcp_update_scoreboard_fack(s
                                if (IsFack(tp) ||
                                    (TCP_SKB_CB(skb)->sacked & 
TCPCB_SACKED_ACKED))
                                        reord_count += tcp_skb_pcount(skb);
-                               if (reord_count > tp->reordering)
+                               if (reord_count > tp->reordering) {
+                                       if (after(TCP_SKB_CB(skb)->seq, 
tp->high_seq)) {
+                                               /* RFC: should we have 
find_below? */
+                                               skb = tcp_write_queue_find(sk, 
tp->high_seq);
+                                               not_marked_skb = skb;
+                                               skb = tcp_write_queue_prev(sk, 
skb);
+                                               /* Timedout top is again 
uncertain? */
+                                               if (tcp_skb_timedout(sk, skb))
+                                                       timedout_continue = 1;
+                                       }
+                                       /* TODO?: do skb fragmentation if 
necessary */
                                        break;
+                               }
 
                                if (!(TCP_SKB_CB(skb)->sacked & 
TCPCB_SACKED_ACKED))
                                        holes_seen += tcp_skb_pcount(skb);
                        }
                }
 
-               if ((!IsFack(tp) || !tcp_skb_timedout(sk, skb)) &&
-                   after(TCP_SKB_CB(skb)->seq, tp->high_seq)) {
-                       /* RFC: should we have find_below? */
-                       skb = tcp_write_queue_find(sk, tp->high_seq);
-                       not_marked_skb = skb;
-                       skb = tcp_write_queue_prev(sk, skb);
-                       /* Timedout top is again uncertain? */
-                       if (tcp_skb_timedout(sk, skb))
-                               timedout_continue = 1;
-               }
-               /* RFC: ...else if (!tcp_skb_timedout) do skb fragmentation? */
-
                /* Phase II: Marker */
                tcp_for_write_queue_backwards_from(skb, sk) {
                        if ((tp->fackets_out <= tp->sacked_out + tp->lost_out +
-- 
1.4.2

Reply via email to