libnss-resolve: Fallback from resolve to dns breaks DNSSEC validation

Bug #1624071 reported by Anders Kaseorg on 2016-09-15
36
This bug affects 7 people
Affects Status Importance Assigned to Milestone
systemd
Fix Released
Unknown
systemd (Ubuntu)
Medium
Martin Pitt

Bug Description

The libnss-resolve postinst script inserts ‘resolve’ before ‘dns’ in the hosts line of /etc/nsswitch.conf. This makes DNSSEC validation impossible, even with DNSSEC=yes in /etc/systemd/resolved.conf, because if libnss_resolve returns a validation failure, glibc will simply fall back to libnss_dns. It also makes NXDOMAIN lookups twice as slow.

Anders Kaseorg (andersk) wrote :

I also worry that, by masking systemd-resolved failures, this fallback has meant that systemd-resolved is not really getting adequate testing. If there were widespread problems causing systemd-resolved lookups to fail, would anyone have noticed?

Martin Pitt (pitti) wrote :

Thanks for reporting this, well spotted!

The reason for having "dns" is *not* to guard against failures of resolved -- if the daemon is not running, then nss-resolve already falls back to glibc's resolver (i. e. "dns").

The reason is that libnss-resolve itself might not be available. E. g. you might have the amd64 version installed that inserts itself into nsswitch. But then you start a 32 bit package from an i386 deb which needs libnss-resolve:i386 and that might not be installed. That needs "dns" otherwise you get a "System error" when resolving.

I actually thought that "resolve [NOTFOUND=return] dns" should do the right thing, as that's the crucial case -- its default action is "continue", and if a DNS entry fails validation we don't want to fall back to "dns". The actions for success/unavail/tryagain already seem right. But this doesn't work, "ping sigfail.verteiltesysteme.net" still succeeds and falls back to dns.

So I'm not sure how to solve this. Ideally we would have a syntax which would ignore the absence of the "resolve" NSS module but accept if that says "not found". Or we need to ensure that for any :arch package the corresponding libnss-resolve:arch is installed.

Changed in systemd (Ubuntu):
status: New → Triaged
Anders Kaseorg (andersk) wrote :

You’re right: glibc seems to treat the absence of libnss-resolve itself as UNAVAIL, which is the same code returned on DNSSEC validation failures when libnss-resolve is working. I don’t see a way around this other than patching libnss-resolve to return NOTFOUND (or TRYAGAIN?) on validation failure.

It looks like there may be other ways for an active attacker to force a TRYAGAIN code (with a response that doesn’t fit in the caller-provided buffer), which suggests that the right configuration is [!UNAVAIL=return], not merely [NOTFOUND=return].

Anders Kaseorg (andersk) on 2016-09-15
description: updated
Anders Kaseorg (andersk) wrote :

Filed https://github.com/systemd/systemd/issues/4157 upstream for the NOTFOUND vs. UNAVAIL problem.

Martin Pitt (pitti) on 2016-09-16
Changed in systemd (Ubuntu):
assignee: nobody → Martin Pitt (pitti)
importance: Undecided → Medium
milestone: none → ubuntu-16.10
Martin Pitt (pitti) wrote :

Upstream PR sent with a possible fix: https://github.com/systemd/systemd/pull/4164

With that "resolve [!UNAVAIL=return] dns" does the right thing.

Martin Pitt (pitti) on 2016-09-28
Changed in systemd (Ubuntu):
milestone: ubuntu-16.10 → ubuntu-16.11
Martin Pitt (pitti) on 2016-10-01
Changed in systemd (Ubuntu):
status: Triaged → In Progress
milestone: ubuntu-16.11 → ubuntu-16.10
Martin Pitt (pitti) on 2016-10-02
Changed in systemd (Ubuntu):
status: In Progress → Fix Committed
Launchpad Janitor (janitor) wrote :

This bug was fixed in the package systemd - 231-9git1

---------------
systemd (231-9git1) yakkety; urgency=medium

  * systemctl: Add --wait option to wait until started units terminate again.
    This is a prerequisite for using systemd for graphical sessions without
    ugly polling.
  * nss-resolve: return NOTFOUND instead of UNAVAIL on resolution errors.
    This makes it possible to configure a fallback to "dns" without breaking
    DNSSEC, with "resolve [!UNAVAIL=return] dns".
  * libnss-resolve.postinst: Skip dns fallback if resolve is present.
    Only fall back to "dns" if nss-resolve is not installed (for the
    architecture of the calling program). Once it is, we never want to fall
    back to "dns" as that breaks enforcing DNSSEC verification and also
    pointlessly retries NXDOMAIN failures. (LP: #1624071)

 -- Martin Pitt <email address hidden> Sun, 02 Oct 2016 10:33:11 +0200

Changed in systemd (Ubuntu):
status: Fix Committed → Fix Released
Calin Cerghedean (ccerghe1) wrote :

Glad to see this has been reported. On my system, I can no longer get to any local nodes by referring to the hostname, so it is pretty clear that hostname resolution is not working. I was able to circumvent the behavior for only 1 Linux machine by specifying nodename.local, but that doesn't work with my NAS device. So, I'm kinda stuck... I think this package is currently in yakkety-proposed (sorry, I still haven't learned how to be able to tell where a "fix" was released and in what repository it is currently in).
Any idea when this will be released to yakkety-updates ?

Martin Pitt (pitti) wrote :

Calin: This sounds like something entirely unrelated. Can you please file a new bug?

Changed in systemd:
status: Unknown → Fix Released
To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.