pdns icon indicating copy to clipboard operation
pdns copied to clipboard

pdnsutil edit-zone function segfaults when query-logging enabled

Open eriksejr opened this issue 2 years ago • 2 comments

  • Program: Authoritative
  • Issue type: Bug report

Short description

pdnsutil crashes with a segfault when editing a reverse zone file if query-logging is enabled.

Environment

  • Operating system: FreeBSD 13.1
  • Software version: 4.6.2
  • Software source: FreeBSD Ports

Steps to reproduce

  1. Enable query-logging and loglevel=6 in pdns.conf
  2. Edit a reverse zone file (or possibly just any zonefile). Make your change, save and increment serial. Then select "apply"
pdnsutil edit-zone 66.65.100.in-addr.arpa
Checked 6 records of '66.65.100.in-addr.arpa', 0 errors, 0 warnings.
Detected the following changes:
-1.66.65.100.in-addr.arpa 3600 IN PTR testing.somedomain.com
+1.66.65.100.in-addr.arpa 3600 IN PTR testingchange.somedomain.com

You have not updated the SOA record! Would you like to increase-serial?
(y)es - increase serial, (n)o - leave SOA record as is, (e)dit your changes, (q)uit: y
Jun 28 15:21:20 Query 34396367136: Statement: SELECT content,ttl,prio,type,domain_id,disabled::int,name,auth::int FROM records WHERE disabled=false and type=$1 and name=$2
Jun 28 15:21:20 Query 34396367136: Parameters: $1 = 'SOA', $2 = '66.65.100.in-addr.arpa'
Jun 28 15:21:20 Query 34396367136: 472 usec to execute
Jun 28 15:21:20 Query 34396367136: 537 total usec to last row

(a)pply these changes, (e)dit again, (r)etry with original zone, (q)uit: a
Jun 28 15:21:22 Query 34402413536: Statement: delete from records where domain_id=$1 and name=$2 and type=$3
Jun 28 15:21:22 Query 34402413536: Parameters: $1 = '780', $2 = '66.65.100.in-addr.arpa', $3 = 'SOA'
Jun 28 15:21:22 Query 34402413536: 520 usec to execute
Jun 28 15:21:22 Query 34402411776: Statement: insert into records (content,ttl,prio,type,domain_id,disabled,name,ordername,auth) values ($1,$2,$3,$4,$5,$6,$7,$8,$9)
Segmentation fault (core dumped)

When query-logging is disabled:

pdnsutil edit-zone 66.65.100.in-addr.arpa
Checked 6 records of '66.65.100.in-addr.arpa', 0 errors, 0 warnings.
Detected the following changes:
-1.66.65.100.in-addr.arpa 3600 IN PTR testing.somedomain.com
+1.66.65.100.in-addr.arpa 3600 IN PTR testingchange.somedomain.com

You have not updated the SOA record! Would you like to increase-serial?
(y)es - increase serial, (n)o - leave SOA record as is, (e)dit your changes, (q)uit:
y
(a)pply these changes, (e)dit again, (r)etry with original zone, (q)uit: a
Adding empty non-terminals for non-DNSSEC zone '66.65.100.in-addr.arpa', 1 updates

Expected behaviour

The database is updated with the modified zone file contents with queries logged, but without the segfault.

Actual behaviour

pdnsutil crashes. The database is not updated with the changes

Other information

Works fine without query-logging on. I was debugging other issues when I ran into this.

eriksejr avatar Jun 28 '22 19:06 eriksejr

Hi @eriksejr. Thank you for the report.

You mention that you installed PowerDNS from FreeBSD ports, could you please provide more information?

  1. The output of make pretty-print-config for the dns/powerdns port.
  2. Did you install dependencies using pkg or also using ports? If you used ports, did you change any dependency build configuration (e.g. using make config-recursive) or did you leave everything as default?
  3. The full contents of pdns.conf.
  4. The full contents of the (reverse-)zonefile you are using if possible, or at least a minimized version of it that still triggers the problem.

The reason I am asking for this information is that I can't reproduce the segfault on a FreeBSD 13.1 with PowerDNS installed from ports (but dependencies installed using pkg).

fredmorcos avatar Jul 18 '22 10:07 fredmorcos

Hi Fred, Thanks for the question I might not be able to get you all the information you are asking for but I can get you some of it.

  1. I built the package on a separate build machine with poudriere from the ports tree then installed the package using pkg. I am unsure how to get the output you want out of poudiere but I can tell you didn't adjust package-specific options before the build but I DID alter the version of pgsql used as a dependency by setting "DEFAULT_VERSIONS+=pgsql=14" in /usr/local/etc/poudriere.d/make.conf

I could rerun the build with -i to have it drop me to an interactive shell in the build jail but this would also cause it to rebuild a number of the dependencies so the answer you would get might be different then the original build (i think) but if you are using a pgsql backend other then 14 that could be the reason you can't reproduce the issue.

  1. Answered in 1.

  2. query-logging is commented because of the problem. Passwords have been removed.

launch=gpgsql

gpgsql-host=localhost
gpgsql-dbname=powerdns
gpgsql-user=pdns
gpgsql-password=<some password>
disable-axfr=yes
daemon=yes
guardian=yes
local-address=0.0.0.0
local-port=53
log-dns-details
log-dns-queries
log-timestamp
loglevel=6
# query-logging
webserver-loglevel=detailed
primary=yes
secondary=no
autosecondary=no
xfr-cycle-interval=60
webserver=yes
webserver-port=8081
api=yes
api-key=<somekey>
enable-lua-records
  1. In the example I am editing a zone already in the database. But if I were to write the contents out as a BIND zonefile it would look something like this:
$TTL 3600
@                IN SOA ns00.domain.com. fake.domain.com. (
                                     2017101301  ;Serial
                                     3h    ; Refresh after 3 hours
                                     1h    ; Retry after 1 hour
                                     1W    ; Expire after 1 week
                                     3h )  ; Neg Cache 3h
                             IN NS      ns01.domain.com.
                             IN NS      ns02.domain.com.
                             IN NS      ns03.domain.com.
                             IN NS      ns04.domain.com.

1       IN PTR  testing.domain.com.
  1. This might also be helpful to you in reproducing this issue
pkg info -dx powerdns
powerdns-4.6.2:
	lua52-5.2.4
	curl-7.83.1
	boost-libs-1.79.0_1
	sqlite3-3.37.2,1
	postgresql14-client-14.3
	mysql57-client-5.7.38
	lmdb-0.9.29_1,1

Thanks for taking the time to look at it.

eriksejr avatar Jul 18 '22 13:07 eriksejr

Hi @eriksejr, can you try this branch out please?

fredmorcos avatar Aug 25 '22 08:08 fredmorcos

Hi Fred, I removed my packaged pdns and cloned your git repo then compiled your branch:

Aug 25 14:20:07 PowerDNS Authoritative Server 0.0.24267.0.fred11731fixpdnsutilqueryloggingsegfault.gfd4fd2dae2 (C) 2001-2022 PowerDNS.COM BV
Aug 25 14:20:07 Using 64-bits mode. Built using clang 13.0.0 ([email protected]:llvm/llvm-project.git llvmorg-13.0.0-0-gd7b669b3a303) on Aug 25 2022 09:51:40 by [email protected].
Aug 25 14:20:07 PowerDNS comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it according to the terms of the GPL version 2.
Aug 25 14:20:07 Features: libcrypto-ecdsa libcrypto-ed25519 libcrypto-ed448 libcrypto-eddsa lua lua-records protobuf curl scrypt
Aug 25 14:20:07 Built-in modules: bind gmysql gpgsql
Aug 25 14:20:07 Configured with: " '--enable-tools' '--with-modules=bind gmysql gpgsql'"

I made a similar change to a zone file which was causing the crash before in the existing database with query logging enabled:

Aug 25 14:15:56 Query 34405982848: Statement: select id,name,master,last_check,notified_serial,type,options,catalog,account from domains where name=$1
Aug 25 14:15:56 Query 34405982848: Parameters: $1 = '66.65.100.in-addr.arpa'
Aug 25 14:15:56 Query 34405982848: 592 usec to execute
Aug 25 14:15:56 Query 34405982848: 636 total usec to last row
Aug 25 14:15:56 Query 34400562080: Statement: SELECT content,ttl,prio,type,domain_id,disabled::int,name,auth::int FROM records WHERE disabled=false and type=$1 and name=$2
Aug 25 14:15:56 Query 34400562080: Parameters: $1 = 'SOA', $2 = '66.65.100.in-addr.arpa'
Aug 25 14:15:56 Query 34400562080: 487 usec to execute
Aug 25 14:15:56 Query 34400562080: 545 total usec to last row
Aug 25 14:15:56 Query 34405989568: Statement: select kind,content from domains, domainmetadata where domainmetadata.domain_id=domains.id and name=$1
Aug 25 14:15:56 Query 34405989568: Parameters: $1 = '66.65.100.in-addr.arpa'
Aug 25 14:15:56 Query 34405989568: 1210 usec to execute
Aug 25 14:15:56 Query 34405989568: 1254 total usec to last row
Aug 25 14:15:56 Query 34400562080: Statement: SELECT content,ttl,prio,type,domain_id,disabled::int,name,auth::int FROM records WHERE disabled=false and type=$1 and name=$2
Aug 25 14:15:56 Query 34400562080: Parameters: $1 = 'SOA', $2 = '65.100.in-addr.arpa'
Aug 25 14:15:56 Query 34400562080: 494 usec to execute
Aug 25 14:15:56 Query 34400562080: 539 total usec to last row
Aug 25 14:15:56 Query 34400562080: Statement: SELECT content,ttl,prio,type,domain_id,disabled::int,name,auth::int FROM records WHERE disabled=false and type=$1 and name=$2
Aug 25 14:15:56 Query 34400562080: Parameters: $1 = 'SOA', $2 = '100.in-addr.arpa'
Aug 25 14:15:56 Query 34400562080: 430 usec to execute
Aug 25 14:15:56 Query 34400562080: 475 total usec to last row
Aug 25 14:15:56 Query 34400562080: Statement: SELECT content,ttl,prio,type,domain_id,disabled::int,name,auth::int FROM records WHERE disabled=false and type=$1 and name=$2
Aug 25 14:15:56 Query 34400562080: Parameters: $1 = 'SOA', $2 = 'in-addr.arpa'
Aug 25 14:15:56 Query 34400562080: 452 usec to execute
Aug 25 14:15:56 Query 34400562080: 497 total usec to last row
Aug 25 14:15:56 Query 34400562080: Statement: SELECT content,ttl,prio,type,domain_id,disabled::int,name,auth::int FROM records WHERE disabled=false and type=$1 and name=$2
Aug 25 14:15:56 Query 34400562080: Parameters: $1 = 'SOA', $2 = 'arpa'
Aug 25 14:15:56 Query 34400562080: 419 usec to execute
Aug 25 14:15:56 Query 34400562080: 464 total usec to last row
Aug 25 14:15:56 Query 34400562080: Statement: SELECT content,ttl,prio,type,domain_id,disabled::int,name,auth::int FROM records WHERE disabled=false and type=$1 and name=$2
Aug 25 14:15:56 Query 34400562080: Parameters: $1 = 'SOA', $2 = '.'
Aug 25 14:15:56 Query 34400562080: 300 usec to execute
Aug 25 14:15:56 Query 34400562080: 345 total usec to last row
Aug 25 14:15:56 Query 34405989568: Statement: select kind,content from domains, domainmetadata where domainmetadata.domain_id=domains.id and name=$1
Aug 25 14:15:56 Query 34405989568: Parameters: $1 = '66.65.100.in-addr.arpa'
Aug 25 14:15:56 Query 34405989568: 541 usec to execute
Aug 25 14:15:56 Query 34405989568: 588 total usec to last row
Checked 6 records of '66.65.100.in-addr.arpa', 0 errors, 0 warnings.
Detected the following changes:
-1.66.65.100.in-addr.arpa 3600 IN PTR testingchange.somedomain.com
+2.66.65.100.in-addr.arpa 3600 IN PTR testingchange.somedomain.com

You have not updated the SOA record! Would you like to increase-serial?
(y)es - increase serial, (n)o - leave SOA record as is, (e)dit your changes, (q)uit: y
Aug 25 14:16:00 Query 34400562080: Statement: SELECT content,ttl,prio,type,domain_id,disabled::int,name,auth::int FROM records WHERE disabled=false and type=$1 and name=$2
Aug 25 14:16:00 Query 34400562080: Parameters: $1 = 'SOA', $2 = '66.65.100.in-addr.arpa'
Aug 25 14:16:00 Query 34400562080: 622 usec to execute
Aug 25 14:16:00 Query 34400562080: 702 total usec to last row

(a)pply these changes, (e)dit again, (r)etry with original zone, (q)uit: a
Aug 25 14:16:03 Query 34405986528: Statement: delete from records where domain_id=$1 and name=$2 and type=$3
Aug 25 14:16:03 Query 34405986528: Parameters: $1 = '780', $2 = '66.65.100.in-addr.arpa', $3 = 'SOA'
Aug 25 14:16:03 Query 34405986528: 686 usec to execute
Aug 25 14:16:03 Query 34405984128: Statement: insert into records (content,ttl,prio,type,domain_id,disabled,name,ordername,auth) values ($1,$2,$3,$4,$5,$6,$7,$8,$9)
Aug 25 14:16:03 Query 34405984128: Parameters: $1 = 'ns00.somedomain.com isp-admin.somedomain.com 2017101304 10800 3600 604800 10800', $2 = '3600', $3 = '0', $4 = 'SOA', $5 = '780', $6 = 'f', $7 = '66.65.100.in-addr.arpa', $8 = NULL, $9 = 't'
Aug 25 14:16:03 Query 34405984128: 44017 usec to execute
Aug 25 14:16:03 Query 34405986528: Statement: delete from records where domain_id=$1 and name=$2 and type=$3
Aug 25 14:16:03 Query 34405986528: Parameters: $1 = '780', $2 = '1.66.65.100.in-addr.arpa', $3 = 'PTR'
Aug 25 14:16:03 Query 34405986528: 9275 usec to execute
Aug 25 14:16:03 Query 34405992448: Statement: DELETE FROM comments WHERE domain_id=$1 AND name=$2 AND type=$3
Aug 25 14:16:03 Query 34405992448: Parameters: $1 = '780', $2 = '1.66.65.100.in-addr.arpa', $3 = 'PTR'
Aug 25 14:16:03 Query 34405992448: 20933 usec to execute
Aug 25 14:16:03 Query 34405986528: Statement: delete from records where domain_id=$1 and name=$2 and type=$3
Aug 25 14:16:03 Query 34405986528: Parameters: $1 = '780', $2 = '2.66.65.100.in-addr.arpa', $3 = 'PTR'
Aug 25 14:16:03 Query 34405986528: 1274 usec to execute
Aug 25 14:16:03 Query 34405984128: Statement: insert into records (content,ttl,prio,type,domain_id,disabled,name,ordername,auth) values ($1,$2,$3,$4,$5,$6,$7,$8,$9)
Aug 25 14:16:03 Query 34405984128: Parameters: $1 = 'testingchange.somedomain.com', $2 = '3600', $3 = '0', $4 = 'PTR', $5 = '780', $6 = 'f', $7 = '2.66.65.100.in-addr.arpa', $8 = NULL, $9 = 't'
Aug 25 14:16:03 Query 34405984128: 729 usec to execute
Aug 25 14:16:03 Query 34400562080: Statement: SELECT content,ttl,prio,type,domain_id,disabled::int,name,auth::int FROM records WHERE disabled=false and type=$1 and name=$2
Aug 25 14:16:03 Query 34400562080: Parameters: $1 = 'SOA', $2 = '66.65.100.in-addr.arpa'
Aug 25 14:16:03 Query 34400562080: 214 usec to execute
Aug 25 14:16:03 Query 34400562080: 268 total usec to last row
Aug 25 14:16:03 Query 34400563040: Statement: SELECT content,ttl,prio,type,domain_id,disabled::int,name,auth::int,ordername FROM records WHERE (disabled=false OR $1) and domain_id=$2 order by name, type
Aug 25 14:16:03 Query 34400563040: Parameters: $1 = '0', $2 = '780'
Aug 25 14:16:03 Query 34400563040: 479 usec to execute
Aug 25 14:16:03 Query 34400563040: 610 total usec to last row

There was no crash. I see the "NULL" as parameter 8 in the INSERT statement after the apply, so the patch seems to have prevented the crash.

eriksejr avatar Aug 25 '22 18:08 eriksejr