1
0
mirror of https://github.com/systemd/systemd synced 2026-03-14 09:04:47 +01:00

Compare commits

..

4 Commits

Author SHA1 Message Date
Lennart Poettering
2a9cfe6b07
Merge pull request #19531 from poettering/nss-systemd-fixes
nss-systemd: two minor fixes
2021-05-07 11:15:53 +02:00
Lennart Poettering
a1aa41e4e1 nss-systemd: properly handle empty membership lists
When we are queried for membership lists on a system that has exactly
zero, then we'll return ESRCH immediately instead of at EOF. Which is
OK, but we need to handle this in various places, and not get confused
by it.
2021-05-07 09:15:40 +02:00
Lennart Poettering
e9b88a6d4e string-util: add strextendf() helper, that allows extending some allocated string via a format string
It's not going to be efficient if called in inner loops, but it's oh so
handy, and we have some code that does this:

   asprintf(&p, "%s…", b, …);
   free(b);
   b = TAKE_PTR(p);

which can now be replaced by the quicker and easier to read:

   strextendf(&p, "…", …);
2021-05-07 09:10:59 +02:00
Lennart Poettering
1fdfca4da7 nss-systemd: reset the right field 2021-05-06 22:35:49 +02:00
6 changed files with 121 additions and 29 deletions

View File

@ -803,6 +803,87 @@ char *strextend_with_separator_internal(char **x, const char *separator, ...) {
return p;
}
int strextendf(char **x, const char *format, ...) {
size_t m, a;
va_list ap;
int l;
/* Appends a formatted string to the specified string. Don't use this in inner loops, since then
* we'll spend a tonload of time in determining the length of the string passed in, over and over
* again. */
assert(x);
assert(format);
/* Let's try to use the allocated buffer, if there's room at the end still. Otherwise let's extend by 64 chars. */
if (*x) {
m = strlen(*x);
a = malloc_usable_size(*x);
assert(a >= m + 1);
} else
m = a = 0;
if (a - m < 17) { /* if there's less than 16 chars space, then enlarge the buffer first */
char *n;
if (_unlikely_(m > SIZE_MAX - 64)) /* overflow check */
return -ENOMEM;
n = realloc(*x, m + 64);
if (!n)
return -ENOMEM;
*x = n;
a = malloc_usable_size(*x);
}
/* Now, let's try to format the string into it */
va_start(ap, format);
l = vsnprintf(*x + m, a - m, format, ap);
va_end(ap);
assert(l >= 0);
if ((size_t) l < a - m) {
char *n;
/* Nice! This worked. We are done. But first, let's return the extra space we don't
* need. This should be a cheap operation, since we only lower the allocation size here,
* never increase. */
n = realloc(*x, m + (size_t) l + 1);
if (n)
*x = n;
} else {
char *n;
/* Wasn't enough. Then let's allocate exactly what we need. */
if (_unlikely_((size_t) l > SIZE_MAX - 1)) /* overflow check #1 */
goto oom;
if (_unlikely_(m > SIZE_MAX - ((size_t) l + 1))) /* overflow check #2 */
goto oom;
a = m + (size_t) l + 1;
n = realloc(*x, a);
if (!n)
goto oom;
*x = n;
va_start(ap, format);
l = vsnprintf(*x + m, a - m, format, ap);
va_end(ap);
assert((size_t) l < a - m);
}
return 0;
oom:
/* truncate the bytes added after the first vsnprintf() attempt again */
(*x)[m] = 0;
return -ENOMEM;
}
char *strrep(const char *s, unsigned n) {
char *r, *p;
size_t l;

View File

@ -152,6 +152,8 @@ char *strextend_with_separator_internal(char **x, const char *separator, ...) _s
#define strextend_with_separator(x, separator, ...) strextend_with_separator_internal(x, separator, __VA_ARGS__, NULL)
#define strextend(x, ...) strextend_with_separator_internal(x, NULL, __VA_ARGS__, NULL)
int strextendf(char **x, const char *format, ...) _printf_(2,3);
char *strrep(const char *s, unsigned n);
int split_pair(const char *s, const char *sep, char **l, char **r);

View File

@ -2967,8 +2967,7 @@ static int determine_names(void) {
if (!arg_machine) {
if (arg_directory && path_equal(arg_directory, "/"))
arg_machine = gethostname_malloc();
else {
if (arg_image) {
else if (arg_image) {
char *e;
arg_machine = strdup(basename(arg_image));
@ -2979,7 +2978,6 @@ static int determine_names(void) {
*e = 0;
} else
arg_machine = strdup(basename(arg_directory));
}
if (!arg_machine)
return log_oom();
@ -2987,20 +2985,11 @@ static int determine_names(void) {
if (!hostname_is_valid(arg_machine, 0))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to determine machine name automatically, please use -M.");
if (arg_ephemeral) {
char *b;
/* Add a random suffix when this is an
* ephemeral machine, so that we can run many
* instances at once without manually having
* to specify -M each time. */
if (asprintf(&b, "%s-%016" PRIx64, arg_machine, random_u64()) < 0)
/* Add a random suffix when this is an ephemeral machine, so that we can run many
* instances at once without manually having to specify -M each time. */
if (arg_ephemeral)
if (strextendf(&arg_machine, "-%016" PRIx64, random_u64()) < 0)
return log_oom();
free(arg_machine);
arg_machine = b;
}
}
return 0;

View File

@ -348,7 +348,7 @@ enum nss_status _nss_systemd_setgrent(int stayopen) {
_l = pthread_mutex_lock_assert(&getgrent_data.mutex);
getgrent_data.iterator = userdb_iterator_free(getgrent_data.iterator);
getpwent_data.by_membership = false;
getgrent_data.by_membership = false;
/* See _nss_systemd_setpwent() for an explanation why we use USERDB_DONT_SYNTHESIZE here */
r = groupdb_all(nss_glue_userdb_flags() | USERDB_DONT_SYNTHESIZE, &getgrent_data.iterator);
@ -441,7 +441,7 @@ enum nss_status _nss_systemd_getgrent_r(
getgrent_data.iterator = userdb_iterator_free(getgrent_data.iterator);
r = membershipdb_all(nss_glue_userdb_flags(), &getgrent_data.iterator);
if (r < 0) {
if (r < 0 && r != -ESRCH) {
UNPROTECT_ERRNO;
*errnop = -r;
return NSS_STATUS_UNAVAIL;
@ -454,7 +454,7 @@ enum nss_status _nss_systemd_getgrent_r(
return NSS_STATUS_UNAVAIL;
} else if (!STR_IN_SET(gr->group_name, root_group.gr_name, nobody_group.gr_name)) {
r = membershipdb_by_group_strv(gr->group_name, nss_glue_userdb_flags(), &members);
if (r < 0) {
if (r < 0 && r != -ESRCH) {
UNPROTECT_ERRNO;
*errnop = -r;
return NSS_STATUS_UNAVAIL;
@ -465,6 +465,9 @@ enum nss_status _nss_systemd_getgrent_r(
if (getgrent_data.by_membership) {
_cleanup_(_nss_systemd_unblockp) bool blocked = false;
if (!getgrent_data.iterator)
return NSS_STATUS_NOTFOUND;
for (;;) {
_cleanup_free_ char *user_name = NULL, *group_name = NULL;

View File

@ -216,7 +216,7 @@ enum nss_status userdb_getgrnam(
}
r = membershipdb_by_group_strv(name, nss_glue_userdb_flags(), &members);
if (r < 0) {
if (r < 0 && r != -ESRCH) {
*errnop = -r;
return NSS_STATUS_UNAVAIL;
}
@ -309,7 +309,7 @@ enum nss_status userdb_getgrgid(
from_nss = false;
r = membershipdb_by_group_strv(g->group_name, nss_glue_userdb_flags(), &members);
if (r < 0) {
if (r < 0 && r != -ESRCH) {
*errnop = -r;
return NSS_STATUS_UNAVAIL;
}

View File

@ -970,6 +970,22 @@ static void test_strverscmp_improved(void) {
assert_se(strverscmp_improved("123_aa2-67.89", "123aa+2-67.89") == 0);
}
static void test_strextendf(void) {
_cleanup_free_ char *p = NULL;
assert_se(strextendf(&p, "<%i>", 77) >= 0);
assert_se(streq(p, "<77>"));
assert_se(strextendf(&p, "<%i>", 99) >= 0);
assert_se(streq(p, "<77><99>"));
assert_se(strextendf(&p, "<%80i>", 88) >= 0);
assert_se(streq(p, "<77><99>< 88>"));
assert_se(strextendf(&p, "<%08x>", 0x1234) >= 0);
assert_se(streq(p, "<77><99>< 88><00001234>"));
}
int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
@ -1008,6 +1024,7 @@ int main(int argc, char *argv[]) {
test_string_contains_word_strv();
test_string_contains_word();
test_strverscmp_improved();
test_strextendf();
return 0;
}