From 38ccb55731e5c288fd086344bbb07a7167a78d2b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 7 Jul 2020 21:58:12 +0200 Subject: [PATCH] nss-mymachines: drop support for UID/GID resolving Now that we make the user/group name resolving available via userdb and thus nss-systemd, we do not need the UID/GID resolving support in nss-mymachines anymore. Let's drop it hence. We keep the module around, since besides UID/GID resolving it also does hostname resolving, which we care about. (One of those days we should replace that by some Varlink logic between nss-resolve/systemd-resolved.service too) The hooks are kept in the NSS module, but they do not resolve anything anymore, in order to keep compat at a maximum. --- README | 22 +- docs/UIDS-GIDS.md | 6 +- factory/etc/nsswitch.conf | 4 +- man/nss-myhostname.xml | 4 +- man/nss-mymachines.xml | 48 +---- man/nss-resolve.xml | 4 +- man/nss-systemd.xml | 4 +- src/nspawn/nspawn.c | 2 +- src/nss-mymachines/nss-mymachines.c | 312 +--------------------------- 9 files changed, 35 insertions(+), 371 deletions(-) diff --git a/README b/README index 4269f0c73d..558b8d9195 100644 --- a/README +++ b/README @@ -262,19 +262,19 @@ USERS AND GROUPS: NSS: systemd ships with four glibc NSS modules: - nss-myhostname resolves the local hostname to locally - configured IP addresses, as well as "localhost" to - 127.0.0.1/::1. + nss-myhostname resolves the local hostname to locally configured IP + addresses, as well as "localhost" to 127.0.0.1/::1. - nss-resolve enables DNS resolution via the systemd-resolved - DNS/LLMNR caching stub resolver "systemd-resolved". + nss-resolve enables DNS resolution via the systemd-resolved DNS/LLMNR + caching stub resolver "systemd-resolved". nss-mymachines enables resolution of all local containers registered - with machined to their respective IP addresses. It also maps UID/GIDs - ranges used by containers to useful names. + with machined to their respective IP addresses. - nss-systemd enables resolution of all dynamically allocated service - users. (See the DynamicUser= setting in unit files.) + nss-systemd enables resolution of users/group registered via the + User/Group Record Lookup API (https://systemd.io/USER_GROUP_API/), + including all dynamically allocated service users. (See the + DynamicUser= setting in unit files.) To make use of these NSS modules, please add them to the "hosts:", "passwd:" and "group:" lines in /etc/nsswitch.conf. The "resolve" @@ -283,8 +283,8 @@ NSS: The four modules should be used in the following order: - passwd: compat mymachines systemd - group: compat mymachines systemd + passwd: compat systemd + group: compat systemd hosts: files mymachines resolve [!UNAVAIL=return] dns myhostname SYSV INIT.D SCRIPTS: diff --git a/docs/UIDS-GIDS.md b/docs/UIDS-GIDS.md index c41c4d7eec..67e6d083ff 100644 --- a/docs/UIDS-GIDS.md +++ b/docs/UIDS-GIDS.md @@ -132,7 +132,7 @@ but downstreams are strongly advised against doing that.) range is above the 16bit boundary. Moreover it's below the 31bit boundary, as some broken code (specifically: the kernel's `devpts` file system) erroneously considers UIDs signed integers, and hence can't deal with values - above 2^31. The `nss-mymachines` glibc NSS module will synthesize user + above 2^31. The `systemd-machined.service` service will synthesize user database records for all UIDs assigned to a running container from this range. @@ -240,14 +240,14 @@ the artifacts the container manager persistently leaves in the system. | 5 | `tty` group | `systemd` | `/etc/passwd` | | 6…999 | System users | Distributions | `/etc/passwd` | | 1000…60000 | Regular users | Distributions | `/etc/passwd` + LDAP/NIS/… | -| 60001…60513 | Human Users (homed) | `systemd` | `nss-systemd` +| 60001…60513 | Human Users (homed) | `systemd` | `nss-systemd` | | 60514…61183 | Unused | | | | 61184…65519 | Dynamic service users | `systemd` | `nss-systemd` | | 65520…65533 | Unused | | | | 65534 | `nobody` user | Linux | `/etc/passwd` + `nss-systemd` | | 65535 | 16bit `(uid_t) -1` | Linux | | | 65536…524287 | Unused | | | -| 524288…1879048191 | Container UID ranges | `systemd` | `nss-mymachines` | +| 524288…1879048191 | Container UID ranges | `systemd` | `nss-systemd` | | 1879048192…2147483647 | Unused | | | | 2147483648…4294967294 | HIC SVNT LEONES | | | | 4294967295 | 32bit `(uid_t) -1` | Linux | | diff --git a/factory/etc/nsswitch.conf b/factory/etc/nsswitch.conf index e7365cd142..da74b19d90 100644 --- a/factory/etc/nsswitch.conf +++ b/factory/etc/nsswitch.conf @@ -1,7 +1,7 @@ # This file is part of systemd. -passwd: compat mymachines systemd -group: compat [SUCCESS=merge] mymachines [SUCCESS=merge] systemd +passwd: compat systemd +group: compat [SUCCESS=merge] systemd shadow: compat hosts: files mymachines resolve [!UNAVAIL=return] dns myhostname diff --git a/man/nss-myhostname.xml b/man/nss-myhostname.xml index 8bb21f2621..a41c383bb3 100644 --- a/man/nss-myhostname.xml +++ b/man/nss-myhostname.xml @@ -82,8 +82,8 @@ nss-myhostname correctly: -passwd: compat mymachines systemd -group: compat mymachines systemd +passwd: compat systemd +group: compat systemd shadow: compat # Either (untrusted network): diff --git a/man/nss-mymachines.xml b/man/nss-mymachines.xml index 6e48835550..e0e6989c40 100644 --- a/man/nss-mymachines.xml +++ b/man/nss-mymachines.xml @@ -39,22 +39,13 @@ Note that the name that is resolved is the one registered with systemd-machined, which may be different than the hostname configured inside of the container. - The module also provides name resolution for user and group identifiers mapped to containers. All names from - the range allocated to a given container container are exposed on the host as - vu-container-uid and - vg-container-gid (see example below). This - functionality only applies to containers using user namespacing (see the description of - in - systemd-nspawn1). - - To activate the NSS module, add mymachines to the lines starting with - hosts:, passwd: and group: in - /etc/nsswitch.conf. + To activate the NSS module, add mymachines to the line starting with + hosts: in /etc/nsswitch.conf. It is recommended to place mymachines after the files or - compat entry of the /etc/nsswitch.conf lines to make sure that its mappings - are preferred over other resolvers such as DNS, but so that /etc/hosts, - /etc/passwd and /etc/group based mappings take precedence. + compat entry of the /etc/nsswitch.conf line to make sure that its + mappings are preferred over other resolvers such as DNS, but so that /etc/hosts + based mappings take precedence. @@ -64,8 +55,8 @@ nss-mymachines correctly: - passwd: compat mymachines systemd -group: compat mymachines systemd + passwd: compat systemd +group: compat systemd shadow: compat hosts: mymachines resolve [!UNAVAIL=return] myhostname files dns @@ -81,7 +72,7 @@ netgroup: nis - Mappings provided by <filename>nss-mymachines</filename> + Example: Mappings provided by <filename>nss-mymachines</filename> The container rawhide is spawned using systemd-nspawn1: @@ -96,29 +87,6 @@ $ machinectl --max-addresses=3 MACHINE CLASS SERVICE OS VERSION ADDRESSES rawhide container systemd-nspawn fedora 30 169.254.40.164 fe80::94aa:3aff:fe7b:d4b9 -$ getent passwd vu-rawhide-0 vu-rawhide-81 -vu-rawhide-0:*:20119552:65534:vu-rawhide-0:/:/usr/sbin/nologin -vu-rawhide-81:*:20119633:65534:vu-rawhide-81:/:/usr/sbin/nologin - -$ getent group vg-rawhide-0 vg-rawhide-81 -vg-rawhide-0:*:20119552: -vg-rawhide-81:*:20119633: - -$ ps -o user:15,pid,tty,command -e|grep '^vu-rawhide' -vu-rawhide-0 692 ? /usr/lib/systemd/systemd -vu-rawhide-0 731 ? /usr/lib/systemd/systemd-journald -vu-rawhide-192 734 ? /usr/lib/systemd/systemd-networkd -vu-rawhide-193 738 ? /usr/lib/systemd/systemd-resolved -vu-rawhide-0 742 ? /usr/lib/systemd/systemd-logind -vu-rawhide-81 744 ? /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only -vu-rawhide-0 746 ? /usr/sbin/sshd -D ... -vu-rawhide-0 752 ? /usr/lib/systemd/systemd --user -vu-rawhide-0 753 ? (sd-pam) -vu-rawhide-0 1628 ? login -- zbyszek -vu-rawhide-1000 1630 ? /usr/lib/systemd/systemd --user -vu-rawhide-1000 1631 ? (sd-pam) -vu-rawhide-1000 1637 pts/8 -zsh - $ ping -c1 rawhide PING rawhide(fe80::94aa:3aff:fe7b:d4b9%ve-rawhide (fe80::94aa:3aff:fe7b:d4b9%ve-rawhide)) 56 data bytes 64 bytes from fe80::94aa:3aff:fe7b:d4b9%ve-rawhide (fe80::94aa:3aff:fe7b:d4b9%ve-rawhide): icmp_seq=1 ttl=64 time=0.045 ms diff --git a/man/nss-resolve.xml b/man/nss-resolve.xml index 332cf0b06d..c377468953 100644 --- a/man/nss-resolve.xml +++ b/man/nss-resolve.xml @@ -63,8 +63,8 @@ correctly: -passwd: compat mymachines systemd -group: compat mymachines systemd +passwd: compat systemd +group: compat systemd shadow: compat hosts: mymachines resolve [!UNAVAIL=return] myhostname files dns diff --git a/man/nss-systemd.xml b/man/nss-systemd.xml index ea293596be..34aee0e880 100644 --- a/man/nss-systemd.xml +++ b/man/nss-systemd.xml @@ -61,8 +61,8 @@ nss-systemd correctly: - passwd: compat mymachines systemd -group: compat [SUCCESS=merge] mymachines [SUCCESS=merge] systemd + passwd: compat systemd +group: compat [SUCCESS=merge] systemd shadow: compat hosts: mymachines resolve [!UNAVAIL=return] myhostname files dns diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 1f321f9ea3..330bd7e7d2 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -4636,7 +4636,7 @@ static int run_container( if (!barrier_place_and_sync(&barrier)) /* #5 */ return log_error_errno(SYNTHETIC_ERRNO(ESRCH), "Child died too early."); - /* At this point we have made use of the UID we picked, and thus nss-mymachines + /* At this point we have made use of the UID we picked, and thus nss-systemd/systemd-machined.service * will make them appear in getpwuid(), thus we can release the /etc/passwd lock. */ etc_passwd_lock = safe_close(etc_passwd_lock); diff --git a/src/nss-mymachines/nss-mymachines.c b/src/nss-mymachines/nss-mymachines.c index 9269e7fd7b..5db0dcef76 100644 --- a/src/nss-mymachines/nss-mymachines.c +++ b/src/nss-mymachines/nss-mymachines.c @@ -19,15 +19,11 @@ #include "nss-util.h" #include "signal-util.h" #include "string-util.h" -#include "user-util.h" NSS_GETHOSTBYNAME_PROTOTYPES(mymachines); NSS_GETPW_PROTOTYPES(mymachines); NSS_GETGR_PROTOTYPES(mymachines); -#define HOST_UID_LIMIT ((uid_t) UINT32_C(0x10000)) -#define HOST_GID_LIMIT ((gid_t) UINT32_C(0x10000)) - static int count_addresses(sd_bus_message *m, int af, unsigned *ret) { unsigned c = 0; int r; @@ -402,94 +398,7 @@ enum nss_status _nss_mymachines_getpwnam_r( char *buffer, size_t buflen, int *errnop) { - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL; - _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; - const char *p, *e, *machine; - uint32_t mapped; - uid_t uid; - size_t l; - int r; - - PROTECT_ERRNO; - BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); - - assert(name); - assert(pwd); - - p = startswith(name, "vu-"); - if (!p) - return NSS_STATUS_NOTFOUND; - - e = strrchr(p, '-'); - if (!e || e == p) - return NSS_STATUS_NOTFOUND; - - if (e - p > HOST_NAME_MAX - 1) /* -1 for the last dash */ - return NSS_STATUS_NOTFOUND; - - r = parse_uid(e + 1, &uid); - if (r < 0) - return NSS_STATUS_NOTFOUND; - - machine = strndupa(p, e - p); - if (!machine_name_is_valid(machine)) - 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. */ - return NSS_STATUS_NOTFOUND; - - if (avoid_deadlock()) { - r = -EDEADLK; - goto fail; - } - - r = sd_bus_open_system(&bus); - if (r < 0) - goto fail; - - r = bus_call_method(bus, bus_machine_mgr, "MapFromMachineUser", &error, &reply, "su", machine, (uint32_t) uid); - if (r < 0) { - if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_USER_MAPPING)) - return NSS_STATUS_NOTFOUND; - - goto fail; - } - - r = sd_bus_message_read(reply, "u", &mapped); - if (r < 0) - goto fail; - - /* 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) - return NSS_STATUS_NOTFOUND; - - l = strlen(name); - if (buflen < l+1) { - UNPROTECT_ERRNO; - *errnop = ERANGE; - return NSS_STATUS_TRYAGAIN; - } - - memcpy(buffer, name, l+1); - - pwd->pw_name = buffer; - pwd->pw_uid = mapped; - pwd->pw_gid = GID_NOBODY; - pwd->pw_gecos = buffer; - pwd->pw_passwd = (char*) "*"; /* locked */ - pwd->pw_dir = (char*) "/"; - pwd->pw_shell = (char*) NOLOGIN; - - return NSS_STATUS_SUCCESS; - -fail: - UNPROTECT_ERRNO; - *errnop = -r; - return NSS_STATUS_UNAVAIL; + return NSS_STATUS_NOTFOUND; } enum nss_status _nss_mymachines_getpwuid_r( @@ -498,162 +407,16 @@ enum nss_status _nss_mymachines_getpwuid_r( char *buffer, size_t buflen, int *errnop) { - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL; - _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; - const char *machine; - uint32_t mapped; - int r; - - PROTECT_ERRNO; - BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); - - if (!uid_is_valid(uid)) - return NSS_STATUS_NOTFOUND; - - /* We consider all uids < 65536 host uids */ - if (uid < HOST_UID_LIMIT) - return NSS_STATUS_NOTFOUND; - - if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0) - return NSS_STATUS_NOTFOUND; - - if (avoid_deadlock()) { - r = -EDEADLK; - goto fail; - } - - r = sd_bus_open_system(&bus); - if (r < 0) - goto fail; - - r = bus_call_method(bus, bus_machine_mgr, "MapToMachineUser", &error, &reply, "u", (uint32_t) uid); - if (r < 0) { - if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_USER_MAPPING)) - return NSS_STATUS_NOTFOUND; - - goto fail; - } - - r = sd_bus_message_read(reply, "sou", &machine, NULL, &mapped); - if (r < 0) - goto fail; - - if (mapped == uid) - return NSS_STATUS_NOTFOUND; - - if (snprintf(buffer, buflen, "vu-%s-" UID_FMT, machine, (uid_t) mapped) >= (int) buflen) { - UNPROTECT_ERRNO; - *errnop = ERANGE; - return NSS_STATUS_TRYAGAIN; - } - - pwd->pw_name = buffer; - pwd->pw_uid = uid; - pwd->pw_gid = GID_NOBODY; - pwd->pw_gecos = buffer; - pwd->pw_passwd = (char*) "*"; /* locked */ - pwd->pw_dir = (char*) "/"; - pwd->pw_shell = (char*) NOLOGIN; - - return NSS_STATUS_SUCCESS; - -fail: - UNPROTECT_ERRNO; - *errnop = -r; - return NSS_STATUS_UNAVAIL; + return NSS_STATUS_NOTFOUND; } -#pragma GCC diagnostic ignored "-Wsizeof-pointer-memaccess" - enum nss_status _nss_mymachines_getgrnam_r( const char *name, struct group *gr, char *buffer, size_t buflen, int *errnop) { - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL; - _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; - const char *p, *e, *machine; - uint32_t mapped; - uid_t gid; - size_t l; - int r; - - PROTECT_ERRNO; - BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); - - assert(name); - assert(gr); - - p = startswith(name, "vg-"); - if (!p) - return NSS_STATUS_NOTFOUND; - - e = strrchr(p, '-'); - if (!e || e == p) - return NSS_STATUS_NOTFOUND; - - if (e - p > HOST_NAME_MAX - 1) /* -1 for the last dash */ - return NSS_STATUS_NOTFOUND; - - r = parse_gid(e + 1, &gid); - if (r < 0) - return NSS_STATUS_NOTFOUND; - - machine = strndupa(p, e - p); - if (!machine_name_is_valid(machine)) - return NSS_STATUS_NOTFOUND; - - if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0) - return NSS_STATUS_NOTFOUND; - - if (avoid_deadlock()) { - r = -EDEADLK; - goto fail; - } - - r = sd_bus_open_system(&bus); - if (r < 0) - goto fail; - - r = bus_call_method(bus, bus_machine_mgr, "MapFromMachineGroup", &error, &reply, "su", machine, (uint32_t) gid); - if (r < 0) { - if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_GROUP_MAPPING)) - return NSS_STATUS_NOTFOUND; - - goto fail; - } - - r = sd_bus_message_read(reply, "u", &mapped); - if (r < 0) - goto fail; - - if (mapped < HOST_GID_LIMIT || mapped == gid) - return NSS_STATUS_NOTFOUND; - - l = sizeof(char*) + strlen(name) + 1; - if (buflen < l) { - UNPROTECT_ERRNO; - *errnop = ERANGE; - return NSS_STATUS_TRYAGAIN; - } - - memzero(buffer, sizeof(char*)); - strcpy(buffer + sizeof(char*), name); - - gr->gr_name = buffer + sizeof(char*); - gr->gr_gid = mapped; - gr->gr_passwd = (char*) "*"; /* locked */ - gr->gr_mem = (char**) buffer; - - return NSS_STATUS_SUCCESS; - -fail: - UNPROTECT_ERRNO; - *errnop = -r; - return NSS_STATUS_UNAVAIL; + return NSS_STATUS_NOTFOUND; } enum nss_status _nss_mymachines_getgrgid_r( @@ -662,72 +425,5 @@ enum nss_status _nss_mymachines_getgrgid_r( char *buffer, size_t buflen, int *errnop) { - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL; - _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; - const char *machine; - uint32_t mapped; - int r; - - PROTECT_ERRNO; - BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); - - if (!gid_is_valid(gid)) - return NSS_STATUS_NOTFOUND; - - /* We consider all gids < 65536 host gids */ - if (gid < HOST_GID_LIMIT) - return NSS_STATUS_NOTFOUND; - - if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0) - return NSS_STATUS_NOTFOUND; - - if (avoid_deadlock()) { - r = -EDEADLK; - goto fail; - } - - r = sd_bus_open_system(&bus); - if (r < 0) - goto fail; - - r = bus_call_method(bus, bus_machine_mgr, "MapToMachineGroup", &error, &reply, "u", (uint32_t) gid); - if (r < 0) { - if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_GROUP_MAPPING)) - return NSS_STATUS_NOTFOUND; - - goto fail; - } - - r = sd_bus_message_read(reply, "sou", &machine, NULL, &mapped); - if (r < 0) - goto fail; - - if (mapped == gid) - return NSS_STATUS_NOTFOUND; - - if (buflen < sizeof(char*) + 1) { - UNPROTECT_ERRNO; - *errnop = ERANGE; - return NSS_STATUS_TRYAGAIN; - } - - memzero(buffer, sizeof(char*)); - if (snprintf(buffer + sizeof(char*), buflen - sizeof(char*), "vg-%s-" GID_FMT, machine, (gid_t) mapped) >= (int) buflen) { - UNPROTECT_ERRNO; - *errnop = ERANGE; - return NSS_STATUS_TRYAGAIN; - } - - gr->gr_name = buffer + sizeof(char*); - gr->gr_gid = gid; - gr->gr_passwd = (char*) "*"; /* locked */ - gr->gr_mem = (char**) buffer; - - return NSS_STATUS_SUCCESS; - -fail: - UNPROTECT_ERRNO; - *errnop = -r; - return NSS_STATUS_UNAVAIL; + return NSS_STATUS_NOTFOUND; }