diff --git a/src/iosource/Packet.cc b/src/iosource/Packet.cc index c9d697334b..3f038a7115 100644 --- a/src/iosource/Packet.cc +++ b/src/iosource/Packet.cc @@ -144,7 +144,11 @@ RecordValPtr Packet::ToRawPktHdrVal() const { pkt_hdr->Assign(0, std::move(l2_hdr)); - if ( ip_hdr && cap_len >= ip_hdr->TotalLen() && (l3_proto == L3_IPV4 || l3_proto == L3_IPV6) ) + // The cap_len >= ip_hdr->TotalLen() and Reassembled() checks ensure that + // ToPktHdrVal() doesn't access out of bounds memory. For reassembled datagrams, + // cap_len ends up less than the reassembled packets total length. + if ( ip_hdr && (cap_len >= ip_hdr->TotalLen() || ip_hdr->Reassembled()) && + (l3_proto == L3_IPV4 || l3_proto == L3_IPV6) ) // Packet analysis will have stored the IP header in the packet, so we can use // that to build the output. return ip_hdr->ToPktHdrVal(std::move(pkt_hdr), 1); diff --git a/testing/btest/Baseline/bifs.get_current_packet_header_fragmented_syn/output b/testing/btest/Baseline/bifs.get_current_packet_header_fragmented_syn/output new file mode 100644 index 0000000000..11507dc7f1 --- /dev/null +++ b/testing/btest/Baseline/bifs.get_current_packet_header_fragmented_syn/output @@ -0,0 +1,2 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +[l2=[encap=LINK_ETHERNET, len=74, cap_len=50, src=98:ee:cb:bd:07:fe, dst=1e:0b:8b:14:f6:f9, vlan=, inner_vlan=, eth_type=2048, proto=L3_IPV4], ip=[hl=20, tos=0, len=60, id=1, DF=F, MF=T, offset=0, ttl=64, p=6, sum=36538, src=192.168.1.100, dst=10.0.0.5], ip6=, tcp=[sport=12345/tcp, dport=80/tcp, seq=1000, ack=0, hl=40, dl=0, reserved=0, flags=2, win=8192], udp=, icmp=] diff --git a/testing/btest/Traces/ipv4/fragmented-syn.pcap b/testing/btest/Traces/ipv4/fragmented-syn.pcap new file mode 100644 index 0000000000..9637890edb Binary files /dev/null and b/testing/btest/Traces/ipv4/fragmented-syn.pcap differ diff --git a/testing/btest/bifs/get_current_packet_header_fragmented_syn.zeek b/testing/btest/bifs/get_current_packet_header_fragmented_syn.zeek new file mode 100644 index 0000000000..da439c9deb --- /dev/null +++ b/testing/btest/bifs/get_current_packet_header_fragmented_syn.zeek @@ -0,0 +1,10 @@ +# @TEST-DOC: Regression test for #4845, get_current_packet_header() for a fragmented SYN packet +# +# @TEST-EXEC: zeek -b -C -r $TRACES/ipv4/fragmented-syn.pcap %INPUT >output +# @TEST-EXEC: btest-diff output + +event connection_SYN_packet(c: connection, pkt: SYN_packet) + { + local hdr: raw_pkt_hdr = get_current_packet_header(); + print fmt("%s", hdr); + }