nss-resolve: drop the internal fallback to libnss_dns (#5945)

If we could not communicate with systemd-resolved, we would call into
libnss_dns. libnss_dns would return NOTFOUND for stuff like "localhost" and
other names resolved by nss-myhostname, which we would fall under the !UNAVAIL=
condition and cause resolution to fail. So the following recommended
configuration in nsswitch.conf would not work:

   hosts: resolve [!UNAVAIL=return] dns myhostname

Remove the internal fallback code completely so that the fallback logic
can be configured in nsswitch.conf.

Tested with
   hosts: resolve [!UNAVAIL=return] myhostname
and
   hosts: resolve [!UNAVAIL=return] dns myhostname

Fixes #5742.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2017-05-12 08:31:46 -04:00 committed by Lennart Poettering
parent 3823da25cf
commit 5486a31d28
4 changed files with 27 additions and 70 deletions

View File

@ -5630,8 +5630,7 @@ libnss_resolve_la_LDFLAGS = \
libnss_resolve_la_LIBADD = \
libsystemd-internal.la \
libbasic.la \
-ldl
libbasic.la
rootlib_LTLIBRARIES += \
libnss_resolve.la

7
NEWS
View File

@ -1,5 +1,12 @@
systemd System and Service Manager
CHANGES WITH 234 in spe
* The code to call libnss_dns as a fallback from libnss_resolve when
the communication with systemd-resolved fails was removed. This
fallback was redundant and interfered with the [!UNAVAIL=return]
suffix. See nss-resolve(8) for the recommended configuration.
CHANGES WITH 233:
* This version requires at least gperf 3.1 for building, 3.0 is not

View File

@ -1150,15 +1150,14 @@ test_dlopen = executable(
link_with : [libbasic],
dependencies : [libdl])
foreach tuple : [['myhostname', 'HAVE_MYHOSTNAME', []],
['systemd', '', []],
['mymachines', 'ENABLE_MACHINED', []],
['resolve', 'ENABLE_RESOLVED', [libdl]]]
foreach tuple : [['myhostname', 'HAVE_MYHOSTNAME'],
['systemd', '' ],
['mymachines', 'ENABLE_MACHINED'],
['resolve', 'ENABLE_RESOLVED']]
condition = tuple[1] == '' or conf.get(tuple[1], false)
if condition
module = tuple[0]
extra_deps = tuple[2]
sym = 'src/nss-@0@/nss-@0@.sym'.format(module)
version_script_arg = join_paths(meson.current_source_dir(), sym)
@ -1174,7 +1173,7 @@ foreach tuple : [['myhostname', 'HAVE_MYHOSTNAME', []],
link_with : [libsystemd_internal,
libbasic],
dependencies : [threads,
librt] + extra_deps,
librt],
link_depends : sym,
install : true,
install_dir : rootlibdir)

View File

@ -17,7 +17,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <dlfcn.h>
#include <errno.h>
#include <netdb.h>
#include <nss.h>
@ -39,20 +38,6 @@ NSS_GETHOSTBYADDR_PROTOTYPES(resolve);
#define DNS_CALL_TIMEOUT_USEC (45*USEC_PER_SEC)
typedef void (*voidfunc_t)(void);
static voidfunc_t find_fallback(const char *module, const char *symbol) {
void *dl;
/* Try to find a fallback NSS module symbol */
dl = dlopen(module, RTLD_LAZY|RTLD_NODELETE);
if (!dl)
return NULL;
return dlsym(dl, symbol);
}
static bool bus_error_shall_fallback(sd_bus_error *e) {
return sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN) ||
sd_bus_error_has_name(e, SD_BUS_ERROR_NAME_HAS_NO_OWNER) ||
@ -151,7 +136,7 @@ enum nss_status _nss_resolve_gethostbyname4_r(
r = sd_bus_open_system(&bus);
if (r < 0)
goto fallback;
goto fail;
r = sd_bus_message_new_method_call(
bus,
@ -179,13 +164,14 @@ enum nss_status _nss_resolve_gethostbyname4_r(
return NSS_STATUS_NOTFOUND;
}
if (bus_error_shall_fallback(&error))
goto fallback;
/* Return NSS_STATUS_UNAVAIL when communication with systemd-resolved fails,
allowing falling back to other nss modules. Treat all other error conditions as
NOTFOUND. This includes DNSSEC errors and suchlike. (We don't use UNAVAIL in this
case so that the nsswitch.conf configuration can distuingish such executed but
negative replies from complete failure to talk to resolved). */
if (!bus_error_shall_fallback(&error))
ret = NSS_STATUS_NOTFOUND;
/* Treat all other error conditions as NOTFOUND, and fail. This includes DNSSEC errors and
suchlike. (We don't use UNAVAIL in this case so that the nsswitch.conf configuration can distuingish
such executed but negative replies from complete failure to talk to resolved. */
ret = NSS_STATUS_NOTFOUND;
goto fail;
}
@ -286,17 +272,6 @@ enum nss_status _nss_resolve_gethostbyname4_r(
return NSS_STATUS_SUCCESS;
fallback:
{
_nss_gethostbyname4_r_t fallback;
fallback = (_nss_gethostbyname4_r_t)
find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyname4_r");
if (fallback)
return fallback(name, pat, buffer, buflen, errnop, h_errnop, ttlp);
}
fail:
*errnop = -r;
*h_errnop = NO_RECOVERY;
@ -339,7 +314,7 @@ enum nss_status _nss_resolve_gethostbyname3_r(
r = sd_bus_open_system(&bus);
if (r < 0)
goto fallback;
goto fail;
r = sd_bus_message_new_method_call(
bus,
@ -367,10 +342,9 @@ enum nss_status _nss_resolve_gethostbyname3_r(
return NSS_STATUS_NOTFOUND;
}
if (bus_error_shall_fallback(&error))
goto fallback;
if (!bus_error_shall_fallback(&error))
ret = NSS_STATUS_NOTFOUND;
ret = NSS_STATUS_NOTFOUND;
goto fail;
}
@ -484,16 +458,6 @@ enum nss_status _nss_resolve_gethostbyname3_r(
return NSS_STATUS_SUCCESS;
fallback:
{
_nss_gethostbyname3_r_t fallback;
fallback = (_nss_gethostbyname3_r_t)
find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyname3_r");
if (fallback)
return fallback(name, af, result, buffer, buflen, errnop, h_errnop, ttlp, canonp);
}
fail:
*errnop = -r;
*h_errnop = NO_RECOVERY;
@ -540,7 +504,7 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
r = sd_bus_open_system(&bus);
if (r < 0)
goto fallback;
goto fail;
r = sd_bus_message_new_method_call(
bus,
@ -576,10 +540,9 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
return NSS_STATUS_NOTFOUND;
}
if (bus_error_shall_fallback(&error))
goto fallback;
if (!bus_error_shall_fallback(&error))
ret = NSS_STATUS_NOTFOUND;
ret = NSS_STATUS_NOTFOUND;
goto fail;
}
@ -674,17 +637,6 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
return NSS_STATUS_SUCCESS;
fallback:
{
_nss_gethostbyaddr2_r_t fallback;
fallback = (_nss_gethostbyaddr2_r_t)
find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyaddr2_r");
if (fallback)
return fallback(addr, len, af, result, buffer, buflen, errnop, h_errnop, ttlp);
}
fail:
*errnop = -r;
*h_errnop = NO_RECOVERY;