From 3f9721fef0f2e4da181eab9b20bac127f30efa08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Fri, 12 Mar 2021 11:57:25 +0100 Subject: [PATCH 1/4] Rename test-nss to test-nss-hosts --- src/test/meson.build | 2 +- src/test/{test-nss.c => test-nss-hosts.c} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/test/{test-nss.c => test-nss-hosts.c} (100%) diff --git a/src/test/meson.build b/src/test/meson.build index ff40a8d10d..af55cbac82 100644 --- a/src/test/meson.build +++ b/src/test/meson.build @@ -540,7 +540,7 @@ tests += [ [['src/test/test-gcrypt-util.c'], [], [], [], 'HAVE_GCRYPT'], - [['src/test/test-nss.c'], + [['src/test/test-nss-hosts.c'], [], [libdl], [], 'ENABLE_NSS', 'manual'], diff --git a/src/test/test-nss.c b/src/test/test-nss-hosts.c similarity index 100% rename from src/test/test-nss.c rename to src/test/test-nss-hosts.c From f0d1266821771724b09a00764f4e20478c77f0a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Fri, 12 Mar 2021 14:25:56 +0100 Subject: [PATCH 2/4] test-nss-users: add new nss test that resolves users and groups Inspired by https://bugzilla.redhat.com/show_bug.cgi?id=1929936. This is similar to test-nss-hosts, but does users, groups, uid, gids. Functions tested are: _nss_*_getpwnam_r _nss_*_getgrnam_r _nss_*_getpwgid_r _nss_*_getgrgid_r Other entry points should be tested too, but it's not relevant to the bug I was investigating, so I'm leaving that for later ;) --- src/basic/nss-util.h | 22 ++++ src/test/meson.build | 11 +- src/test/nss-test-util.c | 42 +++++++ src/test/nss-test-util.h | 8 ++ src/test/test-nss-hosts.c | 47 +------ src/test/test-nss-users.c | 258 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 346 insertions(+), 42 deletions(-) create mode 100644 src/test/nss-test-util.c create mode 100644 src/test/nss-test-util.h create mode 100644 src/test/test-nss-users.c diff --git a/src/basic/nss-util.h b/src/basic/nss-util.h index dfc0d3fb20..3c59dcc03c 100644 --- a/src/basic/nss-util.h +++ b/src/basic/nss-util.h @@ -213,3 +213,25 @@ typedef enum nss_status (*_nss_gethostbyaddr_r_t)( struct hostent *host, char *buffer, size_t buflen, int *errnop, int *h_errnop); + +typedef enum nss_status (*_nss_getpwnam_r_t)( + const char *name, + struct passwd *pwd, + char *buffer, size_t buflen, + int *errnop); +typedef enum nss_status (*_nss_getpwuid_r_t)( + uid_t uid, + struct passwd *pwd, + char *buffer, size_t buflen, + int *errnop); + +typedef enum nss_status (*_nss_getgrnam_r_t)( + const char *name, + struct group *gr, + char *buffer, size_t buflen, + int *errnop); +typedef enum nss_status (*_nss_getgrgid_r_t)( + gid_t gid, + struct group *gr, + char *buffer, size_t buflen, + int *errnop); diff --git a/src/test/meson.build b/src/test/meson.build index af55cbac82..0488baba82 100644 --- a/src/test/meson.build +++ b/src/test/meson.build @@ -540,7 +540,16 @@ tests += [ [['src/test/test-gcrypt-util.c'], [], [], [], 'HAVE_GCRYPT'], - [['src/test/test-nss-hosts.c'], + [['src/test/test-nss-hosts.c', + 'src/test/nss-test-util.c', + 'src/test/nss-test-util.h'], + [], + [libdl], + [], 'ENABLE_NSS', 'manual'], + + [['src/test/test-nss-users.c', + 'src/test/nss-test-util.c', + 'src/test/nss-test-util.h'], [], [libdl], [], 'ENABLE_NSS', 'manual'], diff --git a/src/test/nss-test-util.c b/src/test/nss-test-util.c new file mode 100644 index 0000000000..fc1d724a2f --- /dev/null +++ b/src/test/nss-test-util.c @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include +#include +#include + +#include "nss-test-util.h" +#include "string-util.h" + +const char* nss_status_to_string(enum nss_status status, char *buf, size_t buf_len) { + switch (status) { + case NSS_STATUS_TRYAGAIN: + return "NSS_STATUS_TRYAGAIN"; + case NSS_STATUS_UNAVAIL: + return "NSS_STATUS_UNAVAIL"; + case NSS_STATUS_NOTFOUND: + return "NSS_STATUS_NOTFOUND"; + case NSS_STATUS_SUCCESS: + return "NSS_STATUS_SUCCESS"; + case NSS_STATUS_RETURN: + return "NSS_STATUS_RETURN"; + default: + snprintf(buf, buf_len, "%i", status); + return buf; + } +}; + +void* nss_open_handle(const char *dir, const char *module, int flags) { + const char *path = NULL; + void *handle; + + if (dir) + path = strjoina(dir, "/libnss_", module, ".so.2"); + if (!path || access(path, F_OK) < 0) + path = strjoina("libnss_", module, ".so.2"); + + log_debug("Using %s", path); + handle = dlopen(path, flags); + if (!handle) + log_error("Failed to load module %s: %s", module, dlerror()); + return handle; +} diff --git a/src/test/nss-test-util.h b/src/test/nss-test-util.h new file mode 100644 index 0000000000..f081e6467e --- /dev/null +++ b/src/test/nss-test-util.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +#include +#include + +const char* nss_status_to_string(enum nss_status status, char *buf, size_t buf_len); +void* nss_open_handle(const char *dir, const char *module, int flags); diff --git a/src/test/test-nss-hosts.c b/src/test/test-nss-hosts.c index 2e9414d16d..1dd6aa083b 100644 --- a/src/test/test-nss-hosts.c +++ b/src/test/test-nss-hosts.c @@ -15,6 +15,7 @@ #include "local-addresses.h" #include "log.h" #include "main-func.h" +#include "nss-test-util.h" #include "nss-util.h" #include "path-util.h" #include "stdio-util.h" @@ -22,24 +23,6 @@ #include "strv.h" #include "tests.h" -static const char* nss_status_to_string(enum nss_status status, char *buf, size_t buf_len) { - switch (status) { - case NSS_STATUS_TRYAGAIN: - return "NSS_STATUS_TRYAGAIN"; - case NSS_STATUS_UNAVAIL: - return "NSS_STATUS_UNAVAIL"; - case NSS_STATUS_NOTFOUND: - return "NSS_STATUS_NOTFOUND"; - case NSS_STATUS_SUCCESS: - return "NSS_STATUS_SUCCESS"; - case NSS_STATUS_RETURN: - return "NSS_STATUS_RETURN"; - default: - snprintf(buf, buf_len, "%i", status); - return buf; - } -}; - static const char* af_to_string(int family, char *buf, size_t buf_len) { const char *name; @@ -54,22 +37,6 @@ static const char* af_to_string(int family, char *buf, size_t buf_len) { return buf; } -static void* open_handle(const char *dir, const char *module, int flags) { - const char *path = NULL; - void *handle; - - if (dir) - path = strjoina(dir, "/libnss_", module, ".so.2"); - if (!path || access(path, F_OK) < 0) - path = strjoina("libnss_", module, ".so.2"); - - log_debug("Using %s", path); - handle = dlopen(path, flags); - if (!handle) - log_error("Failed to load module %s: %s", module, dlerror()); - return handle; -} - static int print_gaih_addrtuples(const struct gaih_addrtuple *tuples) { int n = 0; @@ -414,7 +381,7 @@ static int test_one_module(const char *dir, log_info("======== %s ========", module); - handle = open_handle(dir, module, RTLD_LAZY|RTLD_NODELETE); + handle = nss_open_handle(dir, module, RTLD_LAZY|RTLD_NODELETE); if (!handle) return -EINVAL; @@ -437,10 +404,10 @@ static int parse_argv(int argc, char **argv, char ***the_names, struct local_address **the_addresses, int *n_addresses) { - int r, n = 0; _cleanup_strv_free_ char **modules = NULL, **names = NULL; _cleanup_free_ struct local_address *addrs = NULL; size_t n_allocated = 0; + int r, n = 0; if (argc > 1) modules = strv_new(argv[1]); @@ -495,12 +462,10 @@ static int parse_argv(int argc, char **argv, return n; } - *the_modules = modules; - *the_names = names; - modules = names = NULL; - *the_addresses = addrs; + *the_modules = TAKE_PTR(modules); + *the_names = TAKE_PTR(names); + *the_addresses = TAKE_PTR(addrs); *n_addresses = n; - addrs = NULL; return 0; } diff --git a/src/test/test-nss-users.c b/src/test/test-nss-users.c new file mode 100644 index 0000000000..c415c0ca3b --- /dev/null +++ b/src/test/test-nss-users.c @@ -0,0 +1,258 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "dlfcn-util.h" +#include "errno-list.h" +#include "format-util.h" +#include "log.h" +#include "main-func.h" +#include "nss-test-util.h" +#include "nss-util.h" +#include "path-util.h" +#include "parse-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "strv.h" +#include "tests.h" +#include "user-util.h" + +static size_t arg_bufsize = 1024; + +static void print_struct_passwd(const struct passwd *pwd) { + log_info(" \"%s\" / "UID_FMT":"GID_FMT, + pwd->pw_name, pwd->pw_uid, pwd->pw_gid); + log_info(" passwd=\"%s\"", pwd->pw_passwd); + log_info(" gecos=\"%s\"", pwd->pw_gecos); + log_info(" dir=\"%s\"", pwd->pw_dir); + log_info(" shell=\"%s\"", pwd->pw_shell); +} + +static void print_struct_group(const struct group *gr) { + _cleanup_free_ char *members = NULL; + + log_info(" \"%s\" / "GID_FMT, + gr->gr_name, gr->gr_gid); + log_info(" passwd=\"%s\"", gr->gr_passwd); + + assert_se(members = strv_join(gr->gr_mem, ", ")); + // FIXME: use shell_maybe_quote(SHELL_ESCAPE_EMPTY) when it becomes available + log_info(" members=%s", members); +} + +static void test_getpwnam_r(void *handle, const char *module, const char *name) { + const char *fname; + _nss_getpwnam_r_t f; + char buffer[arg_bufsize]; + int errno1 = 999; /* nss-dns doesn't set those */ + enum nss_status status; + char pretty_status[DECIMAL_STR_MAX(enum nss_status)]; + struct passwd pwd; + + fname = strjoina("_nss_", module, "_getpwnam_r"); + f = dlsym(handle, fname); + log_debug("dlsym(0x%p, %s) → 0x%p", handle, fname, f); + if (!f) { + log_info("%s not defined", fname); + return; + } + + status = f(name, &pwd, buffer, sizeof buffer, &errno1); + log_info("%s(\"%s\") → status=%s%-20serrno=%d/%s", + fname, name, + nss_status_to_string(status, pretty_status, sizeof pretty_status), "\n", + errno1, errno_to_name(errno1) ?: "---"); + if (status == NSS_STATUS_SUCCESS) + print_struct_passwd(&pwd); +} + +static void test_getgrnam_r(void *handle, const char *module, const char *name) { + const char *fname; + _nss_getgrnam_r_t f; + char buffer[arg_bufsize]; + int errno1 = 999; /* nss-dns doesn't set those */ + enum nss_status status; + char pretty_status[DECIMAL_STR_MAX(enum nss_status)]; + struct group gr; + + fname = strjoina("_nss_", module, "_getgrnam_r"); + f = dlsym(handle, fname); + log_debug("dlsym(0x%p, %s) → 0x%p", handle, fname, f); + if (!f) { + log_info("%s not defined", fname); + return; + } + + status = f(name, &gr, buffer, sizeof buffer, &errno1); + log_info("%s(\"%s\") → status=%s%-20serrno=%d/%s", + fname, name, + nss_status_to_string(status, pretty_status, sizeof pretty_status), "\n", + errno1, errno_to_name(errno1) ?: "---"); + if (status == NSS_STATUS_SUCCESS) + print_struct_group(&gr); +} + +static void test_getpwuid_r(void *handle, const char *module, uid_t uid) { + const char *fname; + _nss_getpwuid_r_t f; + char buffer[arg_bufsize]; + int errno1 = 999; /* nss-dns doesn't set those */ + enum nss_status status; + char pretty_status[DECIMAL_STR_MAX(enum nss_status)]; + struct passwd pwd; + + fname = strjoina("_nss_", module, "_getpwuid_r"); + f = dlsym(handle, fname); + log_debug("dlsym(0x%p, %s) → 0x%p", handle, fname, f); + if (!f) { + log_info("%s not defined", fname); + return; + } + + status = f(uid, &pwd, buffer, sizeof buffer, &errno1); + log_info("%s("UID_FMT") → status=%s%-20serrno=%d/%s", + fname, uid, + nss_status_to_string(status, pretty_status, sizeof pretty_status), "\n", + errno1, errno_to_name(errno1) ?: "---"); + if (status == NSS_STATUS_SUCCESS) + print_struct_passwd(&pwd); +} + +static void test_getgrgid_r(void *handle, const char *module, gid_t gid) { + const char *fname; + _nss_getgrgid_r_t f; + char buffer[arg_bufsize]; + int errno1 = 999; /* nss-dns doesn't set those */ + enum nss_status status; + char pretty_status[DECIMAL_STR_MAX(enum nss_status)]; + struct group gr; + + fname = strjoina("_nss_", module, "_getgrgid_r"); + f = dlsym(handle, fname); + log_debug("dlsym(0x%p, %s) → 0x%p", handle, fname, f); + if (!f) { + log_info("%s not defined", fname); + return; + } + + status = f(gid, &gr, buffer, sizeof buffer, &errno1); + log_info("%s("GID_FMT") → status=%s%-20serrno=%d/%s", + fname, gid, + nss_status_to_string(status, pretty_status, sizeof pretty_status), "\n", + errno1, errno_to_name(errno1) ?: "---"); + if (status == NSS_STATUS_SUCCESS) + print_struct_group(&gr); +} + +static void test_byname(void *handle, const char *module, const char *name) { + test_getpwnam_r(handle, module, name); + test_getgrnam_r(handle, module, name); + puts(""); +} + +static void test_byuid(void *handle, const char *module, uid_t uid) { + test_getpwuid_r(handle, module, uid); + test_getgrgid_r(handle, module, uid); + puts(""); +} + +static int test_one_module(const char *dir, + const char *module, + char **names) { + + log_info("======== %s ========", module); + + _cleanup_(dlclosep) void *handle = nss_open_handle(dir, module, RTLD_LAZY|RTLD_NODELETE); + if (!handle) + return -EINVAL; + + char **name; + STRV_FOREACH(name, names) + test_byname(handle, module, *name); + + STRV_FOREACH(name, names) { + uid_t uid; + + assert_cc(sizeof(uid_t) == sizeof(uint32_t)); + /* We use safe_atou32 because we don't want to refuse invalid uids. */ + if (safe_atou32(*name, &uid) < 0) + continue; + + test_byuid(handle, module, uid); + } + + log_info(" "); + return 0; +} + +static int parse_argv(int argc, char **argv, + char ***the_modules, + char ***the_names) { + + _cleanup_strv_free_ char **modules = NULL, **names = NULL; + const char *p; + int r; + + p = getenv("SYSTEMD_TEST_NSS_BUFSIZE"); + if (p) { + r = safe_atozu(p, &arg_bufsize); + if (r < 0) + return log_error_errno(r, "Failed to parse $SYSTEMD_TEST_NSS_BUFSIZE"); + } + + if (argc > 1) + modules = strv_new(argv[1]); + else + modules = strv_new( +#if ENABLE_NSS_SYSTEMD + "systemd", +#endif +#if ENABLE_NSS_MYMACHINES + "mymachines", +#endif + "files"); + assert_se(modules); + + if (argc > 2) + names = strv_copy(strv_skip(argv, 2)); + else + names = strv_new("root", + NOBODY_USER_NAME, + "foo_no_such_user", + "0", + "65534"); + assert_se(names); + + *the_modules = TAKE_PTR(modules); + *the_names = TAKE_PTR(names); + return 0; +} + +static int run(int argc, char **argv) { + _cleanup_free_ char *dir = NULL; + _cleanup_strv_free_ char **modules = NULL, **names = NULL; + char **module; + int r; + + test_setup_logging(LOG_INFO); + + r = parse_argv(argc, argv, &modules, &names); + if (r < 0) + return log_error_errno(r, "Failed to parse arguments: %m"); + + assert_se(path_extract_directory(argv[0], &dir) >= 0); + + STRV_FOREACH(module, modules) { + r = test_one_module(dir, *module, names); + if (r < 0) + return r; + } + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); From e2aa384bcdd1c137872294397b07e98caf966d5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 23 Mar 2021 13:56:37 +0100 Subject: [PATCH 3/4] test-nss-hosts: use _cleanup_, fix return value, assert on allocations --- src/test/test-nss-hosts.c | 39 ++++++++++++--------------------------- 1 file changed, 12 insertions(+), 27 deletions(-) diff --git a/src/test/test-nss-hosts.c b/src/test/test-nss-hosts.c index 1dd6aa083b..2eb4f8079e 100644 --- a/src/test/test-nss-hosts.c +++ b/src/test/test-nss-hosts.c @@ -1,12 +1,12 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include #include #include #include #include "af-list.h" #include "alloc-util.h" +#include "dlfcn-util.h" #include "errno-list.h" #include "format-util.h" #include "hexdecoct.h" @@ -359,8 +359,7 @@ static int make_addresses(struct local_address **addresses) { log_info_errno(n, "Failed to query local addresses: %m"); n_alloc = n; /* we _can_ do that */ - if (!GREEDY_REALLOC(addrs, n_alloc, n + 3)) - return log_oom(); + assert_se(GREEDY_REALLOC(addrs, n_alloc, n + 3)); addrs[n++] = (struct local_address) { .family = AF_INET, .address.in = { htobe32(0x7F000001) } }; @@ -376,15 +375,14 @@ static int test_one_module(const char *dir, char **names, struct local_address *addresses, int n_addresses) { - void *handle; - char **name; log_info("======== %s ========", module); - handle = nss_open_handle(dir, module, RTLD_LAZY|RTLD_NODELETE); + _cleanup_(dlclosep) void *handle = nss_open_handle(dir, module, RTLD_LAZY|RTLD_NODELETE); if (!handle) return -EINVAL; + char **name; STRV_FOREACH(name, names) test_byname(handle, module, *name); @@ -395,7 +393,6 @@ static int test_one_module(const char *dir, addresses[i].family); log_info(" "); - dlclose(handle); return 0; } @@ -423,8 +420,7 @@ static int parse_argv(int argc, char **argv, "mymachines", #endif "dns"); - if (!modules) - return -ENOMEM; + assert_se(modules); if (argc > 2) { char **name; @@ -439,8 +435,7 @@ static int parse_argv(int argc, char **argv, if (r < 0) return r; } else { - if (!GREEDY_REALLOC0(addrs, n_allocated, n + 1)) - return -ENOMEM; + assert_se(GREEDY_REALLOC0(addrs, n_allocated, n + 1)); addrs[n++] = (struct local_address) { .family = family, .address = address }; @@ -448,18 +443,12 @@ static int parse_argv(int argc, char **argv, } } else { _cleanup_free_ char *hostname; + assert_se(hostname = gethostname_malloc()); - hostname = gethostname_malloc(); - if (!hostname) - return -ENOMEM; - - names = strv_new("localhost", "_gateway", "foo_no_such_host", hostname); - if (!names) - return -ENOMEM; + assert_se(names = strv_new("localhost", "_gateway", "foo_no_such_host", hostname)); n = make_addresses(&addrs); - if (n < 0) - return n; + assert_se(n >= 0); } *the_modules = TAKE_PTR(modules); @@ -480,14 +469,10 @@ static int run(int argc, char **argv) { test_setup_logging(LOG_INFO); r = parse_argv(argc, argv, &modules, &names, &addresses, &n_addresses); - if (r < 0) { - log_error_errno(r, "Failed to parse arguments: %m"); - return EXIT_FAILURE; - } + if (r < 0) + return log_error_errno(r, "Failed to parse arguments: %m"); - dir = dirname_malloc(argv[0]); - if (!dir) - return log_oom(); + assert_se(path_extract_directory(argv[0], &dir) >= 0); STRV_FOREACH(module, modules) { r = test_one_module(dir, *module, names, addresses, n_addresses); From f0cb09bb0f2796c9532f8bbf9161d9e274d36343 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Fri, 12 Mar 2021 14:37:18 +0100 Subject: [PATCH 4/4] test-nss-hosts: make buffer size configurable too and document it --- docs/ENVIRONMENT.md | 13 ++++++++----- src/test/test-nss-hosts.c | 23 +++++++++++++++++------ 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/docs/ENVIRONMENT.md b/docs/ENVIRONMENT.md index ad2d3ad84b..2cec3bdc16 100644 --- a/docs/ENVIRONMENT.md +++ b/docs/ENVIRONMENT.md @@ -198,11 +198,6 @@ All tools: prefixed with `:` in which case the kernel command line option takes precedence, if it is specified as well. -installed systemd tests: - -* `$SYSTEMD_TEST_DATA` — override the location of test data. This is useful if - a test executable is moved to an arbitrary location. - `nss-systemd`: * `$SYSTEMD_NSS_BYPASS_SYNTHETIC=1` — if set, `nss-systemd` won't synthesize @@ -302,6 +297,14 @@ installed systemd tests: * `$SYSTEMD_SYSVRCND_PATH` — Controls where `systemd-sysv-generator` looks for SysV init script runlevel link farms. +systemd tests: + +* `$SYSTEMD_TEST_DATA` — override the location of test data. This is useful if + a test executable is moved to an arbitrary location. + +* `$SYSTEMD_TEST_NSS_BUFSIZE` — size of scratch buffers for "reentrant" + functions exported by the nss modules. + fuzzers: * `$SYSTEMD_FUZZ_OUTPUT` — A boolean that specifies whether to write output to diff --git a/src/test/test-nss-hosts.c b/src/test/test-nss-hosts.c index 2eb4f8079e..e9bc6ecce6 100644 --- a/src/test/test-nss-hosts.c +++ b/src/test/test-nss-hosts.c @@ -17,12 +17,15 @@ #include "main-func.h" #include "nss-test-util.h" #include "nss-util.h" +#include "parse-util.h" #include "path-util.h" #include "stdio-util.h" #include "string-util.h" #include "strv.h" #include "tests.h" +static size_t arg_bufsize = 1024; + static const char* af_to_string(int family, char *buf, size_t buf_len) { const char *name; @@ -99,7 +102,7 @@ static void print_struct_hostent(struct hostent *host, const char *canon) { static void test_gethostbyname4_r(void *handle, const char *module, const char *name) { const char *fname; _nss_gethostbyname4_r_t f; - char buffer[2000]; + char buffer[arg_bufsize]; struct gaih_addrtuple *pat = NULL; int errno1 = 999, errno2 = 999; /* nss-dns doesn't set those */ int32_t ttl = INT32_MAX; /* nss-dns wants to return the lowest ttl, @@ -151,7 +154,7 @@ static void test_gethostbyname4_r(void *handle, const char *module, const char * static void test_gethostbyname3_r(void *handle, const char *module, const char *name, int af) { const char *fname; _nss_gethostbyname3_r_t f; - char buffer[2000]; + char buffer[arg_bufsize]; int errno1 = 999, errno2 = 999; /* nss-dns doesn't set those */ int32_t ttl = INT32_MAX; /* nss-dns wants to return the lowest ttl, and will access this variable through *ttlp, @@ -186,7 +189,7 @@ static void test_gethostbyname3_r(void *handle, const char *module, const char * static void test_gethostbyname2_r(void *handle, const char *module, const char *name, int af) { const char *fname; _nss_gethostbyname2_r_t f; - char buffer[2000]; + char buffer[arg_bufsize]; int errno1 = 999, errno2 = 999; /* nss-dns doesn't set those */ enum nss_status status; char pretty_status[DECIMAL_STR_MAX(enum nss_status)]; @@ -214,7 +217,7 @@ static void test_gethostbyname2_r(void *handle, const char *module, const char * static void test_gethostbyname_r(void *handle, const char *module, const char *name) { const char *fname; _nss_gethostbyname_r_t f; - char buffer[2000]; + char buffer[arg_bufsize]; int errno1 = 999, errno2 = 999; /* nss-dns doesn't set those */ enum nss_status status; char pretty_status[DECIMAL_STR_MAX(enum nss_status)]; @@ -245,7 +248,7 @@ static void test_gethostbyaddr2_r(void *handle, const char *fname; _nss_gethostbyaddr2_r_t f; - char buffer[2000]; + char buffer[arg_bufsize]; int errno1 = 999, errno2 = 999; /* nss-dns doesn't set those */ enum nss_status status; char pretty_status[DECIMAL_STR_MAX(enum nss_status)]; @@ -283,7 +286,7 @@ static void test_gethostbyaddr_r(void *handle, const char *fname; _nss_gethostbyaddr_r_t f; - char buffer[2000]; + char buffer[arg_bufsize]; int errno1 = 999, errno2 = 999; /* nss-dns doesn't set those */ enum nss_status status; char pretty_status[DECIMAL_STR_MAX(enum nss_status)]; @@ -404,8 +407,16 @@ static int parse_argv(int argc, char **argv, _cleanup_strv_free_ char **modules = NULL, **names = NULL; _cleanup_free_ struct local_address *addrs = NULL; size_t n_allocated = 0; + const char *p; int r, n = 0; + p = getenv("SYSTEMD_TEST_NSS_BUFSIZE"); + if (p) { + r = safe_atozu(p, &arg_bufsize); + if (r < 0) + return log_error_errno(r, "Failed to parse $SYSTEMD_TEST_NSS_BUFSIZE"); + } + if (argc > 1) modules = strv_new(argv[1]); else