Segmentation fault with dns-anonymizer

Hi,

I'm trying to anonymize a DNS trace while running bro 1.5.1 and get a
segmentation fault while running

bro -r trace.pcap dns-anonymizer.bro -w output.pcap

The segmentation fault results in this back trace:

#0 0x000000000064c474 in __ns_name_pack ()
#1 0x000000000064cd32 in __ns_name_compress ()
#2 0x00000000005d5ae8 in DNS_Rewriter::DnsCopyQuery (this=0x2830fb0,
query=0x2834c40, qtype=6, qclass=1)
    at DNS_Rewriter.cc:100
#3 0x000000000045e713 in bro_rewrite_dns_reply_question
(frame=0x2825f20, BiF_ARGS=0x2832440) at dns-rw.bif:23
#4 0x00000000004daaa7 in BuiltinFunc::Call (this=0x22c0050,
args=0x2832440, parent=0x2825f20) at Func.cc:451
#5 0x00000000004a5081 in CallExpr::Eval (this=0x276e6d0, f=0x2825f20)
at Expr.cc:4629
#6 0x000000000058618f in ExprStmt::Exec (this=0x276e770, f=0x2825f20,
flow=@0x7fff72d90aa4) at Stmt.cc:397
#7 0x000000000058723a in StmtList::Exec (this=0x276dba0, f=0x2825f20,
flow=@0x7fff72d90aa4) at Stmt.cc:1432
#8 0x00000000004e1ea0 in BroFunc::Call (this=0x2645ee0,
args=0x282fec0, parent=0x0) at Func.cc:308
#9 0x0000000000485a0d in EventHandler::Call (this=0x2123a40,
vl=0x282fec0, no_remote=false) at EventHandler.cc:67
#10 0x000000000040c835 in Event::Dispatch (this=0x2833810,
no_remote=false) at Event.h:43
#11 0x0000000000485439 in EventMgr::Dispatch (this=0x95b760) at Event.cc:107
#12 0x00000000004854a6 in EventMgr::Drain (this=0x95b760) at Event.cc:119
#13 0x000000000051aa68 in net_packet_dispatch (t=1275291343.0222969,
hdr=0x22c1fe0, pkt=0x276e812 "", hdr_size=14,
    src_ps=0x22c1fa0, pkt_elem=0x0) at Net.cc:436
#14 0x000000000051acb5 in net_packet_arrival (t=1275291343.0222969,
hdr=0x22c1fe0, pkt=0x276e812 "", hdr_size=14,
    src_ps=0x22c1fa0) at Net.cc:498
#15 0x000000000052e198 in PktSrc::Process (this=0x22c1fa0) at PktSrc.cc:199
#16 0x000000000051adf1 in net_run () at Net.cc:528
#17 0x000000000040a4df in main (argc=6, argv=0x7fff72d915c8) at main.cc:999

The crash happens within dn_comp in

len = dn_comp(dname, pkt + pkt_size, DNS_PKT_SIZE - pkt_size, dn_ptrs,
last_dn_ptr);

at some point within the trace. This does not happen on the first DNS
packet in the trace, but somewhere in the middle.
Hence, there where successful calls to DNS_Rewriter::DnsCopyQuery()
before the segmentation fault.

I tried to debug the issue and found that the crash is probably due to
uninitialized variables dn_ptrs and last_dn_ptr. Digging deeper into
the problem, I found that the DNS_Rewriter object (this = 0x2830fb0)
has never been initialized (the constructor of that object has never
been called).

Is this a known problem? I could not find any issue at the bug tracker
that seems to be related.

Can someone give me a hint on how to further debug the problem?

Best regards,
  Lothar

Hi again,

replying to my own message: I found the reason for the segmentation fault.

The problem is that my trace contains DNS traffic that is sent over TCP.
DNS.cc creates a DNS_Rewriter for DNS over UDP only. Hence, all DNS
traffic over TCP will be rewritten by a TCP_Rewriter object, which is
created in TCP.cc, TCP_Analyzer::Init()

The problem kicks in because Bro correctly identifies the DNS traffic
within the TCP connection and therefore tries to rewrite them with
bro_rewrite_dns_reply_question()

bro_rewrite_dns_reply_question() gets the rewriter object, checks if
the object is valid:
and then casts the Rewriter into a DNS_Rewriter. This is an error
because the Rewriter is a TCP_Rewriter instead of a DNS_Rewriter,
leading to the segmentation fault that I described yesterday when
DNS_Rewriter::DnsCopyQuery() is called.

Is DNS_Rewriter able to correctly rewrite DNS traffic in TCP packets
and can it be created in DNS.cc for TCP, too?

If the rewriter is not able to handle TCP packets, the methods in
dns-rw.bif could be changed from

        DNS_Rewriter* dnsrewriter = ((DNS_Rewriter*) @TRACE@);
        dnsrewriter->DnsCopyCNAME(ans, name->AsString());

to something like this

        DNS_Rewriter* dnsrewriter = dynamic_cast<DNS_Rewriter*>(@TRACE@);
        if (!dnsrewriter) {
                printf("No suitable rewriter for this kind of DNS traffic!\n");
                return NULL;
        }

This inhibits Bro from segfaulting and gives a hint to the user that
some DNS traffic is not handled correctly (e.g. not anonymized
correctly?).

Does someone have a better idea?

Best regards,
  Lothar

Is DNS_Rewriter able to correctly rewrite DNS traffic in TCP packets
and can it be created in DNS.cc for TCP, too?

It wouldn't surprise me if it's not able to do so. It's code that we haven't
used much; it was added for a research project that we later suspended.

It would be helpful if you could enter this as a ticket in the Tracker
(http://tracker.icir.org/bro).

    Vern