--- i/debian/nsd.service
+++ w/debian/nsd.service
@@ -8,7 +8,7 @@ Type=notify
Restart=always
ExecStart=/usr/sbin/nsd -d
ExecReload=+/bin/kill -HUP $MAINPID
-CapabilityBoundingSet=CAP_CHOWN CAP_IPC_LOCK CAP_NET_BIND_SERVICE
CAP_SETGID CAP_SETUID CAP_SYS_CHROOT
+CapabilityBoundingSet=CAP_CHOWN CAP_DAC_OVERRIDE CAP_IPC_LOCK
CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_CHROOT
MemoryDenyWriteExecute=true
NoNewPrivileges=true
PrivateDevices=true
In a recent upgrade to buster, the nsd service failed to start after
upgrade. After spending more time than expected digging through the
details, it turns out that the CAP_DAC_OVERRIDE capability should be
included in the systemd service unit file since the
CapabilityBoundingSet configuration was added in the latest version [1].
The affected host in particular has been through several release
upgrades (I also ran into #932010). I use "include:" lines in my
configuration file set in order to ease management and version control
of my zone files. As a result, the included configuration files were not
readable. They have permission bits 0440 and are owned by the nsd user.
I haven't done a deep investigation, but it appears that with systemd
starting the process as root, without the CAP_DAC_OVERRIDE capability
available it's unable to read files owned by the 'nsd' user.
Relatedly, have you considered directly running the daemon as the nsd
user using AmbientCapabilities=CAP_NET_BIND_SERVICE? That removes the
need for CAP_{CHOWN,SETGID,SETUID}. In my local testing I haven't found
a need for CAP_IPC_LOCK, and don't use chroot configuration so haven't
needed CAP_SYS_CHROOT.
It sort of looks like the Debian service unit file was derived
incrementally from the upstream one. It'd be useful for external diff
review to rebase the content and ordering based on the upstream file
provided in contrib/nsd.service. In fact, you may consider a Debian
patch making targeted adjustments (ReadWritePaths) and shipping the
upstream config directly. Notably, the upstream unit file doesn't list
CAP_CHOWN in the bounding set, is there a Debian specific rationale for
needing to include it?
Thanks,
Joel
[1] https://salsa.debian.org/dns-team/nsd/commit/8a6039c
Hi Joel, thanks for the report. The systemd service file has been in part of the package for 5 years, with the default ordering of sections (unit, service, install). The upstream service while was more less recently added (~1 year ago). Since systemd hardening has been available and recommended, the corresponding directives where added from upstream. Admittedly this still requires some fine tuning such as: https://salsa.debian.org/dns-team/nsd/merge_requests/1 As such, I am a bit reluctant to ship, use or patch around the upstream service file. However the DAC_OVERRIDE capability is quite excessive as is bypasses all permission checks. Giving the process this capability would be the quite contrary to the intent of settting CapabilityBoundingSet. Best regards, Markus
To be clean, I'm all for the systemd hardening. I'm just reporting a case where the current configuration appears to have a gap. I'm in agreement that the DAC_OVERRIDE may be too big of a hammer, but I wasn't able to quickly identify another alternative without switching to the AmbientCapabilities path. The nsd daemon provides config file inclusion support, however a mixed file ownership as I had becomes nonfunctional. It was non-intuitive to me that the nsd daemon, running as the nsd user, didn't have permissions to read files owned by the nsd user. During investigation I figured out that the systemd initially launches as root and then setuid to nsd. The workaround was ensuring that the base config and all included data files are owned by root, but perhaps there's a cleaner way to support this. Joel
Thank you very much! Adding CAP_DAC_OVERRIDE solved it for me as well. Not sure how many hours it would have taken for me to figure it out. Does systemd or the linux kernel log capability violations somewhere? (is it even possible)
Confirmed, on every system upgraded to buster, nsd fails to start (even with a blank configuration file i.e. all settings at defaults): systemd[1]: Starting Name Server Daemon... nsd[10191]: error: could not open zone list /var/lib/nsd/zone.list: Permission denied nsd[10191]: error: could not read zonelist file /var/lib/nsd/zone.list systemd[1]: nsd.service: Main process exited, code=exited, status=1/FAILURE systemd[1]: nsd.service: Failed with result 'exit-code'. systemd[1]: Failed to start Name Server Daemon. Since the default for the config parameter "zonelistfile" is "/var/lib/nsd/zone.list", the process needs access to this file (seemingly even if you do not use dynamic zones). I don't pretend to understand all this .service file gubbins, I note that it already has ReadWritePaths=/var/lib/nsd so I don't know what's wrong. Since I didn't feel it wise to give the process full root access to the filesystem, I simply commented out the CapabilityBoundingSet line Please can you fix this regression. Thanks David
I ran into this issue too. I think that, in principle, daemons should not be able to write to their own configuration files, so making the files owned by root is a good thing anyway. The only real trouble is that things break on upgrade due to the earlier default ownership. One other related issue is that the current CapabilityBoundingSet appears to break the ip-transparent nsd option. May 03 17:59:40 juniper nsd[20346]: setsockopt(...,IP_TRANSPARENT, ...) failed for udp: Operation not permitted May 03 17:59:40 juniper nsd[20346]: setsockopt(...,IP_TRANSPARENT, ...) failed for udp: Operation not permitted May 03 17:59:40 juniper nsd[20346]: setsockopt(...,IP_TRANSPARENT, ...) failed for tcp: Operation not permitted May 03 17:59:40 juniper nsd[20346]: setsockopt(...,IP_TRANSPARENT, ...) failed for tcp: Operation not permitted I had this in use as a workaround for: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=765831 ...and apparently I don't need the workaround anymore, but other use cases for that option will presumably be broken still. Thanks, Corey
Hey folks, I hit this on sid. nsd is failing to start with a sensible config, done within the bounds of allowed NSD configuration, and fails to start. This has taken me a huge amount of time to track down. What is the NSD maintainer's opinion of the correct way to get nsd to behave with a sensible config, here? I'm reluctant to trim caps, since tightening them seems good, but they're too tight, it appears. paultag
Hello, I got bitten by a problem where NSD would not start and looks very similar to what it’s reported here. Since I found a way to make it work without fiddling with systemd I felt like reporting back. In my case, using Debian 11, the service starts correctly when freshly installed. The problem presents itself when using dynamic zones, specifically when the file /var/lib/nsd/zone.list comes into existence. Usually created automatically when using something like this `nsd-control addzone example.com example`. After this the service won’t start with a 'permission denied’ to read the zone.list file. This file gets created with owner nsd and group nsd. What needs to be done is change the ownership of this file to root:root and everything works. Even adding new zones work and the ownership of the file remains root:root. The cause for this could apparently be that the service initially starts as root and then drops to nsd. Not too sure about the cause though. This was discussed here[1]. A definitive solution could be that the package creates that file with the correct ownership “root:root” and no content. Also, please let me know if anyone see any possible problems with this fix. Thanks. [1]: https://www.mail-archive.com/nsd-users@nlnetlabs.nl/msg00078.html
By using "nsd-control addzone", I also got NSD into the situation that it would not start anymore on Debian 11. The current systemd service settings also prevent "nsd-control write" from working (when trying to pull zones from old nameserver via axfr to nsd on this machine):