From f9bfa6962d3689acf50b3e51d5d4af3642d849d8 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 21 Mar 2018 13:11:01 +0900 Subject: [PATCH 1/5] core: add new dbus method GetDynamicUsers This intruduces a new dbus method GetDynamicUsers for systemd1.Manager, which enumerates all dynamic users realized in the system. --- src/core/dbus-manager.c | 45 ++++++++++++++++++++++++++ src/core/dynamic-user.c | 2 +- src/core/dynamic-user.h | 1 + src/core/org.freedesktop.systemd1.conf | 4 +++ 4 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index 889779d548..90e7f86389 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -1798,6 +1798,50 @@ static int method_lookup_dynamic_user_by_uid(sd_bus_message *message, void *user return sd_bus_reply_method_return(message, "s", name); } +static int method_get_dynamic_users(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + Manager *m = userdata; + DynamicUser *d; + Iterator i; + int r; + + assert(message); + assert(m); + + assert_cc(sizeof(uid_t) == sizeof(uint32_t)); + + if (!MANAGER_IS_SYSTEM(m)) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Dynamic users are only supported in the system instance."); + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "(us)"); + if (r < 0) + return r; + + HASHMAP_FOREACH(d, m->dynamic_users, i) { + uid_t uid; + + r = dynamic_user_current(d, &uid); + if (r == -EAGAIN) /* not realized yet? */ + continue; + if (r < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Failed to lookup a dynamic user."); + + r = sd_bus_message_append(reply, "(us)", uid, d->name); + if (r < 0) + return r; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} + static int list_unit_files_by_patterns(sd_bus_message *message, void *userdata, sd_bus_error *error, char **states, char **patterns) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; Manager *m = userdata; @@ -2572,6 +2616,7 @@ const sd_bus_vtable bus_manager_vtable[] = { SD_BUS_METHOD("SetExitCode", "y", NULL, method_set_exit_code, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("LookupDynamicUserByName", "s", "u", method_lookup_dynamic_user_by_name, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("LookupDynamicUserByUID", "u", "s", method_lookup_dynamic_user_by_uid, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetDynamicUsers", NULL, "a(us)", method_get_dynamic_users, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_SIGNAL("UnitNew", "so", 0), SD_BUS_SIGNAL("UnitRemoved", "so", 0), diff --git a/src/core/dynamic-user.c b/src/core/dynamic-user.c index 3da31bf870..de6aadd597 100644 --- a/src/core/dynamic-user.c +++ b/src/core/dynamic-user.c @@ -563,7 +563,7 @@ static int dynamic_user_realize( return 0; } -static int dynamic_user_current(DynamicUser *d, uid_t *ret) { +int dynamic_user_current(DynamicUser *d, uid_t *ret) { _cleanup_(unlockfp) int storage_socket0_lock = -1; _cleanup_close_ int lock_fd = -1; uid_t uid; diff --git a/src/core/dynamic-user.h b/src/core/dynamic-user.h index b073c65837..34befa3445 100644 --- a/src/core/dynamic-user.h +++ b/src/core/dynamic-user.h @@ -48,6 +48,7 @@ int dynamic_user_serialize(Manager *m, FILE *f, FDSet *fds); void dynamic_user_deserialize_one(Manager *m, const char *value, FDSet *fds); void dynamic_user_vacuum(Manager *m, bool close_user); +int dynamic_user_current(DynamicUser *d, uid_t *ret); int dynamic_user_lookup_uid(Manager *m, uid_t uid, char **ret); int dynamic_user_lookup_name(Manager *m, const char *name, uid_t *ret); diff --git a/src/core/org.freedesktop.systemd1.conf b/src/core/org.freedesktop.systemd1.conf index 645c8f1659..5e72fe7e8e 100644 --- a/src/core/org.freedesktop.systemd1.conf +++ b/src/core/org.freedesktop.systemd1.conf @@ -140,6 +140,10 @@ send_interface="org.freedesktop.systemd1.Manager" send_member="LookupDynamicUserByUID"/> + + Date: Tue, 6 Mar 2018 21:31:16 +0900 Subject: [PATCH 2/5] nss-systemd: cleanup bypassing dbus logic --- src/nss-systemd/nss-systemd.c | 111 +++++++++++++++------------------- 1 file changed, 48 insertions(+), 63 deletions(-) diff --git a/src/nss-systemd/nss-systemd.c b/src/nss-systemd/nss-systemd.c index c502b5f5fd..d64fa2521b 100644 --- a/src/nss-systemd/nss-systemd.c +++ b/src/nss-systemd/nss-systemd.c @@ -115,6 +115,9 @@ enum nss_status _nss_systemd_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; uint32_t translated; size_t l; int bypass, r; @@ -150,16 +153,18 @@ enum nss_status _nss_systemd_getpwnam_r( bypass = getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS"); if (bypass <= 0) { - _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; - r = sd_bus_open_system(&bus); - if (r < 0) { + if (r < 0) bypass = 1; - goto direct_lookup; - } + } + if (bypass > 0) { + r = direct_lookup_name(name, (uid_t*) &translated); + if (r == -ENOENT) + goto not_found; + if (r < 0) + goto fail; + } else { r = sd_bus_call_method(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", @@ -181,16 +186,6 @@ enum nss_status _nss_systemd_getpwnam_r( goto fail; } -direct_lookup: - if (bypass > 0) { - /* Access the dynamic UID allocation directly if we are called from dbus-daemon, see above. */ - r = direct_lookup_name(name, (uid_t*) &translated); - if (r == -ENOENT) - goto not_found; - if (r < 0) - goto fail; - } - l = strlen(name); if (buflen < l+1) { *errnop = ERANGE; @@ -262,11 +257,20 @@ enum nss_status _nss_systemd_getpwuid_r( bypass = getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS"); if (bypass <= 0) { r = sd_bus_open_system(&bus); - if (r < 0) { + if (r < 0) bypass = 1; - goto direct_lookup; - } + } + if (bypass > 0) { + r = direct_lookup_uid(uid, &direct); + if (r == -ENOENT) + goto not_found; + if (r < 0) + goto fail; + + translated = direct; + + } else { r = sd_bus_call_method(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", @@ -288,18 +292,6 @@ enum nss_status _nss_systemd_getpwuid_r( goto fail; } -direct_lookup: - if (bypass > 0) { - r = direct_lookup_uid(uid, &direct); - if (r == -ENOENT) - goto not_found; - if (r < 0) - goto fail; - - translated = direct; - - } - l = strlen(translated) + 1; if (buflen < l) { *errnop = ERANGE; @@ -336,6 +328,9 @@ enum nss_status _nss_systemd_getgrnam_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; uint32_t translated; size_t l; int bypass, r; @@ -368,16 +363,18 @@ enum nss_status _nss_systemd_getgrnam_r( bypass = getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS"); if (bypass <= 0) { - _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; - r = sd_bus_open_system(&bus); - if (r < 0) { + if (r < 0) bypass = 1; - goto direct_lookup; - } + } + if (bypass > 0) { + r = direct_lookup_name(name, (uid_t*) &translated); + if (r == -ENOENT) + goto not_found; + if (r < 0) + goto fail; + } else { r = sd_bus_call_method(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", @@ -399,16 +396,6 @@ enum nss_status _nss_systemd_getgrnam_r( goto fail; } -direct_lookup: - if (bypass > 0) { - /* Access the dynamic GID allocation directly if we are called from dbus-daemon, see above. */ - r = direct_lookup_name(name, (uid_t*) &translated); - if (r == -ENOENT) - goto not_found; - if (r < 0) - goto fail; - } - l = sizeof(char*) + strlen(name) + 1; if (buflen < l) { *errnop = ERANGE; @@ -478,11 +465,20 @@ enum nss_status _nss_systemd_getgrgid_r( bypass = getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS"); if (bypass <= 0) { r = sd_bus_open_system(&bus); - if (r < 0) { + if (r < 0) bypass = 1; - goto direct_lookup; - } + } + if (bypass > 0) { + r = direct_lookup_uid(gid, &direct); + if (r == -ENOENT) + goto not_found; + if (r < 0) + goto fail; + + translated = direct; + + } else { r = sd_bus_call_method(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", @@ -504,17 +500,6 @@ enum nss_status _nss_systemd_getgrgid_r( goto fail; } -direct_lookup: - if (bypass > 0) { - r = direct_lookup_uid(gid, &direct); - if (r == -ENOENT) - goto not_found; - if (r < 0) - goto fail; - - translated = direct; - } - l = sizeof(char*) + strlen(translated) + 1; if (buflen < l) { *errnop = ERANGE; From 9b5eaef3d10544ae0c65f6671f2bb97f7fe1d090 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 6 Mar 2018 15:39:26 +0900 Subject: [PATCH 3/5] nss-systemd: define dynamic user properties --- src/nss-systemd/nss-systemd.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/nss-systemd/nss-systemd.c b/src/nss-systemd/nss-systemd.c index d64fa2521b..a8705e6677 100644 --- a/src/nss-systemd/nss-systemd.c +++ b/src/nss-systemd/nss-systemd.c @@ -34,6 +34,11 @@ #include "user-util.h" #include "util.h" +#define DYNAMIC_USER_GECOS "Dynamic User" +#define DYNAMIC_USER_PASSWD "*" /* locked */ +#define DYNAMIC_USER_DIR "/" +#define DYNAMIC_USER_SHELL "/sbin/nologin" + static const struct passwd root_passwd = { .pw_name = (char*) "root", .pw_passwd = (char*) "x", /* see shadow file */ @@ -197,10 +202,10 @@ enum nss_status _nss_systemd_getpwnam_r( pwd->pw_name = buffer; pwd->pw_uid = (uid_t) translated; pwd->pw_gid = (uid_t) translated; - pwd->pw_gecos = (char*) "Dynamic User"; - pwd->pw_passwd = (char*) "*"; /* locked */ - pwd->pw_dir = (char*) "/"; - pwd->pw_shell = (char*) "/sbin/nologin"; + pwd->pw_gecos = (char*) DYNAMIC_USER_GECOS; + pwd->pw_passwd = (char*) DYNAMIC_USER_PASSWD; + pwd->pw_dir = (char*) DYNAMIC_USER_DIR; + pwd->pw_shell = (char*) DYNAMIC_USER_SHELL; *errnop = 0; return NSS_STATUS_SUCCESS; @@ -303,10 +308,10 @@ enum nss_status _nss_systemd_getpwuid_r( pwd->pw_name = buffer; pwd->pw_uid = uid; pwd->pw_gid = uid; - pwd->pw_gecos = (char*) "Dynamic User"; - pwd->pw_passwd = (char*) "*"; /* locked */ - pwd->pw_dir = (char*) "/"; - pwd->pw_shell = (char*) "/sbin/nologin"; + pwd->pw_gecos = (char*) DYNAMIC_USER_GECOS; + pwd->pw_passwd = (char*) DYNAMIC_USER_PASSWD; + pwd->pw_dir = (char*) DYNAMIC_USER_DIR; + pwd->pw_shell = (char*) DYNAMIC_USER_SHELL; *errnop = 0; return NSS_STATUS_SUCCESS; @@ -407,7 +412,7 @@ enum nss_status _nss_systemd_getgrnam_r( gr->gr_name = buffer + sizeof(char*); gr->gr_gid = (gid_t) translated; - gr->gr_passwd = (char*) "*"; /* locked */ + gr->gr_passwd = (char*) DYNAMIC_USER_PASSWD; gr->gr_mem = (char**) buffer; *errnop = 0; @@ -511,7 +516,7 @@ enum nss_status _nss_systemd_getgrgid_r( gr->gr_name = buffer + sizeof(char*); gr->gr_gid = gid; - gr->gr_passwd = (char*) "*"; /* locked */ + gr->gr_passwd = (char*) DYNAMIC_USER_PASSWD; gr->gr_mem = (char**) buffer; *errnop = 0; From 12c2c56dcbd03dde58c89d3d96c19da7bee04881 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 21 Mar 2018 13:39:03 +0900 Subject: [PATCH 4/5] nss-systemd: make dynamic users enumerable by `getent` This adds `setpwent()`, `getpwent_r()`, `endpwent()`, `setgrent()`, `getgrent_r()`, and `endgrent()` interfaces to nss-systemd library. Thus, dynamic users can be enumerated by e.g. `getent passwd` command. --- src/nss-systemd/nss-systemd.c | 332 ++++++++++++++++++++++++++++++++ src/nss-systemd/nss-systemd.sym | 6 + 2 files changed, 338 insertions(+) diff --git a/src/nss-systemd/nss-systemd.c b/src/nss-systemd/nss-systemd.c index a8705e6677..d5a061a551 100644 --- a/src/nss-systemd/nss-systemd.c +++ b/src/nss-systemd/nss-systemd.c @@ -19,13 +19,17 @@ ***/ #include +#include #include "sd-bus.h" #include "alloc-util.h" #include "bus-common-errors.h" +#include "dirent-util.h" #include "env-util.h" +#include "fd-util.h" #include "fs-util.h" +#include "list.h" #include "macro.h" #include "nss-util.h" #include "signal-util.h" @@ -73,8 +77,40 @@ static const struct group nobody_group = { .gr_mem = (char*[]) { NULL }, }; +typedef struct UserEntry UserEntry; +typedef struct GetentData GetentData; + +struct UserEntry { + uid_t id; + char *name; + + GetentData *data; + LIST_FIELDS(UserEntry, entries); +}; + +struct GetentData { + /* As explained in NOTES section of getpwent_r(3) as 'getpwent_r() is not really + * reentrant since it shares the reading position in the stream with all other threads', + * we need to protect the data in UserEntry from multithreaded programs which may call + * setpwent(), getpwent_r(), or endpwent() simultaneously. So, each function locks the + * data by using the mutex below. */ + pthread_mutex_t mutex; + + UserEntry *position; + LIST_HEAD(UserEntry, entries); +}; + +static GetentData getpwent_data = { PTHREAD_MUTEX_INITIALIZER, NULL, NULL }; +static GetentData getgrent_data = { PTHREAD_MUTEX_INITIALIZER, NULL, NULL }; + NSS_GETPW_PROTOTYPES(systemd); NSS_GETGR_PROTOTYPES(systemd); +enum nss_status _nss_systemd_endpwent(void) _public_; +enum nss_status _nss_systemd_setpwent(int stayopen) _public_; +enum nss_status _nss_systemd_getpwent_r(struct passwd *result, char *buffer, size_t buflen, int *errnop) _public_; +enum nss_status _nss_systemd_endgrent(void) _public_; +enum nss_status _nss_systemd_setgrent(int stayopen) _public_; +enum nss_status _nss_systemd_getgrent_r(struct group *result, char *buffer, size_t buflen, int *errnop) _public_; static int direct_lookup_name(const char *name, uid_t *ret) { _cleanup_free_ char *s = NULL; @@ -530,3 +566,299 @@ fail: *errnop = -r; return NSS_STATUS_UNAVAIL; } + +static void user_entry_free(UserEntry *p) { + if (!p) + return; + + if (p->data) + LIST_REMOVE(entries, p->data->entries, p); + + free(p->name); + free(p); +} + +static int user_entry_add(GetentData *data, const char *name, uid_t id) { + UserEntry *p; + + assert(data); + + /* This happens when User= or Group= already exists statically. */ + if (!uid_is_dynamic(id)) + return -EINVAL; + + p = new0(UserEntry, 1); + if (!p) + return -ENOMEM; + + p->name = strdup(name); + if (!p->name) { + free(p); + return -ENOMEM; + } + p->id = id; + p->data = data; + + LIST_PREPEND(entries, data->entries, p); + + return 0; +} + +static void systemd_endent(GetentData *data) { + UserEntry *p; + + assert(data); + + while ((p = data->entries)) + user_entry_free(p); + + data->position = NULL; +} + +static enum nss_status nss_systemd_endent(GetentData *p) { + BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); + + assert_se(pthread_mutex_lock(&p->mutex) == 0); + systemd_endent(p); + assert_se(pthread_mutex_unlock(&p->mutex) == 0); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status _nss_systemd_endpwent(void) { + return nss_systemd_endent(&getpwent_data); +} + +enum nss_status _nss_systemd_endgrent(void) { + return nss_systemd_endent(&getgrent_data); +} + +static int direct_enumeration(GetentData *p) { + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + int r; + + assert(p); + + d = opendir("/run/systemd/dynamic-uid/"); + if (!d) + return -errno; + + FOREACH_DIRENT(de, d, return -errno) { + _cleanup_free_ char *name = NULL; + uid_t uid, verified; + + if (!dirent_is_file(de)) + continue; + + r = parse_uid(de->d_name, &uid); + if (r < 0) + continue; + + r = direct_lookup_uid(uid, &name); + if (r == -ENOMEM) + return r; + if (r < 0) + continue; + + r = direct_lookup_name(name, &verified); + if (r < 0) + continue; + + if (uid != verified) + continue; + + r = user_entry_add(p, name, uid); + if (r == -ENOMEM) + return r; + if (r < 0) + continue; + } + + return 0; +} + +static enum nss_status systemd_setent(GetentData *p) { + _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 *name; + uid_t id; + int bypass, r; + + BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); + + assert(p); + + assert_se(pthread_mutex_lock(&p->mutex) == 0); + + systemd_endent(p); + + if (getenv_bool_secure("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0) + goto finish; + + bypass = getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS"); + + if (bypass <= 0) { + r = sd_bus_open_system(&bus); + if (r < 0) + bypass = 1; + } + + if (bypass > 0) { + r = direct_enumeration(p); + if (r < 0) + goto fail; + + goto finish; + } + + r = sd_bus_call_method(bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "GetDynamicUsers", + &error, + &reply, + NULL); + if (r < 0) + goto fail; + + r = sd_bus_message_enter_container(reply, 'a', "(us)"); + if (r < 0) + goto fail; + + while ((r = sd_bus_message_read(reply, "(us)", &id, &name)) > 0) { + r = user_entry_add(p, name, id); + if (r == -ENOMEM) + goto fail; + if (r < 0) + continue; + } + if (r < 0) + goto fail; + + r = sd_bus_message_exit_container(reply); + if (r < 0) + goto fail; + +finish: + p->position = p->entries; + assert_se(pthread_mutex_unlock(&p->mutex) == 0); + + return NSS_STATUS_SUCCESS; + +fail: + systemd_endent(p); + assert_se(pthread_mutex_unlock(&p->mutex) == 0); + + return NSS_STATUS_UNAVAIL; +} + +enum nss_status _nss_systemd_setpwent(int stayopen) { + return systemd_setent(&getpwent_data); +} + +enum nss_status _nss_systemd_setgrent(int stayopen) { + return systemd_setent(&getgrent_data); +} + +enum nss_status _nss_systemd_getpwent_r(struct passwd *result, char *buffer, size_t buflen, int *errnop) { + enum nss_status ret; + UserEntry *p; + size_t len; + + BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); + + assert(result); + assert(buffer); + assert(errnop); + + assert_se(pthread_mutex_lock(&getpwent_data.mutex) == 0); + + LIST_FOREACH(entries, p, getpwent_data.position) { + len = strlen(p->name) + 1; + if (buflen < len) { + *errnop = ERANGE; + ret = NSS_STATUS_TRYAGAIN; + goto finalize; + } + + memcpy(buffer, p->name, len); + + result->pw_name = buffer; + result->pw_uid = p->id; + result->pw_gid = p->id; + result->pw_gecos = (char*) DYNAMIC_USER_GECOS; + result->pw_passwd = (char*) DYNAMIC_USER_PASSWD; + result->pw_dir = (char*) DYNAMIC_USER_DIR; + result->pw_shell = (char*) DYNAMIC_USER_SHELL; + break; + } + if (!p) { + *errnop = ENOENT; + ret = NSS_STATUS_NOTFOUND; + goto finalize; + } + + /* On success, step to the next entry. */ + p = p->entries_next; + ret = NSS_STATUS_SUCCESS; + +finalize: + /* Save position for the next call. */ + getpwent_data.position = p; + + assert_se(pthread_mutex_unlock(&getpwent_data.mutex) == 0); + + return ret; +} + +enum nss_status _nss_systemd_getgrent_r(struct group *result, char *buffer, size_t buflen, int *errnop) { + enum nss_status ret; + UserEntry *p; + size_t len; + + BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); + + assert(result); + assert(buffer); + assert(errnop); + + assert_se(pthread_mutex_lock(&getgrent_data.mutex) == 0); + + LIST_FOREACH(entries, p, getgrent_data.position) { + len = sizeof(char*) + strlen(p->name) + 1; + if (buflen < len) { + *errnop = ERANGE; + ret = NSS_STATUS_TRYAGAIN; + goto finalize; + } + + memzero(buffer, sizeof(char*)); + strcpy(buffer + sizeof(char*), p->name); + + result->gr_name = buffer + sizeof(char*); + result->gr_gid = p->id; + result->gr_passwd = (char*) DYNAMIC_USER_PASSWD; + result->gr_mem = (char**) buffer; + break; + } + if (!p) { + *errnop = ENOENT; + ret = NSS_STATUS_NOTFOUND; + goto finalize; + } + + /* On success, step to the next entry. */ + p = p->entries_next; + ret = NSS_STATUS_SUCCESS; + +finalize: + /* Save position for the next call. */ + getgrent_data.position = p; + + assert_se(pthread_mutex_unlock(&getgrent_data.mutex) == 0); + + return ret; +} diff --git a/src/nss-systemd/nss-systemd.sym b/src/nss-systemd/nss-systemd.sym index e3fe56f684..95038c833b 100644 --- a/src/nss-systemd/nss-systemd.sym +++ b/src/nss-systemd/nss-systemd.sym @@ -13,7 +13,13 @@ global: _nss_systemd_getpwnam_r; _nss_systemd_getpwuid_r; + _nss_systemd_endpwent; + _nss_systemd_setpwent; + _nss_systemd_getpwent_r; _nss_systemd_getgrnam_r; _nss_systemd_getgrgid_r; + _nss_systemd_endgrent; + _nss_systemd_setgrent; + _nss_systemd_getgrent_r; local: *; }; From 23e6c10bbe7b5dd83f575ca20d11105fe70c48a9 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 8 Mar 2018 12:53:43 +0900 Subject: [PATCH 5/5] doc: update TODO --- TODO | 3 --- 1 file changed, 3 deletions(-) diff --git a/TODO b/TODO index b21166f90b..8797506c6f 100644 --- a/TODO +++ b/TODO @@ -27,9 +27,6 @@ Features: * add proper dbus APIs for the various sd_notify() commands, such as MAINPID=1 and so on, which would mean we could report errors and such. -* nss-systemd: implement enumeration, that shows all dynamic users plus the - synthesized ones if necessary, so that "getent passwd" shows useful data. - * teach tmpfiles.d q/Q logic something sensible in the context of XFS/ext4 project quota