]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
sctp: Fix SKB list traversal in sctp_intl_store_reasm().
authorDavid S. Miller <davem@davemloft.net>
Sun, 11 Nov 2018 03:28:27 +0000 (19:28 -0800)
committerDavid S. Miller <davem@davemloft.net>
Sun, 11 Nov 2018 03:28:27 +0000 (19:28 -0800)
To be fully correct, an iterator has an undefined value when something
like skb_queue_walk() naturally terminates.

This will actually matter when SKB queues are converted over to
list_head.

Formalize what this code ends up doing with the current
implementation.

Signed-off-by: David S. Miller <davem@davemloft.net>
net/sctp/stream_interleave.c

index 0a78cdf864633eb68af1520fe5e09484dd8ef76f..368d9c33fde1013366241c73078c4ae844154d32 100644 (file)
@@ -140,7 +140,7 @@ static void sctp_intl_store_reasm(struct sctp_ulpq *ulpq,
                                  struct sctp_ulpevent *event)
 {
        struct sctp_ulpevent *cevent;
-       struct sk_buff *pos;
+       struct sk_buff *pos, *loc;
 
        pos = skb_peek_tail(&ulpq->reasm);
        if (!pos) {
@@ -166,23 +166,30 @@ static void sctp_intl_store_reasm(struct sctp_ulpq *ulpq,
                return;
        }
 
+       loc = NULL;
        skb_queue_walk(&ulpq->reasm, pos) {
                cevent = sctp_skb2event(pos);
 
                if (event->stream < cevent->stream ||
                    (event->stream == cevent->stream &&
-                    MID_lt(event->mid, cevent->mid)))
+                    MID_lt(event->mid, cevent->mid))) {
+                       loc = pos;
                        break;
-
+               }
                if (event->stream == cevent->stream &&
                    event->mid == cevent->mid &&
                    !(cevent->msg_flags & SCTP_DATA_FIRST_FRAG) &&
                    (event->msg_flags & SCTP_DATA_FIRST_FRAG ||
-                    event->fsn < cevent->fsn))
+                    event->fsn < cevent->fsn)) {
+                       loc = pos;
                        break;
+               }
        }
 
-       __skb_queue_before(&ulpq->reasm, pos, sctp_event2skb(event));
+       if (!loc)
+               __skb_queue_tail(&ulpq->reasm, sctp_event2skb(event));
+       else
+               __skb_queue_before(&ulpq->reasm, loc, sctp_event2skb(event));
 }
 
 static struct sctp_ulpevent *sctp_intl_retrieve_partial(