Merge pull request #9783 from poettering/get-user-creds-flags

beef up get_user_creds() a bit and other improvements
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2018-08-21 10:09:33 +02:00 committed by GitHub
commit 7692fed98b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 216 additions and 124 deletions

View File

@ -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_PREFER_NSS) ||
(!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_PREFER_NSS 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_PREFER_NSS 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_PREFER_NSS)) {
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 (home) {
if (FLAGS_SET(flags, USER_CREDS_CLEAN) && empty_or_root(p->pw_dir))
*home = NULL;
else
*home = p->pw_dir;
}
if (shell)
*shell = p->pw_shell;
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;
}
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 && empty_or_root(*home))
*home = NULL;
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;

View File

@ -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_PREFER_NSS = 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);

View File

@ -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;

View File

@ -570,36 +570,44 @@ static void drop_outside_root(const char *root_directory, MountEntry *m, size_t
*n = t - m;
}
static int clone_device_node(const char *d, const char *temporary_mount, bool *make_devnode) {
const char *dn;
static int clone_device_node(
const char *d,
const char *temporary_mount,
bool *make_devnode) {
_cleanup_free_ char *sl = NULL;
const char *dn, *bn, *t;
struct stat st;
int r;
if (stat(d, &st) < 0) {
if (errno == ENOENT)
if (errno == ENOENT) {
log_debug_errno(errno, "Device node '%s' to clone does not exist, ignoring.", d);
return -ENXIO;
return -errno;
}
return log_debug_errno(errno, "Failed to stat() device node '%s' to clone, ignoring: %m", d);
}
if (!S_ISBLK(st.st_mode) &&
!S_ISCHR(st.st_mode))
!S_ISCHR(st.st_mode)) {
log_debug("Device node '%s' to clone is not a device node, ignoring.", d);
return -EINVAL;
if (st.st_rdev == 0)
return -ENXIO;
}
dn = strjoina(temporary_mount, d);
/* First, try to create device node properly */
if (*make_devnode) {
mac_selinux_create_file_prepare(d, st.st_mode);
r = mknod(dn, st.st_mode, st.st_rdev);
mac_selinux_create_file_clear();
if (r == 0)
return 0;
if (r >= 0)
goto add_symlink;
if (errno != EPERM)
return log_debug_errno(errno, "mknod failed for %s: %m", d);
/* This didn't work, let's not try this again for the next iterations. */
*make_devnode = false;
}
@ -608,9 +616,8 @@ static int clone_device_node(const char *d, const char *temporary_mount, bool *m
mac_selinux_create_file_prepare(d, 0);
r = mknod(dn, S_IFREG, 0);
mac_selinux_create_file_clear();
if (r < 0 && errno != EEXIST)
return log_debug_errno(errno, "mknod fallback failed for %s: %m", d);
return log_debug_errno(errno, "mknod() fallback failed for '%s': %m", d);
/* Fallback to bind-mounting:
* The assumption here is that all used device nodes carry standard
@ -618,7 +625,23 @@ static int clone_device_node(const char *d, const char *temporary_mount, bool *m
* either be owned by root:root or root:tty (e.g. /dev/tty, /dev/ptmx)
* and should not carry ACLs. */
if (mount(d, dn, NULL, MS_BIND, NULL) < 0)
return log_debug_errno(errno, "mount failed for %s: %m", d);
return log_debug_errno(errno, "Bind mounting failed for '%s': %m", d);
add_symlink:
bn = path_startswith(d, "/dev/");
if (!bn)
return 0;
/* Create symlinks like /dev/char/1:9 → ../urandom */
if (asprintf(&sl, "%s/dev/%s/%u:%u", temporary_mount, S_ISCHR(st.st_mode) ? "char" : "block", major(st.st_rdev), minor(st.st_rdev)) < 0)
return log_oom();
(void) mkdir_parents(sl, 0755);
t = strjoina("../", bn);
if (symlink(t, sl) < 0)
log_debug_errno(errno, "Failed to symlink '%s' to '%s': %m", t, sl);
return 0;
}

View File

@ -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);

View File

@ -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;

View File

@ -909,7 +909,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]);
@ -1097,7 +1097,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]);
}
@ -1130,7 +1130,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]);
@ -1165,7 +1165,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]);

View File

@ -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;

View File

@ -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\"" :

View File

@ -223,7 +223,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."

View File

@ -60,7 +60,7 @@ static int netdev_tuntap_add(NetDev *netdev, struct ifreq *ifr) {
assert(netdev);
assert(ifr);
fd = open(TUN_DEV, O_RDWR);
fd = open(TUN_DEV, O_RDWR|O_CLOEXEC);
if (fd < 0)
return log_netdev_error_errno(netdev, -errno, "Failed to open tun dev: %m");
@ -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);

View File

@ -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;

View File

@ -115,7 +115,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)

View File

@ -1790,7 +1790,12 @@ static int copy_devnodes(const char *dest) {
struct stat st;
from = strappend("/dev/", d);
if (!from)
return log_oom();
to = prefix_root(dest, from);
if (!to)
return log_oom();
if (stat(from, &st) < 0) {
@ -1803,6 +1808,8 @@ static int copy_devnodes(const char *dest) {
return -EIO;
} else {
_cleanup_free_ char *sl = NULL, *prefixed = NULL, *dn = NULL, *t = NULL;
if (mknod(to, st.st_mode, st.st_rdev) < 0) {
/* Explicitly warn the user when /dev is already populated. */
if (errno == EEXIST)
@ -1810,8 +1817,7 @@ static int copy_devnodes(const char *dest) {
if (errno != EPERM)
return log_error_errno(errno, "mknod(%s) failed: %m", to);
/* Some systems abusively restrict mknod but
* allow bind mounts. */
/* Some systems abusively restrict mknod but allow bind mounts. */
r = touch(to);
if (r < 0)
return log_error_errno(r, "touch (%s) failed: %m", to);
@ -1823,6 +1829,28 @@ static int copy_devnodes(const char *dest) {
r = userns_lchown(to, 0, 0);
if (r < 0)
return log_error_errno(r, "chown() of device node %s failed: %m", to);
dn = strjoin("/dev/", S_ISCHR(st.st_mode) ? "char" : "block");
if (!dn)
return log_oom();
r = userns_mkdir(dest, dn, 0755, 0, 0);
if (r < 0)
return log_error_errno(r, "Failed to create '%s': %m", dn);
if (asprintf(&sl, "%s/%u:%u", dn, major(st.st_rdev), minor(st.st_rdev)) < 0)
return log_oom();
prefixed = prefix_root(dest, sl);
if (!prefixed)
return log_oom();
t = strjoin("../", d);
if (!t)
return log_oom();
if (symlink(t, prefixed) < 0)
log_debug_errno(errno, "Failed to symlink '%s' to '%s': %m", t, prefixed);
}
}

View File

@ -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;

View File

@ -34,6 +34,7 @@ static void test_parse_etc_hosts(const char *fname) {
assert_se(fd >= 0);
f = fdopen(fd, "r+");
assert_se(f);
fputs("1.2.3.4 some.where\n", f);
fputs("1.2.3.5 some.where\n", f);
fputs("::0 some.where some.other\n", f);
@ -49,7 +50,7 @@ static void test_parse_etc_hosts(const char *fname) {
if (fname)
return;
EtcHostsItemByName *bn;
assert_se(bn = hashmap_get(hosts.by_name, "some.where"));
assert_se(bn->n_addresses == 3);

View File

@ -1239,7 +1239,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);
@ -1252,7 +1252,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_PREFER_NSS);
if (r < 0)
return log_error_errno(r, "Failed to resolve user %s: %m", arg_exec_user);

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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)");

View File

@ -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;

View File

@ -2728,7 +2728,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);
@ -2740,7 +2740,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);

View File

@ -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;