| File: | build-scan/../src/nss-systemd/nss-systemd.c |
| Warning: | line 579, column 17 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ | |||
| 2 | ||||
| 3 | #include <nss.h> | |||
| 4 | #include <pthread.h> | |||
| 5 | ||||
| 6 | #include "sd-bus.h" | |||
| 7 | ||||
| 8 | #include "alloc-util.h" | |||
| 9 | #include "bus-common-errors.h" | |||
| 10 | #include "dirent-util.h" | |||
| 11 | #include "env-util.h" | |||
| 12 | #include "fd-util.h" | |||
| 13 | #include "fs-util.h" | |||
| 14 | #include "list.h" | |||
| 15 | #include "macro.h" | |||
| 16 | #include "nss-util.h" | |||
| 17 | #include "signal-util.h" | |||
| 18 | #include "stdio-util.h" | |||
| 19 | #include "string-util.h" | |||
| 20 | #include "user-util.h" | |||
| 21 | #include "util.h" | |||
| 22 | ||||
| 23 | #define DYNAMIC_USER_GECOS"Dynamic User" "Dynamic User" | |||
| 24 | #define DYNAMIC_USER_PASSWD"*" "*" /* locked */ | |||
| 25 | #define DYNAMIC_USER_DIR"/" "/" | |||
| 26 | #define DYNAMIC_USER_SHELL"/sbin/nologin" "/sbin/nologin" | |||
| 27 | ||||
| 28 | static const struct passwd root_passwd = { | |||
| 29 | .pw_name = (char*) "root", | |||
| 30 | .pw_passwd = (char*) "x", /* see shadow file */ | |||
| 31 | .pw_uid = 0, | |||
| 32 | .pw_gid = 0, | |||
| 33 | .pw_gecos = (char*) "Super User", | |||
| 34 | .pw_dir = (char*) "/root", | |||
| 35 | .pw_shell = (char*) "/bin/sh", | |||
| 36 | }; | |||
| 37 | ||||
| 38 | static const struct passwd nobody_passwd = { | |||
| 39 | .pw_name = (char*) NOBODY_USER_NAME"nobody", | |||
| 40 | .pw_passwd = (char*) "*", /* locked */ | |||
| 41 | .pw_uid = UID_NOBODY((uid_t) 65534U), | |||
| 42 | .pw_gid = GID_NOBODY((gid_t) 65534U), | |||
| 43 | .pw_gecos = (char*) "User Nobody", | |||
| 44 | .pw_dir = (char*) "/", | |||
| 45 | .pw_shell = (char*) "/sbin/nologin", | |||
| 46 | }; | |||
| 47 | ||||
| 48 | static const struct group root_group = { | |||
| 49 | .gr_name = (char*) "root", | |||
| 50 | .gr_gid = 0, | |||
| 51 | .gr_passwd = (char*) "x", /* see shadow file */ | |||
| 52 | .gr_mem = (char*[]) { NULL((void*)0) }, | |||
| 53 | }; | |||
| 54 | ||||
| 55 | static const struct group nobody_group = { | |||
| 56 | .gr_name = (char*) NOBODY_GROUP_NAME"nobody", | |||
| 57 | .gr_gid = GID_NOBODY((gid_t) 65534U), | |||
| 58 | .gr_passwd = (char*) "*", /* locked */ | |||
| 59 | .gr_mem = (char*[]) { NULL((void*)0) }, | |||
| 60 | }; | |||
| 61 | ||||
| 62 | typedef struct UserEntry UserEntry; | |||
| 63 | typedef struct GetentData GetentData; | |||
| 64 | ||||
| 65 | struct UserEntry { | |||
| 66 | uid_t id; | |||
| 67 | char *name; | |||
| 68 | ||||
| 69 | GetentData *data; | |||
| 70 | LIST_FIELDS(UserEntry, entries)UserEntry *entries_next, *entries_prev; | |||
| 71 | }; | |||
| 72 | ||||
| 73 | struct GetentData { | |||
| 74 | /* As explained in NOTES section of getpwent_r(3) as 'getpwent_r() is not really | |||
| 75 | * reentrant since it shares the reading position in the stream with all other threads', | |||
| 76 | * we need to protect the data in UserEntry from multithreaded programs which may call | |||
| 77 | * setpwent(), getpwent_r(), or endpwent() simultaneously. So, each function locks the | |||
| 78 | * data by using the mutex below. */ | |||
| 79 | pthread_mutex_t mutex; | |||
| 80 | ||||
| 81 | UserEntry *position; | |||
| 82 | LIST_HEAD(UserEntry, entries)UserEntry *entries; | |||
| 83 | }; | |||
| 84 | ||||
| 85 | static GetentData getpwent_data = { PTHREAD_MUTEX_INITIALIZER{ { 0, 0, 0, 0, PTHREAD_MUTEX_TIMED_NP, 0, 0, { 0, 0 } } }, NULL((void*)0), NULL((void*)0) }; | |||
| 86 | static GetentData getgrent_data = { PTHREAD_MUTEX_INITIALIZER{ { 0, 0, 0, 0, PTHREAD_MUTEX_TIMED_NP, 0, 0, { 0, 0 } } }, NULL((void*)0), NULL((void*)0) }; | |||
| 87 | ||||
| 88 | NSS_GETPW_PROTOTYPES(systemd)enum nss_status _nss_systemd_getpwnam_r( const char *name, struct passwd *pwd, char *buffer, size_t buflen, int *errnop) __attribute__ ((visibility("default"))); enum nss_status _nss_systemd_getpwuid_r ( uid_t uid, struct passwd *pwd, char *buffer, size_t buflen, int *errnop) __attribute__ ((visibility("default"))); | |||
| 89 | NSS_GETGR_PROTOTYPES(systemd)enum nss_status _nss_systemd_getgrnam_r( const char *name, struct group *gr, char *buffer, size_t buflen, int *errnop) __attribute__ ((visibility("default"))); enum nss_status _nss_systemd_getgrgid_r ( gid_t gid, struct group *gr, char *buffer, size_t buflen, int *errnop) __attribute__ ((visibility("default"))); | |||
| 90 | enum nss_status _nss_systemd_endpwent(void) _public___attribute__ ((visibility("default"))); | |||
| 91 | enum nss_status _nss_systemd_setpwent(int stayopen) _public___attribute__ ((visibility("default"))); | |||
| 92 | enum nss_status _nss_systemd_getpwent_r(struct passwd *result, char *buffer, size_t buflen, int *errnop) _public___attribute__ ((visibility("default"))); | |||
| 93 | enum nss_status _nss_systemd_endgrent(void) _public___attribute__ ((visibility("default"))); | |||
| 94 | enum nss_status _nss_systemd_setgrent(int stayopen) _public___attribute__ ((visibility("default"))); | |||
| 95 | enum nss_status _nss_systemd_getgrent_r(struct group *result, char *buffer, size_t buflen, int *errnop) _public___attribute__ ((visibility("default"))); | |||
| 96 | ||||
| 97 | static int direct_lookup_name(const char *name, uid_t *ret) { | |||
| 98 | _cleanup_free___attribute__((cleanup(freep))) char *s = NULL((void*)0); | |||
| 99 | const char *path; | |||
| 100 | int r; | |||
| 101 | ||||
| 102 | assert(name)do { if ((__builtin_expect(!!(!(name)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("name"), "../src/nss-systemd/nss-systemd.c" , 102, __PRETTY_FUNCTION__); } while (0); | |||
| 103 | ||||
| 104 | /* Normally, we go via the bus to resolve names. That has the benefit that it is available from any mount | |||
| 105 | * namespace and subject to proper authentication. However, there's one problem: if our module is called from | |||
| 106 | * dbus-daemon itself we really can't use D-Bus to communicate. In this case, resort to a client-side hack, | |||
| 107 | * and look for the dynamic names directly. This is pretty ugly, but breaks the cyclic dependency. */ | |||
| 108 | ||||
| 109 | path = strjoina("/run/systemd/dynamic-uid/direct:", name)({ const char *_appendees_[] = { "/run/systemd/dynamic-uid/direct:" , name }; char *_d_, *_p_; size_t _len_ = 0; size_t _i_; for ( _i_ = 0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_ )/sizeof((_appendees_)[0]), ((void)0))) && _appendees_ [_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca (_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(_appendees_), typeof(& *(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0] ), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy (_p_, _appendees_[_i_]); *_p_ = 0; _d_; }); | |||
| 110 | r = readlink_malloc(path, &s); | |||
| 111 | if (r < 0) | |||
| 112 | return r; | |||
| 113 | ||||
| 114 | return parse_uid(s, ret); | |||
| 115 | } | |||
| 116 | ||||
| 117 | static int direct_lookup_uid(uid_t uid, char **ret) { | |||
| 118 | char path[STRLEN("/run/systemd/dynamic-uid/direct:")(sizeof("""/run/systemd/dynamic-uid/direct:""") - 1) + DECIMAL_STR_MAX(uid_t)(2+(sizeof(uid_t) <= 1 ? 3 : sizeof(uid_t) <= 2 ? 5 : sizeof (uid_t) <= 4 ? 10 : sizeof(uid_t) <= 8 ? 20 : sizeof(int [-2*(sizeof(uid_t) > 8)]))) + 1], *s; | |||
| 119 | int r; | |||
| 120 | ||||
| 121 | xsprintf(path, "/run/systemd/dynamic-uid/direct:" UID_FMT, uid)do { if ((__builtin_expect(!!(!(((size_t) snprintf(path, __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (path), typeof(&*(path))), sizeof(path)/sizeof((path)[0]) , ((void)0))), "/run/systemd/dynamic-uid/direct:" "%" "u", uid ) < (__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(path), typeof(&*(path))), sizeof(path)/sizeof((path )[0]), ((void)0))))))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("xsprintf: " "path" "[] must be big enough"), "../src/nss-systemd/nss-systemd.c" , 121, __PRETTY_FUNCTION__); } while (0); | |||
| 122 | ||||
| 123 | r = readlink_malloc(path, &s); | |||
| 124 | if (r < 0) | |||
| 125 | return r; | |||
| 126 | if (!valid_user_group_name(s, VALID_USER_RELAX)) { /* extra safety check */ | |||
| 127 | free(s); | |||
| 128 | return -EINVAL22; | |||
| 129 | } | |||
| 130 | ||||
| 131 | *ret = s; | |||
| 132 | return 0; | |||
| 133 | } | |||
| 134 | ||||
| 135 | enum nss_status _nss_systemd_getpwnam_r( | |||
| 136 | const char *name, | |||
| 137 | struct passwd *pwd, | |||
| 138 | char *buffer, size_t buflen, | |||
| 139 | int *errnop) { | |||
| 140 | ||||
| 141 | _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0}); | |||
| 142 | _cleanup_(sd_bus_message_unrefp)__attribute__((cleanup(sd_bus_message_unrefp))) sd_bus_message* reply = NULL((void*)0); | |||
| 143 | _cleanup_(sd_bus_flush_close_unrefp)__attribute__((cleanup(sd_bus_flush_close_unrefp))) sd_bus *bus = NULL((void*)0); | |||
| 144 | uint32_t translated; | |||
| 145 | size_t l; | |||
| 146 | int bypass, r; | |||
| 147 | ||||
| 148 | PROTECT_ERRNO__attribute__((cleanup(_reset_errno_))) __attribute__((unused )) int _saved_errno_ = (*__errno_location ()); | |||
| 149 | BLOCK_SIGNALS(NSS_SIGNALS_BLOCK)__attribute__((cleanup(block_signals_reset))) __attribute__ ( (unused)) sigset_t _saved_sigset = ({ sigset_t _t; do { if (( __builtin_expect(!!(!(sigprocmask_many(0, &_t, 14,26,13,17 ,20,29,1,10,12,27,23,28, -1) >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("sigprocmask_many(SIG_BLOCK, &_t, 14,26,13,17,20,29,1,10,12,27,23,28, -1) >= 0" ), "../src/nss-systemd/nss-systemd.c", 149, __PRETTY_FUNCTION__ ); } while (0); _t; }); | |||
| 150 | ||||
| 151 | assert(name)do { if ((__builtin_expect(!!(!(name)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("name"), "../src/nss-systemd/nss-systemd.c" , 151, __PRETTY_FUNCTION__); } while (0); | |||
| 152 | assert(pwd)do { if ((__builtin_expect(!!(!(pwd)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("pwd"), "../src/nss-systemd/nss-systemd.c" , 152, __PRETTY_FUNCTION__); } while (0); | |||
| 153 | ||||
| 154 | /* If the username is not valid, then we don't know it. Ideally libc would filter these for us anyway. We don't | |||
| 155 | * generate EINVAL here, because it isn't really out business to complain about invalid user names. */ | |||
| 156 | if (!valid_user_group_name(name, VALID_USER_RELAX)) | |||
| 157 | return NSS_STATUS_NOTFOUND; | |||
| 158 | ||||
| 159 | /* Synthesize entries for the root and nobody users, in case they are missing in /etc/passwd */ | |||
| 160 | if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) { | |||
| 161 | if (streq(name, root_passwd.pw_name)(strcmp((name),(root_passwd.pw_name)) == 0)) { | |||
| 162 | *pwd = root_passwd; | |||
| 163 | return NSS_STATUS_SUCCESS; | |||
| 164 | } | |||
| 165 | if (synthesize_nobody() && | |||
| 166 | streq(name, nobody_passwd.pw_name)(strcmp((name),(nobody_passwd.pw_name)) == 0)) { | |||
| 167 | *pwd = nobody_passwd; | |||
| 168 | return NSS_STATUS_SUCCESS; | |||
| 169 | } | |||
| 170 | } | |||
| 171 | ||||
| 172 | /* Make sure that we don't go in circles when allocating a dynamic UID by checking our own database */ | |||
| 173 | if (getenv_bool_secure("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0) | |||
| 174 | return NSS_STATUS_NOTFOUND; | |||
| 175 | ||||
| 176 | bypass = getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS"); | |||
| 177 | if (bypass <= 0) { | |||
| 178 | r = sd_bus_open_system(&bus); | |||
| 179 | if (r < 0) | |||
| 180 | bypass = 1; | |||
| 181 | } | |||
| 182 | ||||
| 183 | if (bypass > 0) { | |||
| 184 | r = direct_lookup_name(name, (uid_t*) &translated); | |||
| 185 | if (r == -ENOENT2) | |||
| 186 | return NSS_STATUS_NOTFOUND; | |||
| 187 | if (r < 0) | |||
| 188 | goto fail; | |||
| 189 | } else { | |||
| 190 | r = sd_bus_call_method(bus, | |||
| 191 | "org.freedesktop.systemd1", | |||
| 192 | "/org/freedesktop/systemd1", | |||
| 193 | "org.freedesktop.systemd1.Manager", | |||
| 194 | "LookupDynamicUserByName", | |||
| 195 | &error, | |||
| 196 | &reply, | |||
| 197 | "s", | |||
| 198 | name); | |||
| 199 | if (r < 0) { | |||
| 200 | if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_DYNAMIC_USER"org.freedesktop.systemd1.NoSuchDynamicUser")) | |||
| 201 | return NSS_STATUS_NOTFOUND; | |||
| 202 | ||||
| 203 | goto fail; | |||
| 204 | } | |||
| 205 | ||||
| 206 | r = sd_bus_message_read(reply, "u", &translated); | |||
| 207 | if (r < 0) | |||
| 208 | goto fail; | |||
| 209 | } | |||
| 210 | ||||
| 211 | l = strlen(name); | |||
| 212 | if (buflen < l+1) { | |||
| 213 | UNPROTECT_ERRNOdo { (*__errno_location ()) = _saved_errno_; _saved_errno_ = - 1; } while (0); | |||
| 214 | *errnop = ERANGE34; | |||
| 215 | return NSS_STATUS_TRYAGAIN; | |||
| 216 | } | |||
| 217 | ||||
| 218 | memcpy(buffer, name, l+1); | |||
| 219 | ||||
| 220 | pwd->pw_name = buffer; | |||
| 221 | pwd->pw_uid = (uid_t) translated; | |||
| 222 | pwd->pw_gid = (uid_t) translated; | |||
| 223 | pwd->pw_gecos = (char*) DYNAMIC_USER_GECOS"Dynamic User"; | |||
| 224 | pwd->pw_passwd = (char*) DYNAMIC_USER_PASSWD"*"; | |||
| 225 | pwd->pw_dir = (char*) DYNAMIC_USER_DIR"/"; | |||
| 226 | pwd->pw_shell = (char*) DYNAMIC_USER_SHELL"/sbin/nologin"; | |||
| 227 | ||||
| 228 | return NSS_STATUS_SUCCESS; | |||
| 229 | ||||
| 230 | fail: | |||
| 231 | UNPROTECT_ERRNOdo { (*__errno_location ()) = _saved_errno_; _saved_errno_ = - 1; } while (0); | |||
| 232 | *errnop = -r; | |||
| 233 | return NSS_STATUS_UNAVAIL; | |||
| 234 | } | |||
| 235 | ||||
| 236 | enum nss_status _nss_systemd_getpwuid_r( | |||
| 237 | uid_t uid, | |||
| 238 | struct passwd *pwd, | |||
| 239 | char *buffer, size_t buflen, | |||
| 240 | int *errnop) { | |||
| 241 | ||||
| 242 | _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0}); | |||
| 243 | _cleanup_(sd_bus_message_unrefp)__attribute__((cleanup(sd_bus_message_unrefp))) sd_bus_message* reply = NULL((void*)0); | |||
| 244 | _cleanup_(sd_bus_flush_close_unrefp)__attribute__((cleanup(sd_bus_flush_close_unrefp))) sd_bus *bus = NULL((void*)0); | |||
| 245 | _cleanup_free___attribute__((cleanup(freep))) char *direct = NULL((void*)0); | |||
| 246 | const char *translated; | |||
| 247 | size_t l; | |||
| 248 | int bypass, r; | |||
| 249 | ||||
| 250 | PROTECT_ERRNO__attribute__((cleanup(_reset_errno_))) __attribute__((unused )) int _saved_errno_ = (*__errno_location ()); | |||
| 251 | BLOCK_SIGNALS(NSS_SIGNALS_BLOCK)__attribute__((cleanup(block_signals_reset))) __attribute__ ( (unused)) sigset_t _saved_sigset = ({ sigset_t _t; do { if (( __builtin_expect(!!(!(sigprocmask_many(0, &_t, 14,26,13,17 ,20,29,1,10,12,27,23,28, -1) >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("sigprocmask_many(SIG_BLOCK, &_t, 14,26,13,17,20,29,1,10,12,27,23,28, -1) >= 0" ), "../src/nss-systemd/nss-systemd.c", 251, __PRETTY_FUNCTION__ ); } while (0); _t; }); | |||
| 252 | ||||
| 253 | if (!uid_is_valid(uid)) | |||
| 254 | return NSS_STATUS_NOTFOUND; | |||
| 255 | ||||
| 256 | /* Synthesize data for the root user and for nobody in case they are missing from /etc/passwd */ | |||
| 257 | if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) { | |||
| 258 | if (uid == root_passwd.pw_uid) { | |||
| 259 | *pwd = root_passwd; | |||
| 260 | return NSS_STATUS_SUCCESS; | |||
| 261 | } | |||
| 262 | if (synthesize_nobody() && | |||
| 263 | uid == nobody_passwd.pw_uid) { | |||
| 264 | *pwd = nobody_passwd; | |||
| 265 | return NSS_STATUS_SUCCESS; | |||
| 266 | } | |||
| 267 | } | |||
| 268 | ||||
| 269 | if (!uid_is_dynamic(uid)) | |||
| 270 | return NSS_STATUS_NOTFOUND; | |||
| 271 | ||||
| 272 | if (getenv_bool_secure("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0) | |||
| 273 | return NSS_STATUS_NOTFOUND; | |||
| 274 | ||||
| 275 | bypass = getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS"); | |||
| 276 | if (bypass <= 0) { | |||
| 277 | r = sd_bus_open_system(&bus); | |||
| 278 | if (r < 0) | |||
| 279 | bypass = 1; | |||
| 280 | } | |||
| 281 | ||||
| 282 | if (bypass > 0) { | |||
| 283 | r = direct_lookup_uid(uid, &direct); | |||
| 284 | if (r == -ENOENT2) | |||
| 285 | return NSS_STATUS_NOTFOUND; | |||
| 286 | if (r < 0) | |||
| 287 | goto fail; | |||
| 288 | ||||
| 289 | translated = direct; | |||
| 290 | ||||
| 291 | } else { | |||
| 292 | r = sd_bus_call_method(bus, | |||
| 293 | "org.freedesktop.systemd1", | |||
| 294 | "/org/freedesktop/systemd1", | |||
| 295 | "org.freedesktop.systemd1.Manager", | |||
| 296 | "LookupDynamicUserByUID", | |||
| 297 | &error, | |||
| 298 | &reply, | |||
| 299 | "u", | |||
| 300 | (uint32_t) uid); | |||
| 301 | if (r < 0) { | |||
| 302 | if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_DYNAMIC_USER"org.freedesktop.systemd1.NoSuchDynamicUser")) | |||
| 303 | return NSS_STATUS_NOTFOUND; | |||
| 304 | ||||
| 305 | goto fail; | |||
| 306 | } | |||
| 307 | ||||
| 308 | r = sd_bus_message_read(reply, "s", &translated); | |||
| 309 | if (r < 0) | |||
| 310 | goto fail; | |||
| 311 | } | |||
| 312 | ||||
| 313 | l = strlen(translated) + 1; | |||
| 314 | if (buflen < l) { | |||
| 315 | UNPROTECT_ERRNOdo { (*__errno_location ()) = _saved_errno_; _saved_errno_ = - 1; } while (0); | |||
| 316 | *errnop = ERANGE34; | |||
| 317 | return NSS_STATUS_TRYAGAIN; | |||
| 318 | } | |||
| 319 | ||||
| 320 | memcpy(buffer, translated, l); | |||
| 321 | ||||
| 322 | pwd->pw_name = buffer; | |||
| 323 | pwd->pw_uid = uid; | |||
| 324 | pwd->pw_gid = uid; | |||
| 325 | pwd->pw_gecos = (char*) DYNAMIC_USER_GECOS"Dynamic User"; | |||
| 326 | pwd->pw_passwd = (char*) DYNAMIC_USER_PASSWD"*"; | |||
| 327 | pwd->pw_dir = (char*) DYNAMIC_USER_DIR"/"; | |||
| 328 | pwd->pw_shell = (char*) DYNAMIC_USER_SHELL"/sbin/nologin"; | |||
| 329 | ||||
| 330 | return NSS_STATUS_SUCCESS; | |||
| 331 | ||||
| 332 | fail: | |||
| 333 | UNPROTECT_ERRNOdo { (*__errno_location ()) = _saved_errno_; _saved_errno_ = - 1; } while (0); | |||
| 334 | *errnop = -r; | |||
| 335 | return NSS_STATUS_UNAVAIL; | |||
| 336 | } | |||
| 337 | ||||
| 338 | #pragma GCC diagnostic ignored "-Wsizeof-pointer-memaccess" | |||
| 339 | ||||
| 340 | enum nss_status _nss_systemd_getgrnam_r( | |||
| 341 | const char *name, | |||
| 342 | struct group *gr, | |||
| 343 | char *buffer, size_t buflen, | |||
| 344 | int *errnop) { | |||
| 345 | ||||
| 346 | _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0}); | |||
| 347 | _cleanup_(sd_bus_message_unrefp)__attribute__((cleanup(sd_bus_message_unrefp))) sd_bus_message* reply = NULL((void*)0); | |||
| 348 | _cleanup_(sd_bus_flush_close_unrefp)__attribute__((cleanup(sd_bus_flush_close_unrefp))) sd_bus *bus = NULL((void*)0); | |||
| 349 | uint32_t translated; | |||
| 350 | size_t l; | |||
| 351 | int bypass, r; | |||
| 352 | ||||
| 353 | PROTECT_ERRNO__attribute__((cleanup(_reset_errno_))) __attribute__((unused )) int _saved_errno_ = (*__errno_location ()); | |||
| 354 | BLOCK_SIGNALS(NSS_SIGNALS_BLOCK)__attribute__((cleanup(block_signals_reset))) __attribute__ ( (unused)) sigset_t _saved_sigset = ({ sigset_t _t; do { if (( __builtin_expect(!!(!(sigprocmask_many(0, &_t, 14,26,13,17 ,20,29,1,10,12,27,23,28, -1) >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("sigprocmask_many(SIG_BLOCK, &_t, 14,26,13,17,20,29,1,10,12,27,23,28, -1) >= 0" ), "../src/nss-systemd/nss-systemd.c", 354, __PRETTY_FUNCTION__ ); } while (0); _t; }); | |||
| 355 | ||||
| 356 | assert(name)do { if ((__builtin_expect(!!(!(name)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("name"), "../src/nss-systemd/nss-systemd.c" , 356, __PRETTY_FUNCTION__); } while (0); | |||
| 357 | assert(gr)do { if ((__builtin_expect(!!(!(gr)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("gr"), "../src/nss-systemd/nss-systemd.c" , 357, __PRETTY_FUNCTION__); } while (0); | |||
| 358 | ||||
| 359 | if (!valid_user_group_name(name, VALID_USER_RELAX)) | |||
| 360 | return NSS_STATUS_NOTFOUND; | |||
| 361 | ||||
| 362 | /* Synthesize records for root and nobody, in case they are missing form /etc/group */ | |||
| 363 | if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) { | |||
| 364 | if (streq(name, root_group.gr_name)(strcmp((name),(root_group.gr_name)) == 0)) { | |||
| 365 | *gr = root_group; | |||
| 366 | return NSS_STATUS_SUCCESS; | |||
| 367 | } | |||
| 368 | if (synthesize_nobody() && | |||
| 369 | streq(name, nobody_group.gr_name)(strcmp((name),(nobody_group.gr_name)) == 0)) { | |||
| 370 | *gr = nobody_group; | |||
| 371 | return NSS_STATUS_SUCCESS; | |||
| 372 | } | |||
| 373 | } | |||
| 374 | ||||
| 375 | if (getenv_bool_secure("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0) | |||
| 376 | return NSS_STATUS_NOTFOUND; | |||
| 377 | ||||
| 378 | bypass = getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS"); | |||
| 379 | if (bypass <= 0) { | |||
| 380 | r = sd_bus_open_system(&bus); | |||
| 381 | if (r < 0) | |||
| 382 | bypass = 1; | |||
| 383 | } | |||
| 384 | ||||
| 385 | if (bypass > 0) { | |||
| 386 | r = direct_lookup_name(name, (uid_t*) &translated); | |||
| 387 | if (r == -ENOENT2) | |||
| 388 | return NSS_STATUS_NOTFOUND; | |||
| 389 | if (r < 0) | |||
| 390 | goto fail; | |||
| 391 | } else { | |||
| 392 | r = sd_bus_call_method(bus, | |||
| 393 | "org.freedesktop.systemd1", | |||
| 394 | "/org/freedesktop/systemd1", | |||
| 395 | "org.freedesktop.systemd1.Manager", | |||
| 396 | "LookupDynamicUserByName", | |||
| 397 | &error, | |||
| 398 | &reply, | |||
| 399 | "s", | |||
| 400 | name); | |||
| 401 | if (r < 0) { | |||
| 402 | if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_DYNAMIC_USER"org.freedesktop.systemd1.NoSuchDynamicUser")) | |||
| 403 | return NSS_STATUS_NOTFOUND; | |||
| 404 | ||||
| 405 | goto fail; | |||
| 406 | } | |||
| 407 | ||||
| 408 | r = sd_bus_message_read(reply, "u", &translated); | |||
| 409 | if (r < 0) | |||
| 410 | goto fail; | |||
| 411 | } | |||
| 412 | ||||
| 413 | l = sizeof(char*) + strlen(name) + 1; | |||
| 414 | if (buflen < l) { | |||
| 415 | UNPROTECT_ERRNOdo { (*__errno_location ()) = _saved_errno_; _saved_errno_ = - 1; } while (0); | |||
| 416 | *errnop = ERANGE34; | |||
| 417 | return NSS_STATUS_TRYAGAIN; | |||
| 418 | } | |||
| 419 | ||||
| 420 | memzero(buffer, sizeof(char*))({ size_t _l_ = (sizeof(char*)); void *_x_ = (buffer); _l_ == 0 ? _x_ : memset(_x_, 0, _l_); }); | |||
| 421 | strcpy(buffer + sizeof(char*), name); | |||
| 422 | ||||
| 423 | gr->gr_name = buffer + sizeof(char*); | |||
| 424 | gr->gr_gid = (gid_t) translated; | |||
| 425 | gr->gr_passwd = (char*) DYNAMIC_USER_PASSWD"*"; | |||
| 426 | gr->gr_mem = (char**) buffer; | |||
| 427 | ||||
| 428 | return NSS_STATUS_SUCCESS; | |||
| 429 | ||||
| 430 | fail: | |||
| 431 | UNPROTECT_ERRNOdo { (*__errno_location ()) = _saved_errno_; _saved_errno_ = - 1; } while (0); | |||
| 432 | *errnop = -r; | |||
| 433 | return NSS_STATUS_UNAVAIL; | |||
| 434 | } | |||
| 435 | ||||
| 436 | enum nss_status _nss_systemd_getgrgid_r( | |||
| 437 | gid_t gid, | |||
| 438 | struct group *gr, | |||
| 439 | char *buffer, size_t buflen, | |||
| 440 | int *errnop) { | |||
| 441 | ||||
| 442 | _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0}); | |||
| 443 | _cleanup_(sd_bus_message_unrefp)__attribute__((cleanup(sd_bus_message_unrefp))) sd_bus_message* reply = NULL((void*)0); | |||
| 444 | _cleanup_(sd_bus_flush_close_unrefp)__attribute__((cleanup(sd_bus_flush_close_unrefp))) sd_bus *bus = NULL((void*)0); | |||
| 445 | _cleanup_free___attribute__((cleanup(freep))) char *direct = NULL((void*)0); | |||
| 446 | const char *translated; | |||
| 447 | size_t l; | |||
| 448 | int bypass, r; | |||
| 449 | ||||
| 450 | PROTECT_ERRNO__attribute__((cleanup(_reset_errno_))) __attribute__((unused )) int _saved_errno_ = (*__errno_location ()); | |||
| 451 | BLOCK_SIGNALS(NSS_SIGNALS_BLOCK)__attribute__((cleanup(block_signals_reset))) __attribute__ ( (unused)) sigset_t _saved_sigset = ({ sigset_t _t; do { if (( __builtin_expect(!!(!(sigprocmask_many(0, &_t, 14,26,13,17 ,20,29,1,10,12,27,23,28, -1) >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("sigprocmask_many(SIG_BLOCK, &_t, 14,26,13,17,20,29,1,10,12,27,23,28, -1) >= 0" ), "../src/nss-systemd/nss-systemd.c", 451, __PRETTY_FUNCTION__ ); } while (0); _t; }); | |||
| 452 | ||||
| 453 | if (!gid_is_valid(gid)) | |||
| 454 | return NSS_STATUS_NOTFOUND; | |||
| 455 | ||||
| 456 | /* Synthesize records for root and nobody, in case they are missing from /etc/group */ | |||
| 457 | if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) { | |||
| 458 | if (gid == root_group.gr_gid) { | |||
| 459 | *gr = root_group; | |||
| 460 | return NSS_STATUS_SUCCESS; | |||
| 461 | } | |||
| 462 | if (synthesize_nobody() && | |||
| 463 | gid == nobody_group.gr_gid) { | |||
| 464 | *gr = nobody_group; | |||
| 465 | return NSS_STATUS_SUCCESS; | |||
| 466 | } | |||
| 467 | } | |||
| 468 | ||||
| 469 | if (!gid_is_dynamic(gid)) | |||
| 470 | return NSS_STATUS_NOTFOUND; | |||
| 471 | ||||
| 472 | if (getenv_bool_secure("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0) | |||
| 473 | return NSS_STATUS_NOTFOUND; | |||
| 474 | ||||
| 475 | bypass = getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS"); | |||
| 476 | if (bypass <= 0) { | |||
| 477 | r = sd_bus_open_system(&bus); | |||
| 478 | if (r < 0) | |||
| 479 | bypass = 1; | |||
| 480 | } | |||
| 481 | ||||
| 482 | if (bypass > 0) { | |||
| 483 | r = direct_lookup_uid(gid, &direct); | |||
| 484 | if (r == -ENOENT2) | |||
| 485 | return NSS_STATUS_NOTFOUND; | |||
| 486 | if (r < 0) | |||
| 487 | goto fail; | |||
| 488 | ||||
| 489 | translated = direct; | |||
| 490 | ||||
| 491 | } else { | |||
| 492 | r = sd_bus_call_method(bus, | |||
| 493 | "org.freedesktop.systemd1", | |||
| 494 | "/org/freedesktop/systemd1", | |||
| 495 | "org.freedesktop.systemd1.Manager", | |||
| 496 | "LookupDynamicUserByUID", | |||
| 497 | &error, | |||
| 498 | &reply, | |||
| 499 | "u", | |||
| 500 | (uint32_t) gid); | |||
| 501 | if (r < 0) { | |||
| 502 | if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_DYNAMIC_USER"org.freedesktop.systemd1.NoSuchDynamicUser")) | |||
| 503 | return NSS_STATUS_NOTFOUND; | |||
| 504 | ||||
| 505 | goto fail; | |||
| 506 | } | |||
| 507 | ||||
| 508 | r = sd_bus_message_read(reply, "s", &translated); | |||
| 509 | if (r < 0) | |||
| 510 | goto fail; | |||
| 511 | } | |||
| 512 | ||||
| 513 | l = sizeof(char*) + strlen(translated) + 1; | |||
| 514 | if (buflen < l) { | |||
| 515 | UNPROTECT_ERRNOdo { (*__errno_location ()) = _saved_errno_; _saved_errno_ = - 1; } while (0); | |||
| 516 | *errnop = ERANGE34; | |||
| 517 | return NSS_STATUS_TRYAGAIN; | |||
| 518 | } | |||
| 519 | ||||
| 520 | memzero(buffer, sizeof(char*))({ size_t _l_ = (sizeof(char*)); void *_x_ = (buffer); _l_ == 0 ? _x_ : memset(_x_, 0, _l_); }); | |||
| 521 | strcpy(buffer + sizeof(char*), translated); | |||
| 522 | ||||
| 523 | gr->gr_name = buffer + sizeof(char*); | |||
| 524 | gr->gr_gid = gid; | |||
| 525 | gr->gr_passwd = (char*) DYNAMIC_USER_PASSWD"*"; | |||
| 526 | gr->gr_mem = (char**) buffer; | |||
| 527 | ||||
| 528 | return NSS_STATUS_SUCCESS; | |||
| 529 | ||||
| 530 | fail: | |||
| 531 | UNPROTECT_ERRNOdo { (*__errno_location ()) = _saved_errno_; _saved_errno_ = - 1; } while (0); | |||
| 532 | *errnop = -r; | |||
| 533 | return NSS_STATUS_UNAVAIL; | |||
| 534 | } | |||
| 535 | ||||
| 536 | static void user_entry_free(UserEntry *p) { | |||
| 537 | if (!p
| |||
| 538 | return; | |||
| 539 | ||||
| 540 | if (p->data) | |||
| 541 | LIST_REMOVE(entries, p->data->entries, p)do { typeof(*(p->data->entries)) **_head = &(p-> data->entries), *_item = (p); do { if ((__builtin_expect(! !(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ( "_item"), "../src/nss-systemd/nss-systemd.c", 541, __PRETTY_FUNCTION__ ); } while (0); if (_item->entries_next) _item->entries_next ->entries_prev = _item->entries_prev; if (_item->entries_prev ) _item->entries_prev->entries_next = _item->entries_next ; else { do { if ((__builtin_expect(!!(!(*_head == _item)),0) )) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("*_head == _item" ), "../src/nss-systemd/nss-systemd.c", 541, __PRETTY_FUNCTION__ ); } while (0); *_head = _item->entries_next; } _item-> entries_next = _item->entries_prev = ((void*)0); } while ( 0); | |||
| 542 | ||||
| 543 | free(p->name); | |||
| 544 | free(p); | |||
| 545 | } | |||
| 546 | ||||
| 547 | static int user_entry_add(GetentData *data, const char *name, uid_t id) { | |||
| 548 | UserEntry *p; | |||
| 549 | ||||
| 550 | assert(data)do { if ((__builtin_expect(!!(!(data)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("data"), "../src/nss-systemd/nss-systemd.c" , 550, __PRETTY_FUNCTION__); } while (0); | |||
| 551 | ||||
| 552 | /* This happens when User= or Group= already exists statically. */ | |||
| 553 | if (!uid_is_dynamic(id)) | |||
| 554 | return -EINVAL22; | |||
| 555 | ||||
| 556 | p = new0(UserEntry, 1)((UserEntry*) calloc((1), sizeof(UserEntry))); | |||
| 557 | if (!p) | |||
| 558 | return -ENOMEM12; | |||
| 559 | ||||
| 560 | p->name = strdup(name); | |||
| 561 | if (!p->name) { | |||
| 562 | free(p); | |||
| 563 | return -ENOMEM12; | |||
| 564 | } | |||
| 565 | p->id = id; | |||
| 566 | p->data = data; | |||
| 567 | ||||
| 568 | LIST_PREPEND(entries, data->entries, p)do { typeof(*(data->entries)) **_head = &(data->entries ), *_item = (p); do { if ((__builtin_expect(!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("_item"), "../src/nss-systemd/nss-systemd.c" , 568, __PRETTY_FUNCTION__); } while (0); if ((_item->entries_next = *_head)) _item->entries_next->entries_prev = _item; _item ->entries_prev = ((void*)0); *_head = _item; } while (0); | |||
| 569 | ||||
| 570 | return 0; | |||
| 571 | } | |||
| 572 | ||||
| 573 | static void systemd_endent(GetentData *data) { | |||
| 574 | UserEntry *p; | |||
| 575 | ||||
| 576 | assert(data)do { if ((__builtin_expect(!!(!(data)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("data"), "../src/nss-systemd/nss-systemd.c" , 576, __PRETTY_FUNCTION__); } while (0); | |||
| 577 | ||||
| 578 | while ((p = data->entries)) | |||
| 579 | user_entry_free(p); | |||
| ||||
| 580 | ||||
| 581 | data->position = NULL((void*)0); | |||
| 582 | } | |||
| 583 | ||||
| 584 | static enum nss_status nss_systemd_endent(GetentData *p) { | |||
| 585 | PROTECT_ERRNO__attribute__((cleanup(_reset_errno_))) __attribute__((unused )) int _saved_errno_ = (*__errno_location ()); | |||
| 586 | BLOCK_SIGNALS(NSS_SIGNALS_BLOCK)__attribute__((cleanup(block_signals_reset))) __attribute__ ( (unused)) sigset_t _saved_sigset = ({ sigset_t _t; do { if (( __builtin_expect(!!(!(sigprocmask_many(0, &_t, 14,26,13,17 ,20,29,1,10,12,27,23,28, -1) >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("sigprocmask_many(SIG_BLOCK, &_t, 14,26,13,17,20,29,1,10,12,27,23,28, -1) >= 0" ), "../src/nss-systemd/nss-systemd.c", 586, __PRETTY_FUNCTION__ ); } while (0); _t; }); | |||
| 587 | ||||
| 588 | assert_se(pthread_mutex_lock(&p->mutex) == 0)do { if ((__builtin_expect(!!(!(pthread_mutex_lock(&p-> mutex) == 0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("pthread_mutex_lock(&p->mutex) == 0"), "../src/nss-systemd/nss-systemd.c" , 588, __PRETTY_FUNCTION__); } while (0); | |||
| 589 | systemd_endent(p); | |||
| 590 | assert_se(pthread_mutex_unlock(&p->mutex) == 0)do { if ((__builtin_expect(!!(!(pthread_mutex_unlock(&p-> mutex) == 0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("pthread_mutex_unlock(&p->mutex) == 0"), "../src/nss-systemd/nss-systemd.c" , 590, __PRETTY_FUNCTION__); } while (0); | |||
| 591 | ||||
| 592 | return NSS_STATUS_SUCCESS; | |||
| 593 | } | |||
| 594 | ||||
| 595 | enum nss_status _nss_systemd_endpwent(void) { | |||
| 596 | return nss_systemd_endent(&getpwent_data); | |||
| 597 | } | |||
| 598 | ||||
| 599 | enum nss_status _nss_systemd_endgrent(void) { | |||
| 600 | return nss_systemd_endent(&getgrent_data); | |||
| 601 | } | |||
| 602 | ||||
| 603 | static int direct_enumeration(GetentData *p) { | |||
| 604 | _cleanup_closedir___attribute__((cleanup(closedirp))) DIR *d = NULL((void*)0); | |||
| 605 | struct dirent *de; | |||
| 606 | int r; | |||
| 607 | ||||
| 608 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/nss-systemd/nss-systemd.c" , 608, __PRETTY_FUNCTION__); } while (0); | |||
| 609 | ||||
| 610 | d = opendir("/run/systemd/dynamic-uid/"); | |||
| 611 | if (!d) | |||
| 612 | return -errno(*__errno_location ()); | |||
| 613 | ||||
| 614 | FOREACH_DIRENT(de, d, return -errno)for ((*__errno_location ()) = 0, de = readdir(d);; (*__errno_location ()) = 0, de = readdir(d)) if (!de) { if ((*__errno_location ( )) > 0) { return -(*__errno_location ()); } break; } else if (hidden_or_backup_file((de)->d_name)) continue; else { | |||
| 615 | _cleanup_free___attribute__((cleanup(freep))) char *name = NULL((void*)0); | |||
| 616 | uid_t uid, verified; | |||
| 617 | ||||
| 618 | if (!dirent_is_file(de)) | |||
| 619 | continue; | |||
| 620 | ||||
| 621 | r = parse_uid(de->d_name, &uid); | |||
| 622 | if (r < 0) | |||
| 623 | continue; | |||
| 624 | ||||
| 625 | r = direct_lookup_uid(uid, &name); | |||
| 626 | if (r == -ENOMEM12) | |||
| 627 | return r; | |||
| 628 | if (r < 0) | |||
| 629 | continue; | |||
| 630 | ||||
| 631 | r = direct_lookup_name(name, &verified); | |||
| 632 | if (r < 0) | |||
| 633 | continue; | |||
| 634 | ||||
| 635 | if (uid != verified) | |||
| 636 | continue; | |||
| 637 | ||||
| 638 | r = user_entry_add(p, name, uid); | |||
| 639 | if (r == -ENOMEM12) | |||
| 640 | return r; | |||
| 641 | if (r < 0) | |||
| 642 | continue; | |||
| 643 | } | |||
| 644 | ||||
| 645 | return 0; | |||
| 646 | } | |||
| 647 | ||||
| 648 | static enum nss_status systemd_setent(GetentData *p) { | |||
| 649 | _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0}); | |||
| 650 | _cleanup_(sd_bus_message_unrefp)__attribute__((cleanup(sd_bus_message_unrefp))) sd_bus_message* reply = NULL((void*)0); | |||
| 651 | _cleanup_(sd_bus_flush_close_unrefp)__attribute__((cleanup(sd_bus_flush_close_unrefp))) sd_bus *bus = NULL((void*)0); | |||
| 652 | const char *name; | |||
| 653 | uid_t id; | |||
| 654 | int bypass, r; | |||
| 655 | ||||
| 656 | PROTECT_ERRNO__attribute__((cleanup(_reset_errno_))) __attribute__((unused )) int _saved_errno_ = (*__errno_location ()); | |||
| 657 | BLOCK_SIGNALS(NSS_SIGNALS_BLOCK)__attribute__((cleanup(block_signals_reset))) __attribute__ ( (unused)) sigset_t _saved_sigset = ({ sigset_t _t; do { if (( __builtin_expect(!!(!(sigprocmask_many(0, &_t, 14,26,13,17 ,20,29,1,10,12,27,23,28, -1) >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("sigprocmask_many(SIG_BLOCK, &_t, 14,26,13,17,20,29,1,10,12,27,23,28, -1) >= 0" ), "../src/nss-systemd/nss-systemd.c", 657, __PRETTY_FUNCTION__ ); } while (0); _t; }); | |||
| 658 | ||||
| 659 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/nss-systemd/nss-systemd.c" , 659, __PRETTY_FUNCTION__); } while (0); | |||
| 660 | ||||
| 661 | assert_se(pthread_mutex_lock(&p->mutex) == 0)do { if ((__builtin_expect(!!(!(pthread_mutex_lock(&p-> mutex) == 0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("pthread_mutex_lock(&p->mutex) == 0"), "../src/nss-systemd/nss-systemd.c" , 661, __PRETTY_FUNCTION__); } while (0); | |||
| 662 | ||||
| 663 | systemd_endent(p); | |||
| 664 | ||||
| 665 | if (getenv_bool_secure("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0) | |||
| 666 | goto finish; | |||
| 667 | ||||
| 668 | bypass = getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS"); | |||
| 669 | ||||
| 670 | if (bypass <= 0) { | |||
| 671 | r = sd_bus_open_system(&bus); | |||
| 672 | if (r < 0) | |||
| 673 | bypass = 1; | |||
| 674 | } | |||
| 675 | ||||
| 676 | if (bypass > 0) { | |||
| 677 | r = direct_enumeration(p); | |||
| 678 | if (r < 0) | |||
| 679 | goto fail; | |||
| 680 | ||||
| 681 | goto finish; | |||
| 682 | } | |||
| 683 | ||||
| 684 | r = sd_bus_call_method(bus, | |||
| 685 | "org.freedesktop.systemd1", | |||
| 686 | "/org/freedesktop/systemd1", | |||
| 687 | "org.freedesktop.systemd1.Manager", | |||
| 688 | "GetDynamicUsers", | |||
| 689 | &error, | |||
| 690 | &reply, | |||
| 691 | NULL((void*)0)); | |||
| 692 | if (r < 0) | |||
| 693 | goto fail; | |||
| 694 | ||||
| 695 | r = sd_bus_message_enter_container(reply, 'a', "(us)"); | |||
| 696 | if (r < 0) | |||
| 697 | goto fail; | |||
| 698 | ||||
| 699 | while ((r = sd_bus_message_read(reply, "(us)", &id, &name)) > 0) { | |||
| 700 | r = user_entry_add(p, name, id); | |||
| 701 | if (r == -ENOMEM12) | |||
| 702 | goto fail; | |||
| 703 | if (r < 0) | |||
| 704 | continue; | |||
| 705 | } | |||
| 706 | if (r < 0) | |||
| 707 | goto fail; | |||
| 708 | ||||
| 709 | r = sd_bus_message_exit_container(reply); | |||
| 710 | if (r < 0) | |||
| 711 | goto fail; | |||
| 712 | ||||
| 713 | finish: | |||
| 714 | p->position = p->entries; | |||
| 715 | assert_se(pthread_mutex_unlock(&p->mutex) == 0)do { if ((__builtin_expect(!!(!(pthread_mutex_unlock(&p-> mutex) == 0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("pthread_mutex_unlock(&p->mutex) == 0"), "../src/nss-systemd/nss-systemd.c" , 715, __PRETTY_FUNCTION__); } while (0); | |||
| 716 | ||||
| 717 | return NSS_STATUS_SUCCESS; | |||
| 718 | ||||
| 719 | fail: | |||
| 720 | systemd_endent(p); | |||
| 721 | assert_se(pthread_mutex_unlock(&p->mutex) == 0)do { if ((__builtin_expect(!!(!(pthread_mutex_unlock(&p-> mutex) == 0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("pthread_mutex_unlock(&p->mutex) == 0"), "../src/nss-systemd/nss-systemd.c" , 721, __PRETTY_FUNCTION__); } while (0); | |||
| 722 | ||||
| 723 | return NSS_STATUS_UNAVAIL; | |||
| 724 | } | |||
| 725 | ||||
| 726 | enum nss_status _nss_systemd_setpwent(int stayopen) { | |||
| 727 | return systemd_setent(&getpwent_data); | |||
| 728 | } | |||
| 729 | ||||
| 730 | enum nss_status _nss_systemd_setgrent(int stayopen) { | |||
| 731 | return systemd_setent(&getgrent_data); | |||
| ||||
| 732 | } | |||
| 733 | ||||
| 734 | enum nss_status _nss_systemd_getpwent_r(struct passwd *result, char *buffer, size_t buflen, int *errnop) { | |||
| 735 | enum nss_status ret; | |||
| 736 | UserEntry *p; | |||
| 737 | size_t len; | |||
| 738 | ||||
| 739 | PROTECT_ERRNO__attribute__((cleanup(_reset_errno_))) __attribute__((unused )) int _saved_errno_ = (*__errno_location ()); | |||
| 740 | BLOCK_SIGNALS(NSS_SIGNALS_BLOCK)__attribute__((cleanup(block_signals_reset))) __attribute__ ( (unused)) sigset_t _saved_sigset = ({ sigset_t _t; do { if (( __builtin_expect(!!(!(sigprocmask_many(0, &_t, 14,26,13,17 ,20,29,1,10,12,27,23,28, -1) >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("sigprocmask_many(SIG_BLOCK, &_t, 14,26,13,17,20,29,1,10,12,27,23,28, -1) >= 0" ), "../src/nss-systemd/nss-systemd.c", 740, __PRETTY_FUNCTION__ ); } while (0); _t; }); | |||
| 741 | ||||
| 742 | assert(result)do { if ((__builtin_expect(!!(!(result)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("result"), "../src/nss-systemd/nss-systemd.c" , 742, __PRETTY_FUNCTION__); } while (0); | |||
| 743 | assert(buffer)do { if ((__builtin_expect(!!(!(buffer)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("buffer"), "../src/nss-systemd/nss-systemd.c" , 743, __PRETTY_FUNCTION__); } while (0); | |||
| 744 | assert(errnop)do { if ((__builtin_expect(!!(!(errnop)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("errnop"), "../src/nss-systemd/nss-systemd.c" , 744, __PRETTY_FUNCTION__); } while (0); | |||
| 745 | ||||
| 746 | assert_se(pthread_mutex_lock(&getpwent_data.mutex) == 0)do { if ((__builtin_expect(!!(!(pthread_mutex_lock(&getpwent_data .mutex) == 0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("pthread_mutex_lock(&getpwent_data.mutex) == 0"), "../src/nss-systemd/nss-systemd.c" , 746, __PRETTY_FUNCTION__); } while (0); | |||
| 747 | ||||
| 748 | LIST_FOREACH(entries, p, getpwent_data.position)for ((p) = (getpwent_data.position); (p); (p) = (p)->entries_next ) { | |||
| 749 | len = strlen(p->name) + 1; | |||
| 750 | if (buflen < len) { | |||
| 751 | UNPROTECT_ERRNOdo { (*__errno_location ()) = _saved_errno_; _saved_errno_ = - 1; } while (0); | |||
| 752 | *errnop = ERANGE34; | |||
| 753 | ret = NSS_STATUS_TRYAGAIN; | |||
| 754 | goto finalize; | |||
| 755 | } | |||
| 756 | ||||
| 757 | memcpy(buffer, p->name, len); | |||
| 758 | ||||
| 759 | result->pw_name = buffer; | |||
| 760 | result->pw_uid = p->id; | |||
| 761 | result->pw_gid = p->id; | |||
| 762 | result->pw_gecos = (char*) DYNAMIC_USER_GECOS"Dynamic User"; | |||
| 763 | result->pw_passwd = (char*) DYNAMIC_USER_PASSWD"*"; | |||
| 764 | result->pw_dir = (char*) DYNAMIC_USER_DIR"/"; | |||
| 765 | result->pw_shell = (char*) DYNAMIC_USER_SHELL"/sbin/nologin"; | |||
| 766 | break; | |||
| 767 | } | |||
| 768 | if (!p) { | |||
| 769 | ret = NSS_STATUS_NOTFOUND; | |||
| 770 | goto finalize; | |||
| 771 | } | |||
| 772 | ||||
| 773 | /* On success, step to the next entry. */ | |||
| 774 | p = p->entries_next; | |||
| 775 | ret = NSS_STATUS_SUCCESS; | |||
| 776 | ||||
| 777 | finalize: | |||
| 778 | /* Save position for the next call. */ | |||
| 779 | getpwent_data.position = p; | |||
| 780 | ||||
| 781 | assert_se(pthread_mutex_unlock(&getpwent_data.mutex) == 0)do { if ((__builtin_expect(!!(!(pthread_mutex_unlock(&getpwent_data .mutex) == 0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("pthread_mutex_unlock(&getpwent_data.mutex) == 0"), "../src/nss-systemd/nss-systemd.c" , 781, __PRETTY_FUNCTION__); } while (0); | |||
| 782 | ||||
| 783 | return ret; | |||
| 784 | } | |||
| 785 | ||||
| 786 | enum nss_status _nss_systemd_getgrent_r(struct group *result, char *buffer, size_t buflen, int *errnop) { | |||
| 787 | enum nss_status ret; | |||
| 788 | UserEntry *p; | |||
| 789 | size_t len; | |||
| 790 | ||||
| 791 | PROTECT_ERRNO__attribute__((cleanup(_reset_errno_))) __attribute__((unused )) int _saved_errno_ = (*__errno_location ()); | |||
| 792 | BLOCK_SIGNALS(NSS_SIGNALS_BLOCK)__attribute__((cleanup(block_signals_reset))) __attribute__ ( (unused)) sigset_t _saved_sigset = ({ sigset_t _t; do { if (( __builtin_expect(!!(!(sigprocmask_many(0, &_t, 14,26,13,17 ,20,29,1,10,12,27,23,28, -1) >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("sigprocmask_many(SIG_BLOCK, &_t, 14,26,13,17,20,29,1,10,12,27,23,28, -1) >= 0" ), "../src/nss-systemd/nss-systemd.c", 792, __PRETTY_FUNCTION__ ); } while (0); _t; }); | |||
| 793 | ||||
| 794 | assert(result)do { if ((__builtin_expect(!!(!(result)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("result"), "../src/nss-systemd/nss-systemd.c" , 794, __PRETTY_FUNCTION__); } while (0); | |||
| 795 | assert(buffer)do { if ((__builtin_expect(!!(!(buffer)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("buffer"), "../src/nss-systemd/nss-systemd.c" , 795, __PRETTY_FUNCTION__); } while (0); | |||
| 796 | assert(errnop)do { if ((__builtin_expect(!!(!(errnop)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("errnop"), "../src/nss-systemd/nss-systemd.c" , 796, __PRETTY_FUNCTION__); } while (0); | |||
| 797 | ||||
| 798 | assert_se(pthread_mutex_lock(&getgrent_data.mutex) == 0)do { if ((__builtin_expect(!!(!(pthread_mutex_lock(&getgrent_data .mutex) == 0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("pthread_mutex_lock(&getgrent_data.mutex) == 0"), "../src/nss-systemd/nss-systemd.c" , 798, __PRETTY_FUNCTION__); } while (0); | |||
| 799 | ||||
| 800 | LIST_FOREACH(entries, p, getgrent_data.position)for ((p) = (getgrent_data.position); (p); (p) = (p)->entries_next ) { | |||
| 801 | len = sizeof(char*) + strlen(p->name) + 1; | |||
| 802 | if (buflen < len) { | |||
| 803 | UNPROTECT_ERRNOdo { (*__errno_location ()) = _saved_errno_; _saved_errno_ = - 1; } while (0); | |||
| 804 | *errnop = ERANGE34; | |||
| 805 | ret = NSS_STATUS_TRYAGAIN; | |||
| 806 | goto finalize; | |||
| 807 | } | |||
| 808 | ||||
| 809 | memzero(buffer, sizeof(char*))({ size_t _l_ = (sizeof(char*)); void *_x_ = (buffer); _l_ == 0 ? _x_ : memset(_x_, 0, _l_); }); | |||
| 810 | strcpy(buffer + sizeof(char*), p->name); | |||
| 811 | ||||
| 812 | result->gr_name = buffer + sizeof(char*); | |||
| 813 | result->gr_gid = p->id; | |||
| 814 | result->gr_passwd = (char*) DYNAMIC_USER_PASSWD"*"; | |||
| 815 | result->gr_mem = (char**) buffer; | |||
| 816 | break; | |||
| 817 | } | |||
| 818 | if (!p) { | |||
| 819 | ret = NSS_STATUS_NOTFOUND; | |||
| 820 | goto finalize; | |||
| 821 | } | |||
| 822 | ||||
| 823 | /* On success, step to the next entry. */ | |||
| 824 | p = p->entries_next; | |||
| 825 | ret = NSS_STATUS_SUCCESS; | |||
| 826 | ||||
| 827 | finalize: | |||
| 828 | /* Save position for the next call. */ | |||
| 829 | getgrent_data.position = p; | |||
| 830 | ||||
| 831 | assert_se(pthread_mutex_unlock(&getgrent_data.mutex) == 0)do { if ((__builtin_expect(!!(!(pthread_mutex_unlock(&getgrent_data .mutex) == 0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("pthread_mutex_unlock(&getgrent_data.mutex) == 0"), "../src/nss-systemd/nss-systemd.c" , 831, __PRETTY_FUNCTION__); } while (0); | |||
| 832 | ||||
| 833 | return ret; | |||
| 834 | } |