Skip to content

Commit

Permalink
nss: do not modify errno when NSS_STATUS_NOTFOUND or NSS_STATUS_SUCCESS
Browse files Browse the repository at this point in the history
This also adds PROTECT_ERRNO for all nss module functions.

C.f. glibc NSS documents https://www.gnu.org/software/libc/manual/html_node/NSS-Modules-Interface.html
and discussion in https://sourceware.org/bugzilla/show_bug.cgi?id=23410.

Fixes #9585.
  • Loading branch information
yuwata authored and poettering committed Jul 25, 2018
1 parent 8d45501 commit 06202b9
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 157 deletions.
16 changes: 7 additions & 9 deletions src/nss-myhostname/nss-myhostname.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ enum nss_status _nss_myhostname_gethostbyname4_r(
char *r_name;
unsigned n;

PROTECT_ERRNO;
BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);

assert(name);
Expand All @@ -64,7 +65,6 @@ enum nss_status _nss_myhostname_gethostbyname4_r(

n_addresses = local_gateways(NULL, 0, AF_UNSPEC, &addresses);
if (n_addresses <= 0) {
*errnop = ENOENT;
*h_errnop = HOST_NOT_FOUND;
return NSS_STATUS_NOTFOUND;
}
Expand All @@ -81,7 +81,6 @@ enum nss_status _nss_myhostname_gethostbyname4_r(

/* We respond to our local host name, our hostname suffixed with a single dot. */
if (!streq(name, hn) && !streq_ptr(startswith(name, hn), ".")) {
*errnop = ENOENT;
*h_errnop = HOST_NOT_FOUND;
return NSS_STATUS_NOTFOUND;
}
Expand Down Expand Up @@ -157,8 +156,8 @@ enum nss_status _nss_myhostname_gethostbyname4_r(
if (ttlp)
*ttlp = 0;

/* Explicitly reset all error variables */
*errnop = 0;
/* Explicitly reset both *h_errnop and h_errno to work around
* https://bugzilla.redhat.com/show_bug.cgi?id=1125975 */
*h_errnop = NETDB_SUCCESS;
h_errno = 0;

Expand Down Expand Up @@ -286,8 +285,8 @@ static enum nss_status fill_in_hostent(
if (canonp)
*canonp = r_name;

/* Explicitly reset all error variables */
*errnop = 0;
/* Explicitly reset both *h_errnop and h_errno to work around
* https://bugzilla.redhat.com/show_bug.cgi?id=1125975 */
*h_errnop = NETDB_SUCCESS;
h_errno = 0;

Expand All @@ -309,6 +308,7 @@ enum nss_status _nss_myhostname_gethostbyname3_r(
uint32_t local_address_ipv4 = 0;
int n_addresses = 0;

PROTECT_ERRNO;
BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);

assert(name);
Expand All @@ -334,7 +334,6 @@ enum nss_status _nss_myhostname_gethostbyname3_r(

n_addresses = local_gateways(NULL, 0, af, &addresses);
if (n_addresses <= 0) {
*errnop = ENOENT;
*h_errnop = HOST_NOT_FOUND;
return NSS_STATUS_NOTFOUND;
}
Expand All @@ -350,7 +349,6 @@ enum nss_status _nss_myhostname_gethostbyname3_r(
}

if (!streq(name, hn) && !streq_ptr(startswith(name, hn), ".")) {
*errnop = ENOENT;
*h_errnop = HOST_NOT_FOUND;
return NSS_STATUS_NOTFOUND;
}
Expand Down Expand Up @@ -393,6 +391,7 @@ enum nss_status _nss_myhostname_gethostbyaddr2_r(
bool additional_from_hostname = false;
unsigned n;

PROTECT_ERRNO;
BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);

assert(addr);
Expand Down Expand Up @@ -455,7 +454,6 @@ enum nss_status _nss_myhostname_gethostbyaddr2_r(
}
}

*errnop = ENOENT;
*h_errnop = HOST_NOT_FOUND;
return NSS_STATUS_NOTFOUND;

Expand Down
88 changes: 36 additions & 52 deletions src/nss-mymachines/nss-mymachines.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ enum nss_status _nss_mymachines_gethostbyname4_r(
char *r_name;
int n_ifindices, r;

PROTECT_ERRNO;
BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);

assert(name);
Expand Down Expand Up @@ -126,7 +127,6 @@ enum nss_status _nss_mymachines_gethostbyname4_r(
goto fail;

if (c <= 0) {
*errnop = ESRCH;
*h_errnop = HOST_NOT_FOUND;
return NSS_STATUS_NOTFOUND;
}
Expand Down Expand Up @@ -200,8 +200,8 @@ enum nss_status _nss_mymachines_gethostbyname4_r(
if (ttlp)
*ttlp = 0;

/* Explicitly reset all error variables */
*errnop = 0;
/* Explicitly reset both *h_errnop and h_errno to work around
* https://bugzilla.redhat.com/show_bug.cgi?id=1125975 */
*h_errnop = NETDB_SUCCESS;
h_errno = 0;

Expand Down Expand Up @@ -230,6 +230,7 @@ enum nss_status _nss_mymachines_gethostbyname3_r(
size_t l, idx, ms, alen;
int r;

PROTECT_ERRNO;
BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);

assert(name);
Expand Down Expand Up @@ -278,7 +279,6 @@ enum nss_status _nss_mymachines_gethostbyname3_r(
goto fail;

if (c <= 0) {
*errnop = ENOENT;
*h_errnop = HOST_NOT_FOUND;
return NSS_STATUS_NOTFOUND;
}
Expand Down Expand Up @@ -364,8 +364,8 @@ enum nss_status _nss_mymachines_gethostbyname3_r(
if (canonp)
*canonp = r_name;

/* Explicitly reset all error variables */
*errnop = 0;
/* Explicitly reset both *h_errnop and h_errno to work around
* https://bugzilla.redhat.com/show_bug.cgi?id=1125975 */
*h_errnop = NETDB_SUCCESS;
h_errno = 0;

Expand Down Expand Up @@ -394,35 +394,36 @@ enum nss_status _nss_mymachines_getpwnam_r(
size_t l;
int r;

PROTECT_ERRNO;
BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);

assert(name);
assert(pwd);

p = startswith(name, "vu-");
if (!p)
goto not_found;
return NSS_STATUS_NOTFOUND;

e = strrchr(p, '-');
if (!e || e == p)
goto not_found;
return NSS_STATUS_NOTFOUND;

if (e - p > HOST_NAME_MAX - 1) /* -1 for the last dash */
goto not_found;
return NSS_STATUS_NOTFOUND;

r = parse_uid(e + 1, &uid);
if (r < 0)
goto not_found;
return NSS_STATUS_NOTFOUND;

machine = strndupa(p, e - p);
if (!machine_name_is_valid(machine))
goto not_found;
return NSS_STATUS_NOTFOUND;

if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0)
/* Make sure we can't deadlock if we are invoked by dbus-daemon. This way, it won't be able to resolve
* these UIDs, but that should be unproblematic as containers should never be able to connect to a bus
* running on the host. */
goto not_found;
return NSS_STATUS_NOTFOUND;

r = sd_bus_open_system(&bus);
if (r < 0)
Expand All @@ -439,7 +440,7 @@ enum nss_status _nss_mymachines_getpwnam_r(
machine, (uint32_t) uid);
if (r < 0) {
if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_USER_MAPPING))
goto not_found;
return NSS_STATUS_NOTFOUND;

goto fail;
}
Expand All @@ -450,7 +451,7 @@ enum nss_status _nss_mymachines_getpwnam_r(

/* Refuse to work if the mapped address is in the host UID range, or if there was no mapping at all. */
if (mapped < HOST_UID_LIMIT || mapped == uid)
goto not_found;
return NSS_STATUS_NOTFOUND;

l = strlen(name);
if (buflen < l+1) {
Expand All @@ -468,13 +469,8 @@ enum nss_status _nss_mymachines_getpwnam_r(
pwd->pw_dir = (char*) "/";
pwd->pw_shell = (char*) "/sbin/nologin";

*errnop = 0;
return NSS_STATUS_SUCCESS;

not_found:
*errnop = 0;
return NSS_STATUS_NOTFOUND;

fail:
*errnop = -r;
return NSS_STATUS_UNAVAIL;
Expand All @@ -493,17 +489,18 @@ enum nss_status _nss_mymachines_getpwuid_r(
uint32_t mapped;
int r;

PROTECT_ERRNO;
BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);

if (!uid_is_valid(uid))
goto not_found;
return NSS_STATUS_NOTFOUND;

/* We consider all uids < 65536 host uids */
if (uid < HOST_UID_LIMIT)
goto not_found;
return NSS_STATUS_NOTFOUND;

if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0)
goto not_found;
return NSS_STATUS_NOTFOUND;

r = sd_bus_open_system(&bus);
if (r < 0)
Expand All @@ -520,7 +517,7 @@ enum nss_status _nss_mymachines_getpwuid_r(
(uint32_t) uid);
if (r < 0) {
if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_USER_MAPPING))
goto not_found;
return NSS_STATUS_NOTFOUND;

goto fail;
}
Expand All @@ -530,7 +527,7 @@ enum nss_status _nss_mymachines_getpwuid_r(
goto fail;

if (mapped == uid)
goto not_found;
return NSS_STATUS_NOTFOUND;

if (snprintf(buffer, buflen, "vu-%s-" UID_FMT, machine, (uid_t) mapped) >= (int) buflen) {
*errnop = ERANGE;
Expand All @@ -545,13 +542,8 @@ enum nss_status _nss_mymachines_getpwuid_r(
pwd->pw_dir = (char*) "/";
pwd->pw_shell = (char*) "/sbin/nologin";

*errnop = 0;
return NSS_STATUS_SUCCESS;

not_found:
*errnop = 0;
return NSS_STATUS_NOTFOUND;

fail:
*errnop = -r;
return NSS_STATUS_UNAVAIL;
Expand All @@ -574,32 +566,33 @@ enum nss_status _nss_mymachines_getgrnam_r(
size_t l;
int r;

PROTECT_ERRNO;
BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);

assert(name);
assert(gr);

p = startswith(name, "vg-");
if (!p)
goto not_found;
return NSS_STATUS_NOTFOUND;

e = strrchr(p, '-');
if (!e || e == p)
goto not_found;
return NSS_STATUS_NOTFOUND;

if (e - p > HOST_NAME_MAX - 1) /* -1 for the last dash */
goto not_found;
return NSS_STATUS_NOTFOUND;

r = parse_gid(e + 1, &gid);
if (r < 0)
goto not_found;
return NSS_STATUS_NOTFOUND;

machine = strndupa(p, e - p);
if (!machine_name_is_valid(machine))
goto not_found;
return NSS_STATUS_NOTFOUND;

if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0)
goto not_found;
return NSS_STATUS_NOTFOUND;

r = sd_bus_open_system(&bus);
if (r < 0)
Expand All @@ -616,7 +609,7 @@ enum nss_status _nss_mymachines_getgrnam_r(
machine, (uint32_t) gid);
if (r < 0) {
if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_GROUP_MAPPING))
goto not_found;
return NSS_STATUS_NOTFOUND;

goto fail;
}
Expand All @@ -626,7 +619,7 @@ enum nss_status _nss_mymachines_getgrnam_r(
goto fail;

if (mapped < HOST_GID_LIMIT || mapped == gid)
goto not_found;
return NSS_STATUS_NOTFOUND;

l = sizeof(char*) + strlen(name) + 1;
if (buflen < l) {
Expand All @@ -642,13 +635,8 @@ enum nss_status _nss_mymachines_getgrnam_r(
gr->gr_passwd = (char*) "*"; /* locked */
gr->gr_mem = (char**) buffer;

*errnop = 0;
return NSS_STATUS_SUCCESS;

not_found:
*errnop = 0;
return NSS_STATUS_NOTFOUND;

fail:
*errnop = -r;
return NSS_STATUS_UNAVAIL;
Expand All @@ -667,17 +655,18 @@ enum nss_status _nss_mymachines_getgrgid_r(
uint32_t mapped;
int r;

PROTECT_ERRNO;
BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);

if (!gid_is_valid(gid))
goto not_found;
return NSS_STATUS_NOTFOUND;

/* We consider all gids < 65536 host gids */
if (gid < HOST_GID_LIMIT)
goto not_found;
return NSS_STATUS_NOTFOUND;

if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0)
goto not_found;
return NSS_STATUS_NOTFOUND;

r = sd_bus_open_system(&bus);
if (r < 0)
Expand All @@ -694,7 +683,7 @@ enum nss_status _nss_mymachines_getgrgid_r(
(uint32_t) gid);
if (r < 0) {
if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_GROUP_MAPPING))
goto not_found;
return NSS_STATUS_NOTFOUND;

goto fail;
}
Expand All @@ -704,7 +693,7 @@ enum nss_status _nss_mymachines_getgrgid_r(
goto fail;

if (mapped == gid)
goto not_found;
return NSS_STATUS_NOTFOUND;

if (buflen < sizeof(char*) + 1) {
*errnop = ERANGE;
Expand All @@ -722,13 +711,8 @@ enum nss_status _nss_mymachines_getgrgid_r(
gr->gr_passwd = (char*) "*"; /* locked */
gr->gr_mem = (char**) buffer;

*errnop = 0;
return NSS_STATUS_SUCCESS;

not_found:
*errnop = 0;
return NSS_STATUS_NOTFOUND;

fail:
*errnop = -r;
return NSS_STATUS_UNAVAIL;
Expand Down
Loading

0 comments on commit 06202b9

Please sign in to comment.