Faelix Limited Open Source Software

security, networks & software

Wed, 04 Apr 2007

Patch to Fix Segfault During Signing DNSSEC Key on AMD64

We tested the PKCS#15 signer (written for .se NIC's DNSSEC deployment) on AMD64 (Debian sarge) and found it would segfault in the strftime() calls in write_RRSIG() in dns-util.c:

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 "x86_64-linux"...Using host libthread_db library "/lib/libthread_db.so.1".

(gdb) run
Starting program: /home/maz/dns/pkcs15-dnssec-0.1/pkcs15-dnssec -s -n faelix.net. -i input.txt -o output.txt -c 20070401000000 -x 20070430235959
[Thread debugging using libthread_db enabled]
[New Thread 46954030179488 (LWP 27574)]
Enter PIN [XXXX@YYYY]:

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 46954030179488 (LWP 27574)]
0x00002ab455dcafd7 in strftime () from /lib/libc.so.6

The gmtime() calls on lines 189 and 192 return nil, and that appears to be caused by the sizes of various ints:

sizeof( time_t ) == 8 (returned by string2time(), from mktime())
sizeof( u_int32_t ) == 4 (used in struct dns_type_rrsig)

A tiny patch appears to resolve this:

--- a/dns-util.c        Thu Apr 05 14:28:20 2007 +0100
+++ b/dns-util.c        Thu Apr 05 14:28:31 2007 +0100
@@ -182,14 +182,17 @@ write_RRSIG(FILE *f, const dns_type_rrsi
        int c, b64len;
        char b64buf[MAX_LINE];
        char expiration[MAX_TIMESTAMP], inception[MAX_TIMESTAMP];
+       time_t t;

        const char *tformat = "%Y%m%d%H%M%S";

+       t = rrsig->expiration;
        strftime(expiration, sizeof(expiration), tformat,
-                gmtime((time_t *) &rrsig->expiration));
-
+                gmtime((time_t *) &t));
+
+       t = rrsig->inception;
        strftime(inception,  sizeof(inception), tformat,
-                gmtime((time_t *) &rrsig->inception));
+                gmtime((time_t *) &t));

        b64len = b64_ntop (rrsig->sigdata, rrsig->siglen, b64buf, MAX_LINE);
        b64buf[b64len] = (char) 0;

Please note: this has not been fully tested on either 32-bit or 64-bit platforms! It might generate invalid RRSET records/signatures/etc, but given the simplicity of the patch we think it's probably ok to publish before our in-house testing is complete.