]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
defrag: don't crash when out of memory
authorVictor Julien <victor@inliniac.net>
Wed, 3 Dec 2014 15:07:00 +0000 (16:07 +0100)
committerVictor Julien <victor@inliniac.net>
Fri, 5 Dec 2014 09:01:17 +0000 (10:01 +0100)
Handle memory allocation errors in defrag better. Could lead to
crashes if malloc errors happened.

src/defrag.c

index 7d38dec1c9e5d570a4d28d24ec7c1b8b7666d6d3..71225b8da9f39c26988e9be766fe0a0f8d9d03c7 100644 (file)
@@ -291,7 +291,7 @@ Defrag4Reassemble(ThreadVars *tv, DefragTracker *tracker, Packet *p)
     if (rp == NULL) {
         SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate packet for "
                    "fragmentation re-assembly, dumping fragments.");
-        goto remove_tracker;
+        goto error_remove_tracker;
     }
     PKT_SET_SRC(rp, PKT_SRC_DEFRAG);
     rp->recursion_level = p->recursion_level;
@@ -311,7 +311,7 @@ Defrag4Reassemble(ThreadVars *tv, DefragTracker *tracker, Packet *p)
         if (frag->offset == 0) {
 
             if (PacketCopyData(rp, frag->pkt, frag->len) == -1)
-                goto remove_tracker;
+                goto error_remove_tracker;
 
             hlen = frag->hlen;
             ip_hdr_offset = frag->ip_hdr_offset;
@@ -327,12 +327,12 @@ Defrag4Reassemble(ThreadVars *tv, DefragTracker *tracker, Packet *p)
             if (pkt_end > (int)MAX_PAYLOAD_SIZE) {
                 SCLogWarning(SC_ERR_REASSEMBLY, "Failed re-assemble "
                         "fragmented packet, exceeds size of packet buffer.");
-                goto remove_tracker;
+                goto error_remove_tracker;
             }
             if (PacketCopyDataOffset(rp, fragmentable_offset + frag->offset + frag->ltrim,
                 frag->pkt + frag->data_offset + frag->ltrim,
                 frag->data_len - frag->ltrim) == -1) {
-                goto remove_tracker;
+                goto error_remove_tracker;
             }
             if (frag->offset + frag->data_len > fragmentable_len)
                 fragmentable_len = frag->offset + frag->data_len;
@@ -350,12 +350,16 @@ Defrag4Reassemble(ThreadVars *tv, DefragTracker *tracker, Packet *p)
         old, rp->ip4h->ip_len + rp->ip4h->ip_off);
     SET_PKT_LEN(rp, ip_hdr_offset + hlen + fragmentable_len);
 
-remove_tracker:
-    /** \todo check locking */
     tracker->remove = 1;
     DefragTrackerFreeFrags(tracker);
 done:
     return rp;
+
+error_remove_tracker:
+    tracker->remove = 1;
+    DefragTrackerFreeFrags(tracker);
+    PacketFreeOrRelease(rp);
+    return NULL;
 }
 
 /**
@@ -405,7 +409,7 @@ Defrag6Reassemble(ThreadVars *tv, DefragTracker *tracker, Packet *p)
     if (rp == NULL) {
         SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate packet for "
                 "fragmentation re-assembly, dumping fragments.");
-        goto remove_tracker;
+        goto error_remove_tracker;
     }
     PKT_SET_SRC(rp, PKT_SRC_DEFRAG);
 
@@ -428,11 +432,11 @@ Defrag6Reassemble(ThreadVars *tv, DefragTracker *tracker, Packet *p)
              * IPv6 headers. We also copy in its data, but remove the
              * fragmentation header. */
             if (PacketCopyData(rp, frag->pkt, frag->frag_hdr_offset) == -1)
-                goto remove_tracker;
+                goto error_remove_tracker;
             if (PacketCopyDataOffset(rp, frag->frag_hdr_offset,
                 frag->pkt + frag->frag_hdr_offset + sizeof(IPV6FragHdr),
                 frag->data_len) == -1)
-                goto remove_tracker;
+                goto error_remove_tracker;
             ip_hdr_offset = frag->ip_hdr_offset;
 
             /* This is the start of the fragmentable portion of the
@@ -445,13 +449,13 @@ Defrag6Reassemble(ThreadVars *tv, DefragTracker *tracker, Packet *p)
              * and the frag header. */
             unfragmentable_len = (fragmentable_offset - ip_hdr_offset) - IPV6_HEADER_LEN;
             if (unfragmentable_len >= fragmentable_offset)
-                goto remove_tracker;
+                goto error_remove_tracker;
         }
         else {
             if (PacketCopyDataOffset(rp, fragmentable_offset + frag->offset + frag->ltrim,
                 frag->pkt + frag->data_offset + frag->ltrim,
                 frag->data_len - frag->ltrim) == -1)
-                goto remove_tracker;
+                goto error_remove_tracker;
             if (frag->offset + frag->data_len > fragmentable_len)
                 fragmentable_len = frag->offset + frag->data_len;
         }
@@ -468,12 +472,16 @@ Defrag6Reassemble(ThreadVars *tv, DefragTracker *tracker, Packet *p)
     SET_PKT_LEN(rp, ip_hdr_offset + sizeof(IPV6Hdr) +
             unfragmentable_len + fragmentable_len);
 
-remove_tracker:
-    /** \todo check locking */
     tracker->remove = 1;
     DefragTrackerFreeFrags(tracker);
 done:
     return rp;
+
+error_remove_tracker:
+    tracker->remove = 1;
+    DefragTrackerFreeFrags(tracker);
+    PacketFreeOrRelease(rp);
+    return NULL;
 }
 
 /**