From fafff8f1ffdf24517921d7779c2a9eb89766df30 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 2 Aug 2018 18:36:47 +0200 Subject: [PATCH] user-util: rework get_user_creds() Let's fold get_user_creds_clean() into get_user_creds(), and introduce a flags argument for it to select "clean" behaviour. This flags parameter also learns to other new flags: - USER_CREDS_SYNTHESIZE_FALLBACK: in this mode the user records for root/nobody are only synthesized as fallback. Normally, the synthesized records take precedence over what is in the user database. With this flag set this is reversed, and the user database takes precedence, and the synthesized records are only used if they are missing there. This flag should be set in cases where doing NSS is deemed safe, and where there's interest in knowing the correct shell, for example if the admin changed root's shell to zsh or suchlike. - USER_CREDS_ALLOW_MISSING: if set, and a UID/GID is specified by numeric value, and there's no user/group record for it accept it anyway. This allows us to fix #9767 This then also ports all users to set the most appropriate flags. Fixes: #9767 [zj: remove one isempty() call] --- src/basic/user-util.c | 173 ++++++++++++++++++++++++++----------------- src/basic/user-util.h | 11 ++- src/core/execute.c | 6 +- src/core/socket.c | 4 +- src/coredump/coredump.c | 2 +- src/login/loginctl.c | 8 +- src/login/logind-core.c | 2 +- src/login/user-runtime-dir.c | 4 +- src/mount/mount-tool.c | 2 +- src/network/netdev/tuntap.c | 6 +- src/network/networkd.c | 2 +- src/notify/notify.c | 2 +- src/resolve/resolved.c | 2 +- src/run/run.c | 4 +- src/shared/condition.c | 2 +- src/test/test-acl-util.c | 2 +- src/test/test-ipcrm.c | 2 +- src/test/test-user-util.c | 4 +- src/timesync/timesyncd.c | 2 +- src/tmpfiles/tmpfiles.c | 4 +- src/udev/udev-rules.c | 8 +- 21 files changed, 146 insertions(+), 106 deletions(-) diff --git a/src/basic/user-util.c b/src/basic/user-util.c index a562a39..b618559 100644 --- a/src/basic/user-util.c +++ b/src/basic/user-util.c @@ -87,17 +87,31 @@ char *getusername_malloc(void) { return uid_to_name(getuid()); } -int get_user_creds( +static inline bool is_nologin_shell(const char *shell) { + + return PATH_IN_SET(shell, + /* 'nologin' is the friendliest way to disable logins for a user account. It prints a nice + * message and exits. Different distributions place the binary at different places though, + * hence let's list them all. */ + "/bin/nologin", + "/sbin/nologin", + "/usr/bin/nologin", + "/usr/sbin/nologin", + /* 'true' and 'false' work too for the same purpose, but are less friendly as they don't do + * any message printing. Different distributions place the binary at various places but at + * least not in the 'sbin' directory. */ + "/bin/false", + "/usr/bin/false", + "/bin/true", + "/usr/bin/true"); +} + +static int synthesize_user_creds( const char **username, uid_t *uid, gid_t *gid, const char **home, - const char **shell) { - - struct passwd *p; - uid_t u; - - assert(username); - assert(*username); + const char **shell, + UserCredsFlags flags) { /* We enforce some special rules for uid=0 and uid=65534: in order to avoid NSS lookups for root we hardcode * their user record data. */ @@ -129,32 +143,85 @@ int get_user_creds( *gid = GID_NOBODY; if (home) - *home = "/"; + *home = FLAGS_SET(flags, USER_CREDS_CLEAN) ? NULL : "/"; if (shell) - *shell = "/sbin/nologin"; + *shell = FLAGS_SET(flags, USER_CREDS_CLEAN) ? NULL : "/sbin/nologin"; return 0; } + return -ENOMEDIUM; +} + +int get_user_creds( + const char **username, + uid_t *uid, gid_t *gid, + const char **home, + const char **shell, + UserCredsFlags flags) { + + uid_t u = UID_INVALID; + struct passwd *p; + int r; + + assert(username); + assert(*username); + + if (!FLAGS_SET(flags, USER_CREDS_SYNTHESIZE_FALLBACK) || + (!home && !shell)) { + + /* So here's the deal: normally, we'll try to synthesize all records we can synthesize, and override + * the user database with that. However, if the user specifies USER_CREDS_SYNTHESIZE_FALLBACK then the + * user database will override the synthetic records instead — except if the user is only interested in + * the UID and/or GID (but not the home directory, or the shell), in which case we'll always override + * the user database (i.e. the USER_CREDS_SYNTHESIZE_FALLBACK flag has no effect in this case). Why? + * Simply because there are valid usecase where the user might change the home directory or the shell + * of the relevant users, but changing the UID/GID mappings for them is something we explicitly don't + * support. */ + + r = synthesize_user_creds(username, uid, gid, home, shell, flags); + if (r >= 0) + return 0; + if (r != -ENOMEDIUM) /* not a username we can synthesize */ + return r; + } + if (parse_uid(*username, &u) >= 0) { errno = 0; p = getpwuid(u); - /* If there are multiple users with the same id, make - * sure to leave $USER to the configured value instead - * of the first occurrence in the database. However if - * the uid was configured by a numeric uid, then let's - * pick the real username from /etc/passwd. */ + /* If there are multiple users with the same id, make sure to leave $USER to the configured value + * instead of the first occurrence in the database. However if the uid was configured by a numeric uid, + * then let's pick the real username from /etc/passwd. */ if (p) *username = p->pw_name; + else if (FLAGS_SET(flags, USER_CREDS_ALLOW_MISSING) && !gid && !home && !shell) { + + /* If the specified user is a numeric UID and it isn't in the user database, and the caller + * passed USER_CREDS_ALLOW_MISSING and was only interested in the UID, then juts return that + * and don't complain. */ + + if (uid) + *uid = u; + + return 0; + } } else { errno = 0; p = getpwnam(*username); } + if (!p) { + r = errno > 0 ? -errno : -ESRCH; - if (!p) - return errno > 0 ? -errno : -ESRCH; + /* If the user requested that we only synthesize as fallback, do so now */ + if (FLAGS_SET(flags, USER_CREDS_SYNTHESIZE_FALLBACK)) { + if (synthesize_user_creds(username, uid, gid, home, shell, flags) >= 0) + return 0; + } + + return r; + } if (uid) { if (!uid_is_valid(p->pw_uid)) @@ -170,66 +237,30 @@ int get_user_creds( *gid = p->pw_gid; } - if (home) - *home = p->pw_dir; - - if (shell) - *shell = p->pw_shell; - - return 0; -} - -static inline bool is_nologin_shell(const char *shell) { - - return PATH_IN_SET(shell, - /* 'nologin' is the friendliest way to disable logins for a user account. It prints a nice - * message and exits. Different distributions place the binary at different places though, - * hence let's list them all. */ - "/bin/nologin", - "/sbin/nologin", - "/usr/bin/nologin", - "/usr/sbin/nologin", - /* 'true' and 'false' work too for the same purpose, but are less friendly as they don't do - * any message printing. Different distributions place the binary at various places but at - * least not in the 'sbin' directory. */ - "/bin/false", - "/usr/bin/false", - "/bin/true", - "/usr/bin/true"); -} - -int get_user_creds_clean( - const char **username, - uid_t *uid, gid_t *gid, - const char **home, - const char **shell) { - - int r; - - /* Like get_user_creds(), but resets home/shell to NULL if they don't contain anything relevant. */ - - r = get_user_creds(username, uid, gid, home, shell); - if (r < 0) - return r; - - if (shell && - (isempty(*shell) || is_nologin_shell(*shell))) - *shell = NULL; + if (home) { + if (FLAGS_SET(flags, USER_CREDS_CLEAN) && empty_or_root(p->pw_dir)) + *home = NULL; + else + *home = p->pw_dir; + } - if (home && empty_or_root(*home)) - *home = NULL; + if (shell) { + if (FLAGS_SET(flags, USER_CREDS_CLEAN) && (isempty(p->pw_shell) || is_nologin_shell(p->pw_shell))) + *shell = NULL; + else + *shell = p->pw_shell; + } return 0; } -int get_group_creds(const char **groupname, gid_t *gid) { +int get_group_creds(const char **groupname, gid_t *gid, UserCredsFlags flags) { struct group *g; gid_t id; assert(groupname); - /* We enforce some special rules for gid=0: in order to avoid - * NSS lookups for root we hardcode its data. */ + /* We enforce some special rules for gid=0: in order to avoid NSS lookups for root we hardcode its data. */ if (STR_IN_SET(*groupname, "root", "0")) { *groupname = "root"; @@ -256,6 +287,12 @@ int get_group_creds(const char **groupname, gid_t *gid) { if (g) *groupname = g->gr_name; + else if (FLAGS_SET(flags, USER_CREDS_ALLOW_MISSING)) { + if (gid) + *gid = id; + + return 0; + } } else { errno = 0; g = getgrnam(*groupname); @@ -391,7 +428,7 @@ int in_group(const char *name) { int r; gid_t gid; - r = get_group_creds(&name, &gid); + r = get_group_creds(&name, &gid, 0); if (r < 0) return r; diff --git a/src/basic/user-util.h b/src/basic/user-util.h index b2f198c..a18f4d6 100644 --- a/src/basic/user-util.h +++ b/src/basic/user-util.h @@ -25,9 +25,14 @@ static inline int parse_gid(const char *s, gid_t *ret_gid) { char* getlogname_malloc(void); char* getusername_malloc(void); -int get_user_creds(const char **username, uid_t *uid, gid_t *gid, const char **home, const char **shell); -int get_user_creds_clean(const char **username, uid_t *uid, gid_t *gid, const char **home, const char **shell); -int get_group_creds(const char **groupname, gid_t *gid); +typedef enum UserCredsFlags { + USER_CREDS_SYNTHESIZE_FALLBACK = 1 << 0, /* if set, only synthesize user records if database lacks them. Normally we bypass the userdb entirely for the records we can synthesize */ + USER_CREDS_ALLOW_MISSING = 1 << 1, /* if a numeric UID string is resolved, be OK if there's no record for it */ + USER_CREDS_CLEAN = 1 << 2, /* try to clean up shell and home fields with invalid data */ +} UserCredsFlags; + +int get_user_creds(const char **username, uid_t *uid, gid_t *gid, const char **home, const char **shell, UserCredsFlags flags); +int get_group_creds(const char **groupname, gid_t *gid, UserCredsFlags flags); char* uid_to_name(uid_t uid); char* gid_to_name(gid_t gid); diff --git a/src/core/execute.c b/src/core/execute.c index a35dbac..8867278 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -921,7 +921,7 @@ static int get_fixed_user(const ExecContext *c, const char **user, * (i.e. are "/" or "/bin/nologin"). */ name = c->user; - r = get_user_creds_clean(&name, uid, gid, home, shell); + r = get_user_creds(&name, uid, gid, home, shell, USER_CREDS_CLEAN); if (r < 0) return r; @@ -939,7 +939,7 @@ static int get_fixed_group(const ExecContext *c, const char **group, gid_t *gid) return 0; name = c->group; - r = get_group_creds(&name, gid); + r = get_group_creds(&name, gid, 0); if (r < 0) return r; @@ -1011,7 +1011,7 @@ static int get_supplementary_groups(const ExecContext *c, const char *user, return -E2BIG; g = *i; - r = get_group_creds(&g, l_gids+k); + r = get_group_creds(&g, l_gids+k, 0); if (r < 0) return r; diff --git a/src/core/socket.c b/src/core/socket.c index aedbf51..aa370e7 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -1934,7 +1934,7 @@ static int socket_chown(Socket *s, pid_t *_pid) { if (!isempty(s->user)) { const char *user = s->user; - r = get_user_creds(&user, &uid, &gid, NULL, NULL); + r = get_user_creds(&user, &uid, &gid, NULL, NULL, 0); if (r < 0) { log_unit_error_errno(UNIT(s), r, "Failed to resolve user %s: %m", user); _exit(EXIT_USER); @@ -1944,7 +1944,7 @@ static int socket_chown(Socket *s, pid_t *_pid) { if (!isempty(s->group)) { const char *group = s->group; - r = get_group_creds(&group, &gid); + r = get_group_creds(&group, &gid, 0); if (r < 0) { log_unit_error_errno(UNIT(s), r, "Failed to resolve group %s: %m", group); _exit(EXIT_GROUP); diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c index 20a1cbd..31274ee 100644 --- a/src/coredump/coredump.c +++ b/src/coredump/coredump.c @@ -672,7 +672,7 @@ static int change_uid_gid(const char *context[]) { if (uid <= SYSTEM_UID_MAX) { const char *user = "systemd-coredump"; - r = get_user_creds(&user, &uid, &gid, NULL, NULL); + r = get_user_creds(&user, &uid, &gid, NULL, NULL, 0); if (r < 0) { log_warning_errno(r, "Cannot resolve %s user. Proceeding to dump core as root: %m", user); uid = gid = 0; diff --git a/src/login/loginctl.c b/src/login/loginctl.c index be55fdb..ad957f0 100644 --- a/src/login/loginctl.c +++ b/src/login/loginctl.c @@ -912,7 +912,7 @@ static int show_user(int argc, char *argv[], void *userdata) { const char *path = NULL; uid_t uid; - r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL); + r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL, 0); if (r < 0) return log_error_errno(r, "Failed to look up user %s: %m", argv[i]); @@ -1108,7 +1108,7 @@ static int enable_linger(int argc, char *argv[], void *userdata) { if (isempty(argv[i])) uid = UID_INVALID; else { - r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL); + r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL, 0); if (r < 0) return log_error_errno(r, "Failed to look up user %s: %m", argv[i]); } @@ -1143,7 +1143,7 @@ static int terminate_user(int argc, char *argv[], void *userdata) { for (i = 1; i < argc; i++) { uid_t uid; - r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL); + r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL, 0); if (r < 0) return log_error_errno(r, "Failed to look up user %s: %m", argv[i]); @@ -1180,7 +1180,7 @@ static int kill_user(int argc, char *argv[], void *userdata) { for (i = 1; i < argc; i++) { uid_t uid; - r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL); + r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL, 0); if (r < 0) return log_error_errno(r, "Failed to look up user %s: %m", argv[i]); diff --git a/src/login/logind-core.c b/src/login/logind-core.c index dbae4bf..dc728f7 100644 --- a/src/login/logind-core.c +++ b/src/login/logind-core.c @@ -152,7 +152,7 @@ int manager_add_user_by_name(Manager *m, const char *name, User **_user) { assert(m); assert(name); - r = get_user_creds(&name, &uid, &gid, NULL, NULL); + r = get_user_creds(&name, &uid, &gid, NULL, NULL, 0); if (r < 0) return r; diff --git a/src/login/user-runtime-dir.c b/src/login/user-runtime-dir.c index 51b864c..9f2c594a 100644 --- a/src/login/user-runtime-dir.c +++ b/src/login/user-runtime-dir.c @@ -117,7 +117,7 @@ static int do_mount(const char *user) { gid_t gid; int r; - r = get_user_creds(&user, &uid, &gid, NULL, NULL); + r = get_user_creds(&user, &uid, &gid, NULL, NULL, 0); if (r < 0) return log_error_errno(r, r == -ESRCH ? "No such user \"%s\"" : @@ -141,7 +141,7 @@ static int do_umount(const char *user) { /* The user may be already removed. So, first try to parse the string by parse_uid(), * and if it fails, fallback to get_user_creds().*/ if (parse_uid(user, &uid) < 0) { - r = get_user_creds(&user, &uid, NULL, NULL, NULL); + r = get_user_creds(&user, &uid, NULL, NULL, NULL, 0); if (r < 0) return log_error_errno(r, r == -ESRCH ? "No such user \"%s\"" : diff --git a/src/mount/mount-tool.c b/src/mount/mount-tool.c index 64c1efd..5c96fd8 100644 --- a/src/mount/mount-tool.c +++ b/src/mount/mount-tool.c @@ -212,7 +212,7 @@ static int parse_argv(int argc, char *argv[]) { case ARG_OWNER: { const char *user = optarg; - r = get_user_creds(&user, &arg_uid, &arg_gid, NULL, NULL); + r = get_user_creds(&user, &arg_uid, &arg_gid, NULL, NULL, 0); if (r < 0) return log_error_errno(r, r == -EBADMSG ? "UID or GID of user %s are invalid." diff --git a/src/network/netdev/tuntap.c b/src/network/netdev/tuntap.c index c97478b..951138d 100644 --- a/src/network/netdev/tuntap.c +++ b/src/network/netdev/tuntap.c @@ -75,10 +75,9 @@ static int netdev_tuntap_add(NetDev *netdev, struct ifreq *ifr) { assert(t); if (t->user_name) { - user = t->user_name; - r = get_user_creds(&user, &uid, NULL, NULL, NULL); + r = get_user_creds(&user, &uid, NULL, NULL, NULL, USER_CREDS_ALLOW_MISSING); if (r < 0) return log_netdev_error_errno(netdev, r, "Cannot resolve user name %s: %m", t->user_name); @@ -87,10 +86,9 @@ static int netdev_tuntap_add(NetDev *netdev, struct ifreq *ifr) { } if (t->group_name) { - group = t->group_name; - r = get_group_creds(&group, &gid); + r = get_group_creds(&group, &gid, USER_CREDS_ALLOW_MISSING); if (r < 0) return log_netdev_error_errno(netdev, r, "Cannot resolve group name %s: %m", t->group_name); diff --git a/src/network/networkd.c b/src/network/networkd.c index d2467b7..8f7b5b7 100644 --- a/src/network/networkd.c +++ b/src/network/networkd.c @@ -28,7 +28,7 @@ int main(int argc, char *argv[]) { goto out; } - r = get_user_creds(&user, &uid, &gid, NULL, NULL); + r = get_user_creds(&user, &uid, &gid, NULL, NULL, 0); if (r < 0) { log_error_errno(r, "Cannot resolve user name %s: %m", user); goto out; diff --git a/src/notify/notify.c b/src/notify/notify.c index e928094..3d607c7 100644 --- a/src/notify/notify.c +++ b/src/notify/notify.c @@ -103,7 +103,7 @@ static int parse_argv(int argc, char *argv[]) { case ARG_UID: { const char *u = optarg; - r = get_user_creds(&u, &arg_uid, &arg_gid, NULL, NULL); + r = get_user_creds(&u, &arg_uid, &arg_gid, NULL, NULL, 0); if (r == -ESRCH) /* If the user doesn't exist, then accept it anyway as numeric */ r = parse_uid(u, &arg_uid); if (r < 0) diff --git a/src/resolve/resolved.c b/src/resolve/resolved.c index 6ff56bc..d4d6cba 100644 --- a/src/resolve/resolved.c +++ b/src/resolve/resolved.c @@ -37,7 +37,7 @@ int main(int argc, char *argv[]) { goto finish; } - r = get_user_creds(&user, &uid, &gid, NULL, NULL); + r = get_user_creds(&user, &uid, &gid, NULL, NULL, 0); if (r < 0) { log_error_errno(r, "Cannot resolve user name %s: %m", user); goto finish; diff --git a/src/run/run.c b/src/run/run.c index 2910fcb..effbbb6 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -1232,7 +1232,7 @@ static int start_transient_scope( if (arg_exec_group) { gid_t gid; - r = get_group_creds(&arg_exec_group, &gid); + r = get_group_creds(&arg_exec_group, &gid, 0); if (r < 0) return log_error_errno(r, "Failed to resolve group %s: %m", arg_exec_group); @@ -1245,7 +1245,7 @@ static int start_transient_scope( uid_t uid; gid_t gid; - r = get_user_creds_clean(&arg_exec_user, &uid, &gid, &home, &shell); + r = get_user_creds(&arg_exec_user, &uid, &gid, &home, &shell, USER_CREDS_CLEAN|USER_CREDS_SYNTHESIZE_FALLBACK); if (r < 0) return log_error_errno(r, "Failed to resolve user %s: %m", arg_exec_user); diff --git a/src/shared/condition.c b/src/shared/condition.c index 2969a89..d0b17fe 100644 --- a/src/shared/condition.c +++ b/src/shared/condition.c @@ -219,7 +219,7 @@ static int condition_test_user(Condition *c) { return streq(c->parameter, "root"); u = c->parameter; - r = get_user_creds(&u, &id, NULL, NULL, NULL); + r = get_user_creds(&u, &id, NULL, NULL, NULL, USER_CREDS_ALLOW_MISSING); if (r < 0) return 0; diff --git a/src/test/test-acl-util.c b/src/test/test-acl-util.c index 81eb404..a8d4135 100644 --- a/src/test/test-acl-util.c +++ b/src/test/test-acl-util.c @@ -32,7 +32,7 @@ static void test_add_acls_for_user(void) { if (getuid() == 0) { const char *nobody = NOBODY_USER_NAME; - r = get_user_creds(&nobody, &uid, NULL, NULL, NULL); + r = get_user_creds(&nobody, &uid, NULL, NULL, NULL, 0); if (r < 0) uid = 0; } else diff --git a/src/test/test-ipcrm.c b/src/test/test-ipcrm.c index 106c299..6cdf48a 100644 --- a/src/test/test-ipcrm.c +++ b/src/test/test-ipcrm.c @@ -9,7 +9,7 @@ int main(int argc, char *argv[]) { int r; const char* name = argv[1] ?: NOBODY_USER_NAME; - r = get_user_creds(&name, &uid, NULL, NULL, NULL); + r = get_user_creds(&name, &uid, NULL, NULL, NULL, 0); if (r < 0) { log_full_errno(r == -ESRCH ? LOG_NOTICE : LOG_ERR, r, "Failed to resolve \"%s\": %m", name); diff --git a/src/test/test-user-util.c b/src/test/test-user-util.c index c1428fa..b291aa0 100644 --- a/src/test/test-user-util.c +++ b/src/test/test-user-util.c @@ -159,7 +159,7 @@ static void test_get_user_creds_one(const char *id, const char *name, uid_t uid, log_info("/* %s(\"%s\", \"%s\", "UID_FMT", "GID_FMT", \"%s\", \"%s\") */", __func__, id, name, uid, gid, home, shell); - r = get_user_creds(&id, &ruid, &rgid, &rhome, &rshell); + r = get_user_creds(&id, &ruid, &rgid, &rhome, &rshell, 0); log_info_errno(r, "got \"%s\", "UID_FMT", "GID_FMT", \"%s\", \"%s\": %m", id, ruid, rgid, strnull(rhome), strnull(rshell)); if (!synthesize_nobody() && streq(name, NOBODY_USER_NAME)) { @@ -180,7 +180,7 @@ static void test_get_group_creds_one(const char *id, const char *name, gid_t gid log_info("/* %s(\"%s\", \"%s\", "GID_FMT") */", __func__, id, name, gid); - r = get_group_creds(&id, &rgid); + r = get_group_creds(&id, &rgid, 0); log_info_errno(r, "got \"%s\", "GID_FMT": %m", id, rgid); if (!synthesize_nobody() && streq(name, NOBODY_GROUP_NAME)) { log_info("(skipping detailed tests because nobody is not synthesized)"); diff --git a/src/timesync/timesyncd.c b/src/timesync/timesyncd.c index 987cded..9a43c61 100644 --- a/src/timesync/timesyncd.c +++ b/src/timesync/timesyncd.c @@ -107,7 +107,7 @@ int main(int argc, char *argv[]) { gid = getegid(); if (uid_current == 0) { - r = get_user_creds(&user, &uid, &gid, NULL, NULL); + r = get_user_creds(&user, &uid, &gid, NULL, NULL, 0); if (r < 0) { log_error_errno(r, "Cannot resolve user name %s: %m", user); goto finish; diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index cfd9044..c62d026 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -2704,7 +2704,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer, bool if (!isempty(user) && !streq(user, "-")) { const char *u = user; - r = get_user_creds(&u, &i.uid, NULL, NULL, NULL); + r = get_user_creds(&u, &i.uid, NULL, NULL, NULL, USER_CREDS_ALLOW_MISSING); if (r < 0) { *invalid_config = true; return log_error_errno(r, "[%s:%u] Unknown user '%s'.", fname, line, user); @@ -2716,7 +2716,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer, bool if (!isempty(group) && !streq(group, "-")) { const char *g = group; - r = get_group_creds(&g, &i.gid); + r = get_group_creds(&g, &i.gid, USER_CREDS_ALLOW_MISSING); if (r < 0) { *invalid_config = true; log_error("[%s:%u] Unknown group '%s'.", fname, line, group); diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c index f9eff70..58ce71c 100644 --- a/src/udev/udev-rules.c +++ b/src/udev/udev-rules.c @@ -481,7 +481,7 @@ static uid_t add_uid(struct udev_rules *rules, const char *owner) { return uid; } } - r = get_user_creds(&owner, &uid, NULL, NULL, NULL); + r = get_user_creds(&owner, &uid, NULL, NULL, NULL, USER_CREDS_ALLOW_MISSING); if (r < 0) log_unknown_owner(r, "user", owner); @@ -524,7 +524,7 @@ static gid_t add_gid(struct udev_rules *rules, const char *group) { return gid; } } - r = get_group_creds(&group, &gid); + r = get_group_creds(&group, &gid, USER_CREDS_ALLOW_MISSING); if (r < 0) log_unknown_owner(r, "group", group); @@ -2110,7 +2110,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules, event->owner_final = true; udev_event_apply_format(event, rules_str(rules, cur->key.value_off), owner, sizeof(owner), false); event->owner_set = true; - r = get_user_creds(&ow, &event->uid, NULL, NULL, NULL); + r = get_user_creds(&ow, &event->uid, NULL, NULL, NULL, USER_CREDS_ALLOW_MISSING); if (r < 0) { log_unknown_owner(r, "user", owner); event->uid = 0; @@ -2131,7 +2131,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules, event->group_final = true; udev_event_apply_format(event, rules_str(rules, cur->key.value_off), group, sizeof(group), false); event->group_set = true; - r = get_group_creds(&gr, &event->gid); + r = get_group_creds(&gr, &event->gid, USER_CREDS_ALLOW_MISSING); if (r < 0) { log_unknown_owner(r, "group", group); event->gid = 0; -- 2.7.4