Hi,
We have found incorrect processing of long records by nsd-zonec.
Suppose we have such record in zone file:
longrecord TXT "aaa....aaa"
where "aaa...aaa" is longer than 255 characters. Then by parsing this zone
file nsd-zonec prints error message and then segfaults:
root@ggd114:# nsd-zonec -c /cage/nsd/etc/nsd-auth_policy.conf
/cage/nsd/var/nsd/zones/second_zone.zone:15: error: text string is longer than
255 characters, try splitting it into multiple parts
Segmentation fault (core dumped)
gdb output:
$ gdb obj/nsd-zonec nsd-zonec.core
GNU gdb 6.3
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-unknown-openbsd5.1"...
Core was generated by `nsd-zonec'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /usr/lib/libcrypto.so.20.1...done.
Loaded symbols for /usr/lib/libcrypto.so.20.1
Reading symbols from /usr/lib/libc.so.62.0...done.
Loaded symbols for /usr/lib/libc.so.62.0
Reading symbols from /usr/libexec/ld.so...done.
Loaded symbols for /usr/libexec/ld.so #0 0x1c016d3d in zadd_rdata_txt_wireformat (data=0x0, first=1)
at /data/home/ibaku/nsd/zonec.c:970
970 if ((size_t)rd->data[0] + (size_t)data[0] > 65535) {
(gdb) bt #0 0x1c016d3d in zadd_rdata_txt_wireformat (data=0x0, first=1)
at /data/home/ibaku/nsd/zonec.c:970 #1 0x1c01b3ad in yyparse () at zparser.y:337 #2 0x1c016392 in zone_read (name=0x88904350 "zone2",
zonefile=0x88904384 "/cage/nsd/var/nsd/zones/second_zone.zone",
nsd_options=0x88904000)
at /data/home/ibaku/nsd/zonec.c:1418 #3 0x1c016980 in main (argc=0, argv=0x0) at /data/home/ibaku/nsd/zonec.c:1605
The real problem is that the function zparser_conv_text() returns NULL pointer
when it tries to process this long string. This is then used without further
checks at zonec.c:970, that causes null pointer dereference.
I'm not sure how to better fix this, but probably it's safe to return _some_
valid pointer to let nsd-zonec scan file to the end and produce error output
without coredumping. I have tested this and it works.
I'm not sure how to better fix this, but probably it's safe to return _some_
valid pointer to let nsd-zonec scan file to the end and produce error output
without coredumping. I have tested this and it works.
I agree. A fix has been applied to the NSD_3_2 branch in r3639. Zonec
simply continues with the first 255 characters.
apologies for _not_ testing, but hwat is the final outcome supposed to be?
Accept the zone with shortened TXT RR or refuse to compile due to
properly reported parse error?
[ Quoting <pk@denic.de> in "Re: [nsd-users] nsd-zonec SIGSEGV w..." ]
I agree. A fix has been applied to the NSD_3_2 branch in r3639. Zonec
simply continues with the first 255 characters.
apologies for _not_ testing, but hwat is the final outcome supposed to be?
Accept the zone with shortened TXT RR or refuse to compile due to
What about the RRSIG (if there is one)?
I think the only proper approach is to refuse to load such zone - truncating the record,
thus essentially corrupting zone data is not a good thing to do (even without DNSSEC - as this would break validation.)
there are legitimate uses for large TXT records - for example, DKIM signature records (they contain public keys…)
dropping "too large" record and proceeding to compile rest of zone feels like good compromise but it is actually not
as this would break NSEC (NSEC3) data (with bitmapped list of RR types).
properly reported parse error?
erroring out is probably best -- although NSD is garbage in - garbage out.
(which is a good policy most of the time)
...but long TXT records are not garbage...
so refusing the zone - or just allowing any size of TXT data - is safe behaviour.
with 3.3 defining "<character-string> is a single
length octet followed by that number of characters."
Enlightening, Peter. Shame on me for not reading this up.
Nevertheless, the format indicates that _multiple_ strings can be present,
thus making overall length of RDATA exceed 256 bytes in some cases...
Now, it was at least common to 'auto magically' split
longer TXT zone file format representations, but IIRC
in the context of DNSSEC this practice lost a few friends.
yes, as there can be multiple ways to do it.. and different RRSIGs would result..