From 3c14dc61f7782d8eca0ff7b55e9f60fef176fe82 Mon Sep 17 00:00:00 2001 From: Topi Miettinen Date: Thu, 23 Apr 2020 13:12:23 +0300 Subject: [PATCH] tests: various small fixes for strict systems Don't assume that 4MB can be allocated from stack since there could be smaller DefaultLimitSTACK= in force, so let's use malloc(). NUL terminate the huge strings by hand, also ensure termination in test_lz4_decompress_partial() and optimize the memset() for the string. Some items in /proc and /etc may not be accessible to poor unprivileged users due to e.g. SELinux, BOFH or both, so check for EACCES and EPERM. /var/tmp may be a symlink to /tmp and then path_compare() will always fail, so let's stick to /tmp like elsewhere. /tmp may be mounted with noexec option and then trying to execute scripts from there would fail. Detect and warn if seccomp is already in use, which could make seccomp test fail if the syscalls are already blocked. Unset $TMPDIR so it will not break specifier tests where %T is assumed to be /tmp and %V /var/tmp. --- src/journal/test-compress.c | 19 +++++++++++-------- src/journal/test-journal-send.c | 12 ++++++++---- src/test/test-capability.c | 5 ++++- src/test/test-cgroup-setup.c | 6 ++++++ src/test/test-cgroup-util.c | 3 ++- src/test/test-clock.c | 6 +++--- src/test/test-condition.c | 9 ++++++++- src/test/test-copy.c | 6 +++--- src/test/test-exec-util.c | 15 +++++++++++++++ src/test/test-execute.c | 1 + src/test/test-fileio.c | 5 ++++- src/test/test-proc-cmdline.c | 4 ++++ src/test/test-procfs-util.c | 8 +++++++- src/test/test-sd-hwdb.c | 3 ++- src/test/test-seccomp.c | 6 ++++++ src/test/test-umount.c | 7 ++++++- 16 files changed, 90 insertions(+), 25 deletions(-) diff --git a/src/journal/test-compress.c b/src/journal/test-compress.c index fac2b43c47..6d738f4d66 100644 --- a/src/journal/test-compress.c +++ b/src/journal/test-compress.c @@ -233,8 +233,9 @@ static void test_lz4_decompress_partial(void) { #define HUGE_SIZE (4096*1024) assert_se(huge = malloc(HUGE_SIZE)); - memset(huge, 'x', HUGE_SIZE); - memcpy(huge, "HUGE=", 5); + memcpy(huge, "HUGE=", STRLEN("HUGE=")); + memset(&huge[STRLEN("HUGE=")], 'x', HUGE_SIZE - STRLEN("HUGE=") - 1); + huge[HUGE_SIZE - 1] = '\0'; r = LZ4_compress_default(huge, buf, HUGE_SIZE, buf_size); assert_se(r >= 0); @@ -274,10 +275,12 @@ int main(int argc, char *argv[]) { char data[512] = "random\0"; - char huge[4096*1024]; - memset(huge, 'x', sizeof(huge)); - memcpy(huge, "HUGE=", 5); - char_array_0(huge); + _cleanup_free_ char *huge = NULL; + + assert_se(huge = malloc(HUGE_SIZE)); + memcpy(huge, "HUGE=", STRLEN("HUGE=")); + memset(&huge[STRLEN("HUGE=")], 'x', HUGE_SIZE - STRLEN("HUGE=") - 1); + huge[HUGE_SIZE - 1] = '\0'; test_setup_logging(LOG_DEBUG); @@ -297,7 +300,7 @@ int main(int argc, char *argv[]) { data, sizeof(data), true); test_decompress_startswith(OBJECT_COMPRESSED_XZ, compress_blob_xz, decompress_startswith_xz, - huge, sizeof(huge), true); + huge, HUGE_SIZE, true); test_compress_stream(OBJECT_COMPRESSED_XZ, "xzcat", compress_stream_xz, decompress_stream_xz, srcfile); @@ -322,7 +325,7 @@ int main(int argc, char *argv[]) { data, sizeof(data), true); test_decompress_startswith(OBJECT_COMPRESSED_LZ4, compress_blob_lz4, decompress_startswith_lz4, - huge, sizeof(huge), true); + huge, HUGE_SIZE, true); test_compress_stream(OBJECT_COMPRESSED_LZ4, "lz4cat", compress_stream_lz4, decompress_stream_lz4, srcfile); diff --git a/src/journal/test-journal-send.c b/src/journal/test-journal-send.c index 484308e56e..d187d61a90 100644 --- a/src/journal/test-journal-send.c +++ b/src/journal/test-journal-send.c @@ -7,9 +7,13 @@ #include "sd-journal.h" #include "macro.h" +#include "memory-util.h" int main(int argc, char *argv[]) { - char huge[4096*1024]; + _cleanup_free_ char *huge = NULL; + +#define HUGE_SIZE (4096*1024) + assert_se(huge = malloc(HUGE_SIZE)); /* utf-8 and non-utf-8, message-less and message-ful iovecs */ struct iovec graph1[] = { @@ -36,9 +40,9 @@ int main(int argc, char *argv[]) { assert_se(sd_journal_perror("") == 0); - memset(huge, 'x', sizeof(huge)); - memcpy(huge, "HUGE=", 5); - char_array_0(huge); + memcpy(huge, "HUGE=", STRLEN("HUGE=")); + memset(&huge[STRLEN("HUGE=")], 'x', HUGE_SIZE - STRLEN("HUGE=") - 1); + huge[HUGE_SIZE - 1] = '\0'; assert_se(sd_journal_send("MESSAGE=Huge field attached", huge, diff --git a/src/test/test-capability.c b/src/test/test-capability.c index 74b27379ea..f8766256e2 100644 --- a/src/test/test-capability.c +++ b/src/test/test-capability.c @@ -9,6 +9,7 @@ #include "alloc-util.h" #include "capability-util.h" +#include "errno-util.h" #include "fd-util.h" #include "fileio.h" #include "macro.h" @@ -35,6 +36,8 @@ static void test_last_cap_file(void) { int r; r = read_one_line_file("/proc/sys/kernel/cap_last_cap", &content); + if (r == -ENOENT || ERRNO_IS_PRIVILEGE(r)) /* kernel pre 3.2 or no access */ + return; assert_se(r >= 0); r = safe_atolu(content, &val); @@ -230,7 +233,7 @@ static void test_ensure_cap_64bit(void) { int r; r = read_one_line_file("/proc/sys/kernel/cap_last_cap", &content); - if (r == -ENOENT) /* kernel pre 3.2 */ + if (r == -ENOENT || ERRNO_IS_PRIVILEGE(r)) /* kernel pre 3.2 or no access */ return; assert_se(r >= 0); diff --git a/src/test/test-cgroup-setup.c b/src/test/test-cgroup-setup.c index 330631a910..25fa0d75df 100644 --- a/src/test/test-cgroup-setup.c +++ b/src/test/test-cgroup-setup.c @@ -1,8 +1,11 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ +#include + #include "alloc-util.h" #include "build.h" #include "cgroup-setup.h" +#include "errno-util.h" #include "log.h" #include "proc-cmdline.h" #include "string-util.h" @@ -59,6 +62,9 @@ static void test_is_wanted(void) { int main(void) { test_setup_logging(LOG_DEBUG); + if (access("/proc/cmdline", R_OK) < 0 && ERRNO_IS_PRIVILEGE(errno)) + return log_tests_skipped("can't read /proc/cmdline"); + test_is_wanted_print(true); test_is_wanted_print(false); /* run twice to test caching */ test_is_wanted(); diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c index 83b5156c11..daaffb5a06 100644 --- a/src/test/test-cgroup-util.c +++ b/src/test/test-cgroup-util.c @@ -4,6 +4,7 @@ #include "build.h" #include "cgroup-util.h" #include "dirent-util.h" +#include "errno-util.h" #include "fd-util.h" #include "format-util.h" #include "parse-util.h" @@ -369,7 +370,7 @@ static void test_cg_get_keyed_attribute(void) { int i, r; r = cg_get_keyed_attribute("cpu", "/init.scope", "no_such_file", STRV_MAKE("no_such_attr"), &val); - if (r == -ENOMEDIUM) { + if (r == -ENOMEDIUM || ERRNO_IS_PRIVILEGE(r)) { log_info_errno(r, "Skipping most of %s, /sys/fs/cgroup not accessible: %m", __func__); return; } diff --git a/src/test/test-clock.c b/src/test/test-clock.c index 018e679b45..e5a3de8a59 100644 --- a/src/test/test-clock.c +++ b/src/test/test-clock.c @@ -60,14 +60,14 @@ static void test_clock_is_localtime_system(void) { int r; r = clock_is_localtime(NULL); - if (access("/etc/adjtime", F_OK) == 0) { - log_info("/etc/adjtime exists, clock_is_localtime() == %i", r); + if (access("/etc/adjtime", R_OK) == 0) { + log_info("/etc/adjtime is readable, clock_is_localtime() == %i", r); /* if /etc/adjtime exists we expect some answer, no error or * crash */ assert_se(IN_SET(r, 0, 1)); } else /* default is UTC if there is no /etc/adjtime */ - assert_se(r == 0); + assert_se(r == 0 || ERRNO_IS_PRIVILEGE(r)); } int main(int argc, char *argv[]) { diff --git a/src/test/test-condition.c b/src/test/test-condition.c index 28b5b780c3..8c48518774 100644 --- a/src/test/test-condition.c +++ b/src/test/test-condition.c @@ -15,6 +15,7 @@ #include "condition.h" #include "cpu-set-util.h" #include "efi-loader.h" +#include "errno-util.h" #include "hostname-util.h" #include "id128-util.h" #include "ima-util.h" @@ -274,10 +275,14 @@ static void test_condition_test_architecture(void) { static void test_condition_test_kernel_command_line(void) { Condition *condition; + int r; condition = condition_new(CONDITION_KERNEL_COMMAND_LINE, "thisreallyshouldntbeonthekernelcommandline", false, false); assert_se(condition); - assert_se(condition_test(condition) == 0); + r = condition_test(condition); + if (ERRNO_IS_PRIVILEGE(r)) + return; + assert_se(r == 0); condition_free(condition); condition = condition_new(CONDITION_KERNEL_COMMAND_LINE, "andthis=neither", false, false); @@ -506,6 +511,8 @@ static void test_condition_test_virtualization(void) { condition = condition_new(CONDITION_VIRTUALIZATION, "garbage oifdsjfoidsjoj", false, false); assert_se(condition); r = condition_test(condition); + if (ERRNO_IS_PRIVILEGE(r)) + return; log_info("ConditionVirtualization=garbage → %i", r); assert_se(r == 0); condition_free(condition); diff --git a/src/test/test-copy.c b/src/test/test-copy.c index 68905c662d..0e8d687951 100644 --- a/src/test/test-copy.c +++ b/src/test/test-copy.c @@ -78,8 +78,8 @@ static void test_copy_file_fd(void) { } static void test_copy_tree(void) { - char original_dir[] = "/var/tmp/test-copy_tree/"; - char copy_dir[] = "/var/tmp/test-copy_tree-copy/"; + char original_dir[] = "/tmp/test-copy_tree/"; + char copy_dir[] = "/tmp/test-copy_tree-copy/"; char **files = STRV_MAKE("file", "dir1/file", "dir1/dir2/file", "dir1/dir2/dir3/dir4/dir5/file"); char **links = STRV_MAKE("link", "file", "link2", "dir1/file"); @@ -270,7 +270,7 @@ static void test_copy_atomic(void) { q = strjoina(p, "/fstab"); r = copy_file_atomic("/etc/fstab", q, 0644, 0, 0, COPY_REFLINK); - if (r == -ENOENT) + if (r == -ENOENT || ERRNO_IS_PRIVILEGE(r)) return; assert_se(copy_file_atomic("/etc/fstab", q, 0644, 0, 0, COPY_REFLINK) == -EEXIST); diff --git a/src/test/test-exec-util.c b/src/test/test-exec-util.c index 3168411d8b..f5d640a690 100644 --- a/src/test/test-exec-util.c +++ b/src/test/test-exec-util.c @@ -115,6 +115,9 @@ static void test_execute_directory(bool gather_stdout) { assert_se(chmod(masked2e, 0755) == 0); assert_se(chmod(mask2e, 0755) == 0); + if (access(name, X_OK) < 0 && ERRNO_IS_PRIVILEGE(errno)) + return; + if (gather_stdout) execute_directories(dirs, DEFAULT_TIMEOUT_USEC, ignore_stdout, ignore_stdout_args, NULL, NULL, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS); else @@ -183,6 +186,9 @@ static void test_execution_order(void) { assert_se(chmod(override, 0755) == 0); assert_se(chmod(masked, 0755) == 0); + if (access(name, X_OK) < 0 && ERRNO_IS_PRIVILEGE(errno)) + return; + execute_directories(dirs, DEFAULT_TIMEOUT_USEC, ignore_stdout, ignore_stdout_args, NULL, NULL, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS); assert_se(read_full_file(output, &contents, NULL) >= 0); @@ -265,6 +271,9 @@ static void test_stdout_gathering(void) { assert_se(chmod(name2, 0755) == 0); assert_se(chmod(name3, 0755) == 0); + if (access(name, X_OK) < 0 && ERRNO_IS_PRIVILEGE(errno)) + return; + r = execute_directories(dirs, DEFAULT_TIMEOUT_USEC, gather_stdout, args, NULL, NULL, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS); assert_se(r >= 0); @@ -331,6 +340,9 @@ static void test_environment_gathering(void) { r = setenv("PATH", "no-sh-built-in-path", 1); assert_se(r >= 0); + if (access(name, X_OK) < 0 && ERRNO_IS_PRIVILEGE(errno)) + return; + r = execute_directories(dirs, DEFAULT_TIMEOUT_USEC, gather_environment, args, NULL, NULL, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS); assert_se(r >= 0); @@ -395,6 +407,9 @@ static void test_error_catching(void) { assert_se(chmod(name2, 0755) == 0); assert_se(chmod(name3, 0755) == 0); + if (access(name, X_OK) < 0 && ERRNO_IS_PRIVILEGE(errno)) + return; + r = execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, NULL, NULL, EXEC_DIR_NONE); /* we should exit with the error code of the first script that failed */ diff --git a/src/test/test-execute.c b/src/test/test-execute.c index 5a96b46a77..43f66efa6c 100644 --- a/src/test/test-execute.c +++ b/src/test/test-execute.c @@ -866,6 +866,7 @@ int main(int argc, char *argv[]) { (void) unsetenv("LOGNAME"); (void) unsetenv("SHELL"); (void) unsetenv("HOME"); + (void) unsetenv("TMPDIR"); can_unshare = have_namespaces(); diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c index 32a00349ac..8c04346721 100644 --- a/src/test/test-fileio.c +++ b/src/test/test-fileio.c @@ -444,7 +444,10 @@ static void test_write_string_file_verify(void) { _cleanup_free_ char *buf = NULL, *buf2 = NULL; int r; - assert_se(read_one_line_file("/proc/version", &buf) >= 0); + r = read_one_line_file("/proc/version", &buf); + if (ERRNO_IS_PRIVILEGE(r)) + return; + assert_se(r >= 0); assert_se(buf2 = strjoin(buf, "\n")); r = write_string_file("/proc/version", buf, 0); diff --git a/src/test/test-proc-cmdline.c b/src/test/test-proc-cmdline.c index 370b041189..4a9b111a20 100644 --- a/src/test/test-proc-cmdline.c +++ b/src/test/test-proc-cmdline.c @@ -2,6 +2,7 @@ #include "alloc-util.h" #include "env-util.h" +#include "errno-util.h" #include "log.h" #include "macro.h" #include "proc-cmdline.h" @@ -250,6 +251,9 @@ static void test_proc_cmdline_key_startswith(void) { int main(void) { test_setup_logging(LOG_INFO); + if (access("/proc/cmdline", R_OK) < 0 && ERRNO_IS_PRIVILEGE(errno)) + return log_tests_skipped("can't read /proc/cmdline"); + test_proc_cmdline_parse(); test_proc_cmdline_override(); test_proc_cmdline_given(false); diff --git a/src/test/test-procfs-util.c b/src/test/test-procfs-util.c index 662688e0f0..61434578b0 100644 --- a/src/test/test-procfs-util.c +++ b/src/test/test-procfs-util.c @@ -2,9 +2,11 @@ #include +#include "errno-util.h" #include "format-util.h" #include "log.h" #include "procfs-util.h" +#include "tests.h" int main(int argc, char *argv[]) { char buf[CONST_MAX(FORMAT_TIMESPAN_MAX, FORMAT_BYTES_MAX)]; @@ -24,7 +26,11 @@ int main(int argc, char *argv[]) { assert_se(procfs_tasks_get_current(&v) >= 0); log_info("Current number of tasks: %" PRIu64, v); - assert_se(procfs_tasks_get_limit(&v) >= 0); + r = procfs_tasks_get_limit(&v); + if (r == -ENOENT || ERRNO_IS_PRIVILEGE(r)) + return log_tests_skipped("can't read /proc/sys/kernel/pid_max"); + + assert_se(r >= 0); log_info("Limit of tasks: %" PRIu64, v); assert_se(v > 0); assert_se(procfs_tasks_set_limit(v) >= 0); diff --git a/src/test/test-sd-hwdb.c b/src/test/test-sd-hwdb.c index 17ca6a0e27..eb34d8eab2 100644 --- a/src/test/test-sd-hwdb.c +++ b/src/test/test-sd-hwdb.c @@ -1,6 +1,7 @@ #include "sd-hwdb.h" #include "alloc-util.h" +#include "errno-util.h" #include "errno.h" #include "tests.h" @@ -12,7 +13,7 @@ static int test_failed_enumerate(void) { log_info("/* %s */", __func__); r = sd_hwdb_new(&hwdb); - if (r == -ENOENT) + if (r == -ENOENT || ERRNO_IS_PRIVILEGE(r)) return r; assert_se(r == 0); diff --git a/src/test/test-seccomp.c b/src/test/test-seccomp.c index 67900d85e9..b09d031f5d 100644 --- a/src/test/test-seccomp.c +++ b/src/test/test-seccomp.c @@ -13,6 +13,7 @@ #include "alloc-util.h" #include "fd-util.h" +#include "fileio.h" #include "macro.h" #include "memory-util.h" #include "missing_sched.h" @@ -283,6 +284,7 @@ static void test_restrict_namespace(void) { static void test_protect_sysctl(void) { pid_t pid; + _cleanup_free_ char *seccomp = NULL; log_info("/* %s */", __func__); @@ -301,6 +303,10 @@ static void test_protect_sysctl(void) { return; } + assert_se(get_proc_field("/proc/self/status", "Seccomp", WHITESPACE, &seccomp) == 0); + if (!streq(seccomp, "0")) + log_warning("Warning: seccomp filter detected, results may be unreliable for %s", __func__); + pid = fork(); assert_se(pid >= 0); diff --git a/src/test/test-umount.c b/src/test/test-umount.c index b27b75b352..02852bc089 100644 --- a/src/test/test-umount.c +++ b/src/test/test-umount.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #include "alloc-util.h" +#include "errno-util.h" #include "log.h" #include "path-util.h" #include "string-util.h" @@ -36,6 +37,7 @@ static void test_swap_list(const char *fname) { _cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, mp_list_head); _cleanup_free_ char *testdata_fname = NULL; MountPoint *m; + int r; log_info("/* %s(\"%s\") */", __func__, fname ?: "/proc/swaps"); @@ -45,7 +47,10 @@ static void test_swap_list(const char *fname) { } LIST_HEAD_INIT(mp_list_head); - assert_se(swap_list_get(fname, &mp_list_head) >= 0); + r = swap_list_get(fname, &mp_list_head); + if (ERRNO_IS_PRIVILEGE(r)) + return; + assert_se(r >= 0); LIST_FOREACH(mount_point, m, mp_list_head) log_debug("path=%s o=%s f=0x%lx try-ro=%s dev=%u:%u",