stream memory leaks fixed and unit tests added

remotes/origin/master-1.0.x
Gurvinder Singh 16 years ago committed by Victor Julien
parent 90006d94a6
commit 7438f981da

@ -726,6 +726,71 @@ static int HandleSegmentStartsBeforeListSegment(TcpStream *stream,
list_seg = new_seg;
return_after = TRUE;
}
/* Handle the case, when list_seg is the end of segment list, but
seg is ending after the list_seg. So we need to copy the data
from newly received segment. After copying return the newly
received seg to pool */
} else {
if (SEQ_GT(seg->seq, (list_seg->prev->seq +
list_seg->prev->payload_len)))
{
packet_length = list_seg->payload_len + (list_seg->seq -
seg->seq);
} else {
packet_length = list_seg->payload_len + (list_seg->seq -
(list_seg->prev->seq +
list_seg->prev->payload_len));
}
packet_length += (seg->seq + seg->payload_len) -
(list_seg->seq + list_seg->payload_len);
TcpSegment *new_seg = StreamTcpGetSegment(packet_length);
if (new_seg == NULL) {
SCLogDebug("segment_pool[%"PRIu16"] is empty",
segment_pool_idx[packet_length]);
SCReturnInt(-1);
}
new_seg->payload_len = packet_length;
if (SEQ_GT((list_seg->prev->seq +
list_seg->prev->payload_len), seg->seq))
{
new_seg->seq = (list_seg->prev->seq +
list_seg->prev->payload_len);
} else {
new_seg->seq = seg->seq;
}
SCLogDebug("new_seg->seq %"PRIu32" and new->payload_len "
"%" PRIu16"", new_seg->seq, new_seg->payload_len);
new_seg->next = list_seg->next;
new_seg->prev = list_seg->prev;
/* create a new seg, copy the list_seg data over */
StreamTcpSegmentDataCopy(new_seg, list_seg);
/* copy the part before list_seg */
uint16_t copy_len = list_seg->seq - new_seg->seq;
StreamTcpSegmentDataReplace(new_seg, seg, new_seg->seq,
copy_len);
/* copy the part after list_seg */
copy_len = (seg->seq + seg->payload_len) -
(list_seg->seq + list_seg->payload_len);
StreamTcpSegmentDataReplace(new_seg, seg, (list_seg->seq +
list_seg->payload_len), copy_len);
if (new_seg->prev != NULL) {
new_seg->prev->next = new_seg;
}
/*update the stream last_seg in case of removal of list_seg*/
if (stream->seg_list_tail == list_seg)
stream->seg_list_tail = new_seg;
StreamTcpSegmentReturntoPool(list_seg);
list_seg = new_seg;
return_after = TRUE;
}
}
@ -865,6 +930,12 @@ static int HandleSegmentStartsAtSameListSegment(TcpStream *stream,
{
handle_beyond = TRUE;
}
/* Handle the case, when list_seg is the end of segment list, but
seg is ending after the list_seg. So we need to copy the data
from newly received segment. After copying return the newly
received seg to pool */
} else {
fill_gap = TRUE;
}
SCLogDebug("fill_gap %s, handle_beyond %s", fill_gap?"TRUE":"FALSE",

@ -5135,6 +5135,173 @@ end:
ConfRestoreContextBackup();
return ret;
}
/** \test Test the stream mem leaks conditions. */
static int StreamTcpTest23(void)
{
TcpSession ssn;
Packet p;
Flow f;
TCPHdr tcph;
TcpReassemblyThreadCtx *ra_ctx = StreamTcpReassembleInitThreadCtx();
TcpStream stream;
memset(&stream, 0, sizeof (TcpStream));
stream.os_policy = OS_POLICY_BSD;
uint8_t packet[1460] = "";
int result = 1;
StreamTcpInitConfig(TRUE);
/* prevent L7 from kicking in */
StreamMsgQueueSetMinInitChunkLen(FLOW_PKT_TOSERVER, 4096);
StreamMsgQueueSetMinInitChunkLen(FLOW_PKT_TOCLIENT, 4096);
StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOSERVER, 4096);
StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOCLIENT, 4096);
memset(&ssn, 0, sizeof (TcpSession));
memset(&p, 0, sizeof (Packet));
memset(&f, 0, sizeof (Flow));
memset(&tcph, 0, sizeof (TCPHdr));
f.protoctx = &ssn;
p.src.family = AF_INET;
p.dst.family = AF_INET;
p.proto = IPPROTO_TCP;
p.flow = &f;
tcph.th_win = 5480;
tcph.th_flags = TH_PUSH | TH_ACK;
p.tcph = &tcph;
p.flowflags = FLOW_PKT_TOSERVER;
p.payload = packet;
p.tcph->th_seq = htonl(3184324453UL);
p.tcph->th_ack = htonl(3373419609UL);
p.payload_len = 2;
if (StreamTcpReassembleHandleSegment(ra_ctx,&ssn, &stream, &p) == -1) {
printf("failed in segment reassmebling\n");
result &= 0;
goto end;
}
p.tcph->th_seq = htonl(3184324455UL);
p.tcph->th_ack = htonl(3373419621UL);
p.payload_len = 2;
if (StreamTcpReassembleHandleSegment(ra_ctx,&ssn, &stream, &p) == -1) {
printf("failed in segment reassmebling\n");
result &= 0;
goto end;
}
p.tcph->th_seq = htonl(3184324453UL);
p.tcph->th_ack = htonl(3373419621UL);
p.payload_len = 6;
if (StreamTcpReassembleHandleSegment(ra_ctx,&ssn, &stream, &p) == -1) {
printf("failed in segment reassmebling\n");
result &= 0;
goto end;
}
if(stream.seg_list_tail->payload_len != 4) {
printf("failed in segment reassmebling\n");
result &= 0;
}
end:
StreamTcpReturnStreamSegments(&stream);
StreamTcpFreeConfig(TRUE);
if (stream_memuse == 0) {
result &= 1;
} else {
printf("stream_memuse %"PRIu32"\n", stream_memuse);
}
return result;
}
/** \test Test the stream mem leaks conditions. */
static int StreamTcpTest24(void)
{
TcpSession ssn;
Packet p;
Flow f;
TCPHdr tcph;
TcpReassemblyThreadCtx *ra_ctx = StreamTcpReassembleInitThreadCtx();
TcpStream stream;
memset(&stream, 0, sizeof (TcpStream));
stream.os_policy = OS_POLICY_BSD;
uint8_t packet[1460] = "";
int result = 1;
StreamTcpInitConfig(TRUE);
/* prevent L7 from kicking in */
StreamMsgQueueSetMinInitChunkLen(FLOW_PKT_TOSERVER, 4096);
StreamMsgQueueSetMinInitChunkLen(FLOW_PKT_TOCLIENT, 4096);
StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOSERVER, 4096);
StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOCLIENT, 4096);
memset(&ssn, 0, sizeof (TcpSession));
memset(&p, 0, sizeof (Packet));
memset(&f, 0, sizeof (Flow));
memset(&tcph, 0, sizeof (TCPHdr));
f.protoctx = &ssn;
p.src.family = AF_INET;
p.dst.family = AF_INET;
p.proto = IPPROTO_TCP;
p.flow = &f;
tcph.th_win = 5480;
tcph.th_flags = TH_PUSH | TH_ACK;
p.tcph = &tcph;
p.flowflags = FLOW_PKT_TOSERVER;
p.payload = packet;
p.tcph->th_seq = htonl(3184324455UL);
p.tcph->th_ack = htonl(3373419621UL);
p.payload_len = 4;
if (StreamTcpReassembleHandleSegment(ra_ctx,&ssn, &stream, &p) == -1) {
printf("failed in segment reassmebling\n");
result &= 0;
goto end;
}
p.tcph->th_seq = htonl(3184324459UL);
p.tcph->th_ack = htonl(3373419633UL);
p.payload_len = 2;
if (StreamTcpReassembleHandleSegment(ra_ctx,&ssn, &stream, &p) == -1) {
printf("failed in segment reassmebling\n");
result &= 0;
goto end;
}
p.tcph->th_seq = htonl(3184324459UL);
p.tcph->th_ack = htonl(3373419657UL);
p.payload_len = 4;
if (StreamTcpReassembleHandleSegment(ra_ctx,&ssn, &stream, &p) == -1) {
printf("failed in segment reassmebling\n");
result &= 0;
goto end;
}
if(stream.seg_list_tail->payload_len != 2) {
printf("failed in segment reassmebling\n");
result &= 0;
}
end:
StreamTcpReturnStreamSegments(&stream);
StreamTcpFreeConfig(TRUE);
if (stream_memuse == 0) {
result &= 1;
} else {
printf("stream_memuse %"PRIu32"\n", stream_memuse);
}
return result;
}
#endif /* UNITTESTS */
void StreamTcpRegisterTests (void) {
@ -5177,6 +5344,8 @@ void StreamTcpRegisterTests (void) {
UtRegisterTest("StreamTcpTest20 -- setup OS policy", StreamTcpTest20, 1);
UtRegisterTest("StreamTcpTest21 -- setup OS policy", StreamTcpTest21, 1);
UtRegisterTest("StreamTcpTest22 -- setup OS policy", StreamTcpTest22, 1);
UtRegisterTest("StreamTcpTest23 -- stream memory leaks", StreamTcpTest23, 1);
UtRegisterTest("StreamTcpTest24 -- stream memory leaks", StreamTcpTest24, 1);
/* set up the reassembly tests as well */
StreamTcpReassembleRegisterTests();
#endif /* UNITTESTS */

@ -227,11 +227,21 @@ static inline int SCClassConfAddClasstype(char *rawstr, DetectEngineCtx *de_ctx)
SCLogDebug("HashTable Add failed");
} else {
SCLogDebug("Duplicate classtype found inside classification.config");
if (ct_new->classtype_desc) free(ct_new->classtype_desc);
if (ct_new->classtype) free (ct_new->classtype);
free(ct_new);
}
if (ct_name) free((char *)ct_name);
if (ct_desc) free((char *)ct_desc);
if (ct_priority_str) free((char *)ct_priority_str);
return 0;
error:
if (ct_name) free((char *)ct_name);
if (ct_desc) free((char *)ct_desc);
if (ct_priority_str) free((char *)ct_priority_str);
return -1;
}

Loading…
Cancel
Save