test: several random cleanups and fixlets (#38877)

This commit is contained in:
Yu Watanabe
2025-09-18 09:13:17 +09:00
committed by GitHub
12 changed files with 669 additions and 887 deletions
+397 -383
View File
File diff suppressed because it is too large Load Diff
+6 -2
View File
@@ -5,6 +5,7 @@
#include "sd-event.h"
#include "capability-util.h"
#include "device-internal.h"
#include "device-private.h"
#include "device-util.h"
@@ -25,14 +26,17 @@
#include "tests.h"
#include "tmpfile-util.h"
#include "udev-util.h"
#include "virt.h"
TEST(mdio_bus) {
int r;
/* For issue #37711 */
if (getuid() != 0)
return (void) log_tests_skipped("not running as root");
if (getuid() != 0 || have_effective_cap(CAP_SYS_ADMIN) <= 0)
return (void) log_tests_skipped("Not privileged");
if (running_in_chroot() > 0)
return (void) log_tests_skipped("Running in chroot");
ASSERT_OK(r = safe_fork("(mdio_bus)", FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_WAIT|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE, NULL));
if (r == 0) {
+1 -1
View File
@@ -68,8 +68,8 @@ simple_tests += files(
'test-bus-unit-util.c',
'test-bus-util.c',
'test-calendarspec.c',
'test-cgroup-setup.c',
'test-cgroup-util.c',
'test-cgroup.c',
'test-chase.c',
'test-chid.c',
'test-clock.c',
@@ -3,43 +3,11 @@
#include "cgroup-setup.h"
#include "cgroup-util.h"
#include "errno-util.h"
#include "fd-util.h"
#include "path-util.h"
#include "process-util.h"
#include "stat-util.h"
#include "string-util.h"
#include "tests.h"
TEST(cg_split_spec) {
char *c, *p;
ASSERT_OK_ZERO(cg_split_spec("foobar:/", &c, &p));
ASSERT_STREQ(c, "foobar");
ASSERT_STREQ(p, "/");
c = mfree(c);
p = mfree(p);
ASSERT_OK_ZERO(cg_split_spec("foobar:", &c, &p));
c = mfree(c);
p = mfree(p);
ASSERT_FAIL(cg_split_spec("foobar:asdfd", &c, &p));
ASSERT_FAIL(cg_split_spec(":///", &c, &p));
ASSERT_FAIL(cg_split_spec(":", &c, &p));
ASSERT_FAIL(cg_split_spec("", &c, &p));
ASSERT_FAIL(cg_split_spec("fo/obar:/", &c, &p));
ASSERT_OK(cg_split_spec("/", &c, &p));
ASSERT_NULL(c);
ASSERT_STREQ(p, "/");
p = mfree(p);
ASSERT_OK(cg_split_spec("foo", &c, &p));
ASSERT_STREQ(c, "foo");
ASSERT_NULL(p);
c = mfree(c);
}
TEST(cg_create) {
int r;
@@ -118,45 +86,4 @@ TEST(cg_create) {
ASSERT_OK(cg_trim(test_b, true));
}
TEST(id) {
_cleanup_free_ char *p = NULL, *p2 = NULL;
_cleanup_close_ int fd = -EBADF, fd2 = -EBADF;
uint64_t id, id2;
int r;
r = cg_all_unified();
if (IN_SET(r, -ENOMEDIUM, -ENOENT))
return (void) log_tests_skipped("cgroupfs is not mounted");
if (r == 0)
return (void) log_tests_skipped("skipping cgroupid test, not running in unified mode");
ASSERT_OK_POSITIVE(r);
fd = cg_path_open(SYSTEMD_CGROUP_CONTROLLER, "/");
ASSERT_OK(fd);
ASSERT_OK(fd_get_path(fd, &p));
ASSERT_TRUE(path_equal(p, "/sys/fs/cgroup"));
ASSERT_OK(cg_fd_get_cgroupid(fd, &id));
fd2 = cg_cgroupid_open(fd, id);
if (ERRNO_IS_NEG_PRIVILEGE(fd2))
log_notice("Skipping open-by-cgroup-id test because lacking privs.");
else if (ERRNO_IS_NEG_NOT_SUPPORTED(fd2))
log_notice("Skipping open-by-cgroup-id test because syscall is missing or blocked.");
else {
ASSERT_OK(fd2);
ASSERT_OK(fd_get_path(fd2, &p2));
ASSERT_TRUE(path_equal(p2, "/sys/fs/cgroup"));
ASSERT_OK(cg_fd_get_cgroupid(fd2, &id2));
ASSERT_EQ(id, id2);
ASSERT_OK_EQ(inode_same_at(fd, NULL, fd2, NULL, AT_EMPTY_PATH), true);
}
}
DEFINE_TEST_MAIN(LOG_DEBUG);
+73 -1
View File
@@ -11,6 +11,7 @@
#include "pidref.h"
#include "process-util.h"
#include "special.h"
#include "stat-util.h"
#include "string-util.h"
#include "tests.h"
@@ -334,6 +335,36 @@ TEST(controller_is_valid) {
assert_se(!cg_controller_is_valid("tatü"));
}
TEST(cg_split_spec) {
char *c, *p;
ASSERT_OK_ZERO(cg_split_spec("foobar:/", &c, &p));
ASSERT_STREQ(c, "foobar");
ASSERT_STREQ(p, "/");
c = mfree(c);
p = mfree(p);
ASSERT_OK_ZERO(cg_split_spec("foobar:", &c, &p));
c = mfree(c);
p = mfree(p);
ASSERT_FAIL(cg_split_spec("foobar:asdfd", &c, &p));
ASSERT_FAIL(cg_split_spec(":///", &c, &p));
ASSERT_FAIL(cg_split_spec(":", &c, &p));
ASSERT_FAIL(cg_split_spec("", &c, &p));
ASSERT_FAIL(cg_split_spec("fo/obar:/", &c, &p));
ASSERT_OK(cg_split_spec("/", &c, &p));
ASSERT_NULL(c);
ASSERT_STREQ(p, "/");
p = mfree(p);
ASSERT_OK(cg_split_spec("foo", &c, &p));
ASSERT_STREQ(c, "foo");
ASSERT_NULL(p);
c = mfree(c);
}
static void test_slice_to_path_one(const char *unit, const char *path, int error) {
_cleanup_free_ char *ret = NULL;
int r;
@@ -432,7 +463,7 @@ TEST(cg_get_keyed_attribute) {
int r;
r = cg_get_keyed_attribute("cpu", "/init.scope", "no_such_file", STRV_MAKE("no_such_attr"), &val);
if (IN_SET(r, -ENOMEDIUM, -ENOENT) || ERRNO_IS_PRIVILEGE(r)) {
if (r == -ENOMEDIUM || ERRNO_IS_PRIVILEGE(r)) {
log_info_errno(r, "Skipping most of %s, /sys/fs/cgroup not accessible: %m", __func__);
return;
}
@@ -473,4 +504,45 @@ TEST(bfq_weight_conversion) {
assert_se(BFQ_WEIGHT(10000) == 1000);
}
TEST(cgroupid) {
_cleanup_free_ char *p = NULL, *p2 = NULL;
_cleanup_close_ int fd = -EBADF, fd2 = -EBADF;
uint64_t id, id2;
int r;
r = cg_all_unified();
if (IN_SET(r, -ENOMEDIUM, -ENOENT))
return (void) log_tests_skipped("cgroupfs is not mounted");
if (r == 0)
return (void) log_tests_skipped("skipping cgroupid test, not running in unified mode");
ASSERT_OK_POSITIVE(r);
fd = cg_path_open(SYSTEMD_CGROUP_CONTROLLER, "/");
ASSERT_OK(fd);
ASSERT_OK(fd_get_path(fd, &p));
ASSERT_TRUE(path_equal(p, "/sys/fs/cgroup"));
ASSERT_OK(cg_fd_get_cgroupid(fd, &id));
fd2 = cg_cgroupid_open(fd, id);
if (ERRNO_IS_NEG_PRIVILEGE(fd2))
log_notice("Skipping open-by-cgroup-id test because lacking privs.");
else if (ERRNO_IS_NEG_NOT_SUPPORTED(fd2))
log_notice("Skipping open-by-cgroup-id test because syscall is missing or blocked.");
else {
ASSERT_OK(fd2);
ASSERT_OK(fd_get_path(fd2, &p2));
ASSERT_TRUE(path_equal(p2, "/sys/fs/cgroup"));
ASSERT_OK(cg_fd_get_cgroupid(fd2, &id2));
ASSERT_EQ(id, id2);
ASSERT_OK_EQ(inode_same_at(fd, NULL, fd2, NULL, AT_EMPTY_PATH), true);
}
}
DEFINE_TEST_MAIN(LOG_DEBUG);
+3
View File
@@ -1613,6 +1613,9 @@ static int intro(void) {
if (geteuid() != 0 || have_effective_cap(CAP_SYS_ADMIN) <= 0)
return log_tests_skipped("not privileged");
if (running_in_chroot() > 0)
return log_tests_skipped("running in chroot");
if (enter_cgroup_subroot(NULL) == -ENOMEDIUM)
return log_tests_skipped("cgroupfs not available");
+97 -162
View File
@@ -23,6 +23,23 @@
#include "strv.h"
#include "tests.h"
#include "tmpfile-util.h"
#include "virt.h"
#define FORK_COMMON_FLAGS \
(FORK_CLOSE_ALL_FDS | \
FORK_RESET_SIGNALS | \
FORK_DEATHSIG_SIGTERM | \
FORK_LOG | \
FORK_REOPEN_LOG | \
FORK_WAIT | \
FORK_NEW_MOUNTNS | \
FORK_MOUNTNS_SLAVE)
#define CHECK_PRIV \
if (geteuid() != 0 || have_effective_cap(CAP_SYS_ADMIN) <= 0) \
return (void) log_tests_skipped("Not privileged"); \
if (running_in_chroot() > 0) \
return (void) log_tests_skipped("running in chroot");
TEST(mount_option_mangle) {
char *opts = NULL;
@@ -132,11 +149,9 @@ TEST(mount_flags_to_string) {
TEST(bind_remount_recursive) {
_cleanup_(rm_rf_physical_and_freep) char *tmp = NULL;
_cleanup_free_ char *subdir = NULL;
int r;
if (geteuid() != 0 || have_effective_cap(CAP_SYS_ADMIN) <= 0) {
(void) log_tests_skipped("not running privileged");
return;
}
CHECK_PRIV;
assert_se(mkdtemp_malloc("/tmp/XXXXXX", &tmp) >= 0);
subdir = path_join(tmp, "subdir");
@@ -144,15 +159,9 @@ TEST(bind_remount_recursive) {
assert_se(mkdir(subdir, 0755) >= 0);
FOREACH_STRING(p, "/usr", "/sys", "/", tmp) {
pid_t pid;
pid = fork();
assert_se(pid >= 0);
if (pid == 0) {
ASSERT_OK(r = safe_fork("(bind-remount-recursive)", FORK_COMMON_FLAGS, NULL));
if (r == 0) { /* child */
struct statvfs svfs;
/* child */
assert_se(detach_mount_namespace() >= 0);
/* Check that the subdir is writable (it must be because it's in /tmp) */
assert_se(statvfs(subdir, &svfs) >= 0);
@@ -178,29 +187,18 @@ TEST(bind_remount_recursive) {
_exit(EXIT_SUCCESS);
}
assert_se(wait_for_terminate_and_check("test-remount-rec", pid, WAIT_LOG) == EXIT_SUCCESS);
}
}
TEST(bind_remount_one) {
pid_t pid;
int r;
if (geteuid() != 0 || have_effective_cap(CAP_SYS_ADMIN) <= 0) {
(void) log_tests_skipped("not running privileged");
return;
}
pid = fork();
assert_se(pid >= 0);
if (pid == 0) {
/* child */
CHECK_PRIV;
ASSERT_OK(r = safe_fork("(remount-one-with-mountinfo)", FORK_COMMON_FLAGS, NULL));
if (r == 0) { /* child */
_cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
assert_se(detach_mount_namespace() >= 0);
assert_se(fopen_unlocked("/proc/self/mountinfo", "re", &proc_self_mountinfo) >= 0);
assert_se(bind_remount_one_with_mountinfo("/run", MS_RDONLY, MS_RDONLY, proc_self_mountinfo) >= 0);
@@ -212,16 +210,8 @@ TEST(bind_remount_one) {
_exit(EXIT_SUCCESS);
}
assert_se(wait_for_terminate_and_check("test-remount-one-with-mountinfo", pid, WAIT_LOG) == EXIT_SUCCESS);
pid = fork();
assert_se(pid >= 0);
if (pid == 0) {
/* child */
assert_se(detach_mount_namespace() >= 0);
ASSERT_OK(r = safe_fork("(remount-one)", FORK_COMMON_FLAGS, NULL));
if (r == 0) { /* child */
assert_se(bind_remount_one("/run", MS_RDONLY, MS_RDONLY) >= 0);
assert_se(bind_remount_one("/run", MS_NOEXEC, MS_RDONLY|MS_NOEXEC) >= 0);
assert_se(bind_remount_one("/proc/idontexist", MS_RDONLY, MS_RDONLY) == -ENOENT);
@@ -230,8 +220,6 @@ TEST(bind_remount_one) {
_exit(EXIT_SUCCESS);
}
assert_se(wait_for_terminate_and_check("test-remount-one", pid, WAIT_LOG) == EXIT_SUCCESS);
}
TEST(make_mount_point_inode) {
@@ -283,10 +271,7 @@ TEST(make_mount_switch_root) {
_cleanup_free_ char *s = NULL;
int r;
if (geteuid() != 0 || have_effective_cap(CAP_SYS_ADMIN) <= 0) {
(void) log_tests_skipped("not running privileged");
return;
}
CHECK_PRIV;
assert_se(mkdtemp_malloc(NULL, &t) >= 0);
@@ -305,18 +290,7 @@ TEST(make_mount_switch_root) {
};
FOREACH_ELEMENT(i, table) {
r = safe_fork("(switch-root)",
FORK_RESET_SIGNALS |
FORK_CLOSE_ALL_FDS |
FORK_DEATHSIG_SIGTERM |
FORK_WAIT |
FORK_REOPEN_LOG |
FORK_LOG |
FORK_NEW_MOUNTNS |
FORK_MOUNTNS_SLAVE,
NULL);
assert_se(r >= 0);
ASSERT_OK(r = safe_fork("(switch-root)", FORK_COMMON_FLAGS, NULL));
if (r == 0) {
assert_se(make_mount_point(i->path) >= 0);
assert_se(mount_switch_root_full(i->path, /* mount_propagation_flag= */ 0, i->force_ms_move) >= 0);
@@ -357,23 +331,10 @@ TEST(umount_recursive) {
int r;
CHECK_PRIV;
FOREACH_ELEMENT(t, test_table) {
r = safe_fork("(umount-rec)",
FORK_RESET_SIGNALS |
FORK_CLOSE_ALL_FDS |
FORK_DEATHSIG_SIGTERM |
FORK_WAIT |
FORK_REOPEN_LOG |
FORK_LOG |
FORK_NEW_MOUNTNS |
FORK_MOUNTNS_SLAVE,
NULL);
if (ERRNO_IS_NEG_PRIVILEGE(r))
return (void) log_notice("Skipping umount_recursive() test, lacking privileges");
assert_se(r >= 0);
ASSERT_OK(r = safe_fork("(umount-rec)", FORK_COMMON_FLAGS, NULL));
if (r == 0) { /* child */
_cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL;
_cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL;
@@ -422,10 +383,7 @@ TEST(fd_make_mount_point) {
_cleanup_free_ char *s = NULL;
int r;
if (geteuid() != 0 || have_effective_cap(CAP_SYS_ADMIN) <= 0) {
(void) log_tests_skipped("not running privileged");
return;
}
CHECK_PRIV;
assert_se(mkdtemp_malloc(NULL, &t) >= 0);
@@ -433,18 +391,7 @@ TEST(fd_make_mount_point) {
assert_se(s);
assert_se(mkdir(s, 0700) >= 0);
r = safe_fork("(make_mount-point)",
FORK_RESET_SIGNALS |
FORK_CLOSE_ALL_FDS |
FORK_DEATHSIG_SIGTERM |
FORK_WAIT |
FORK_REOPEN_LOG |
FORK_LOG |
FORK_NEW_MOUNTNS |
FORK_MOUNTNS_SLAVE,
NULL);
assert_se(r >= 0);
ASSERT_OK(r = safe_fork("(make-mount-point)", FORK_COMMON_FLAGS, NULL));
if (r == 0) {
_cleanup_close_ int fd = -EBADF, fd2 = -EBADF;
@@ -468,72 +415,78 @@ TEST(fd_make_mount_point) {
TEST(bind_mount_submounts) {
_cleanup_(rmdir_and_freep) char *a = NULL, *b = NULL;
_cleanup_free_ char *x = NULL;
int r;
CHECK_PRIV;
assert_se(mkdtemp_malloc(NULL, &a) >= 0);
r = mount_nofollow_verbose(LOG_INFO, "tmpfs", a, "tmpfs", 0, NULL);
if (ERRNO_IS_NEG_PRIVILEGE(r))
return (void) log_tests_skipped("Skipping bind_mount_submounts() test, lacking privileges");
assert_se(r >= 0);
assert_se(x = path_join(a, "foo"));
assert_se(touch(x) >= 0);
free(x);
assert_se(x = path_join(a, "x"));
assert_se(mkdir(x, 0755) >= 0);
assert_se(mount_nofollow_verbose(LOG_INFO, "tmpfs", x, "tmpfs", 0, NULL) >= 0);
free(x);
assert_se(x = path_join(a, "x/xx"));
assert_se(touch(x) >= 0);
free(x);
assert_se(x = path_join(a, "y"));
assert_se(mkdir(x, 0755) >= 0);
assert_se(mount_nofollow_verbose(LOG_INFO, "tmpfs", x, "tmpfs", 0, NULL) >= 0);
free(x);
assert_se(x = path_join(a, "y/yy"));
assert_se(touch(x) >= 0);
free(x);
assert_se(mkdtemp_malloc(NULL, &b) >= 0);
assert_se(mount_nofollow_verbose(LOG_INFO, "tmpfs", b, "tmpfs", 0, NULL) >= 0);
assert_se(x = path_join(b, "x"));
assert_se(mkdir(x, 0755) >= 0);
free(x);
ASSERT_OK(r = safe_fork("(bind-mount-submounts)", FORK_COMMON_FLAGS, NULL));
if (r == 0) {
char *x;
assert_se(x = path_join(b, "y"));
assert_se(mkdir(x, 0755) >= 0);
free(x);
ASSERT_OK(mount_nofollow_verbose(LOG_INFO, "tmpfs", a, "tmpfs", 0, NULL));
assert_se(bind_mount_submounts(a, b) >= 0);
assert_se(x = path_join(a, "foo"));
assert_se(touch(x) >= 0);
free(x);
assert_se(x = path_join(b, "foo"));
assert_se(access(x, F_OK) < 0 && errno == ENOENT);
free(x);
assert_se(x = path_join(a, "x"));
assert_se(mkdir(x, 0755) >= 0);
assert_se(mount_nofollow_verbose(LOG_INFO, "tmpfs", x, "tmpfs", 0, NULL) >= 0);
free(x);
assert_se(x = path_join(b, "x/xx"));
assert_se(access(x, F_OK) >= 0);
free(x);
assert_se(x = path_join(a, "x/xx"));
assert_se(touch(x) >= 0);
free(x);
assert_se(x = path_join(b, "y/yy"));
assert_se(access(x, F_OK) >= 0);
free(x);
assert_se(x = path_join(a, "y"));
assert_se(mkdir(x, 0755) >= 0);
assert_se(mount_nofollow_verbose(LOG_INFO, "tmpfs", x, "tmpfs", 0, NULL) >= 0);
free(x);
assert_se(x = path_join(b, "x"));
assert_se(path_is_mount_point(x) > 0);
free(x);
assert_se(x = path_join(a, "y/yy"));
assert_se(touch(x) >= 0);
free(x);
assert_se(x = path_join(b, "y"));
assert_se(path_is_mount_point(x) > 0);
assert_se(mount_nofollow_verbose(LOG_INFO, "tmpfs", b, "tmpfs", 0, NULL) >= 0);
assert_se(umount_recursive(a, 0) >= 0);
assert_se(umount_recursive(b, 0) >= 0);
assert_se(x = path_join(b, "x"));
assert_se(mkdir(x, 0755) >= 0);
free(x);
assert_se(x = path_join(b, "y"));
assert_se(mkdir(x, 0755) >= 0);
free(x);
assert_se(bind_mount_submounts(a, b) >= 0);
assert_se(x = path_join(b, "foo"));
assert_se(access(x, F_OK) < 0 && errno == ENOENT);
free(x);
assert_se(x = path_join(b, "x/xx"));
assert_se(access(x, F_OK) >= 0);
free(x);
assert_se(x = path_join(b, "y/yy"));
assert_se(access(x, F_OK) >= 0);
free(x);
assert_se(x = path_join(b, "x"));
assert_se(path_is_mount_point(x) > 0);
free(x);
assert_se(x = path_join(b, "y"));
assert_se(path_is_mount_point(x) > 0);
free(x);
assert_se(umount_recursive(a, 0) >= 0);
assert_se(umount_recursive(b, 0) >= 0);
_exit(EXIT_SUCCESS);
}
}
TEST(path_is_network_fs_harder) {
@@ -553,26 +506,12 @@ TEST(path_is_network_fs_harder) {
log_debug("path_is_network_fs_harder_at(root, %s) → %i: %s", q, r, r < 0 ? STRERROR(r) : yes_no(r));
}
if (geteuid() != 0 || have_effective_cap(CAP_SYS_ADMIN) <= 0) {
(void) log_tests_skipped("not running privileged");
return;
}
CHECK_PRIV;
_cleanup_(rm_rf_physical_and_freep) char *t = NULL;
assert_se(mkdtemp_malloc("/tmp/test-mount-util.path_is_network_fs_harder.XXXXXXX", &t) >= 0);
r = safe_fork("(make_mount-point)",
FORK_RESET_SIGNALS |
FORK_CLOSE_ALL_FDS |
FORK_DEATHSIG_SIGTERM |
FORK_WAIT |
FORK_REOPEN_LOG |
FORK_LOG |
FORK_NEW_MOUNTNS |
FORK_MOUNTNS_SLAVE,
NULL);
ASSERT_OK(r);
ASSERT_OK(r = safe_fork("(path-is-network-fs-harder)", FORK_COMMON_FLAGS, NULL));
if (r == 0) {
ASSERT_OK(mount_nofollow_verbose(LOG_INFO, "tmpfs", t, "tmpfs", 0, NULL));
ASSERT_OK_ZERO(path_is_network_fs_harder(t));
@@ -587,7 +526,7 @@ TEST(path_is_network_fs_harder) {
}
TEST(umountat) {
int r;
CHECK_PRIV;
_cleanup_(rm_rf_physical_and_freep) char *p = NULL;
_cleanup_close_ int dfd = mkdtemp_open(NULL, O_CLOEXEC, &p);
@@ -597,11 +536,7 @@ TEST(umountat) {
_cleanup_free_ char *q = ASSERT_PTR(path_join(p, "foo"));
r = mount_nofollow_verbose(LOG_ERR, "tmpfs", q, "tmpfs", 0, NULL);
if (ERRNO_IS_NEG_PRIVILEGE(r))
return (void) log_tests_skipped("not running privileged");
ASSERT_OK(r);
ASSERT_OK(mount_nofollow_verbose(LOG_ERR, "tmpfs", q, "tmpfs", 0, NULL));
ASSERT_OK(umountat_detach_verbose(LOG_ERR, dfd, "foo"));
ASSERT_ERROR(umountat_detach_verbose(LOG_ERR, dfd, "foo"), EINVAL);
}
+7
View File
@@ -18,6 +18,7 @@
#include "string-util.h"
#include "tests.h"
#include "tmpfile-util.h"
#include "virt.h"
static void test_mount_propagation_flag_one(const char *name, int ret, unsigned long expected) {
unsigned long flags;
@@ -455,6 +456,12 @@ static int intro(void) {
/* let's move into our own mount namespace with all propagation from the host turned off, so
* that /proc/self/mountinfo is static and constant for the whole time our test runs. */
if (running_in_chroot() > 0) {
/* We cannot remount file system with MS_PRIVATE when running in chroot. */
log_notice("Running in chroot, proceeding in originating mount namespace.");
return EXIT_SUCCESS;
}
if (unshare(CLONE_NEWNS) < 0) {
if (!ERRNO_IS_PRIVILEGE(errno))
return log_error_errno(errno, "Failed to detach mount namespace: %m");
+5 -26
View File
@@ -6,6 +6,7 @@
#include <stdlib.h>
#include <sys/socket.h>
#include "locale-util.h"
#include "parse-util.h"
#include "tests.h"
@@ -655,7 +656,6 @@ TEST(safe_atoux64) {
TEST(safe_atod) {
double d;
char *e;
ASSERT_ERROR(safe_atod("junk", &d), EINVAL);
@@ -663,39 +663,18 @@ TEST(safe_atod) {
assert_se(fabs(d - 0.2244) < 0.000001);
ASSERT_ERROR(safe_atod("0,5", &d), EINVAL);
errno = 0;
strtod("0,5", &e);
assert_se(*e == ',');
ASSERT_ERROR(safe_atod("", &d), EINVAL);
/* Check if this really is locale independent */
if (setlocale(LC_NUMERIC, "de_DE.utf8")) {
ASSERT_OK_ZERO(safe_atod("0.2244", &d));
assert_se(fabs(d - 0.2244) < 0.000001);
ASSERT_ERROR(safe_atod("0,5", &d), EINVAL);
errno = 0;
assert_se(fabs(strtod("0,5", &e) - 0.5) < 0.00001);
ASSERT_ERROR(safe_atod("", &d), EINVAL);
}
/* And check again, reset */
ASSERT_NOT_NULL(setlocale(LC_NUMERIC, "C"));
_cleanup_(freelocalep) locale_t loc =
newlocale(LC_NUMERIC_MASK, "de_DE.utf8", (locale_t) 0);
if (!loc)
return (void) log_tests_skipped_errno(errno, "locale de_DE.utf8 not found");
ASSERT_OK_ZERO(safe_atod("0.2244", &d));
assert_se(fabs(d - 0.2244) < 0.000001);
ASSERT_ERROR(safe_atod("0,5", &d), EINVAL);
errno = 0;
strtod("0,5", &e);
assert_se(*e == ',');
ASSERT_ERROR(safe_atod("", &d), EINVAL);
}
+76 -235
View File
@@ -42,9 +42,13 @@
# define SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN 0
#endif
static bool have_seccomp_privs(void) {
return geteuid() == 0 && have_effective_cap(CAP_SYS_ADMIN) > 0; /* If we are root but CAP_SYS_ADMIN we can't do caps (unless we also do NNP) */
}
#define CHECK_SECCOMP(refuse_container) \
if (!is_seccomp_available()) \
return (void) log_tests_skipped("Seccomp not available"); \
if (geteuid() != 0 || have_effective_cap(CAP_SYS_ADMIN) <= 0) \
return (void) log_tests_skipped("Not privileged"); \
if (refuse_container && detect_container() > 0) \
return (void) log_tests_skipped("Running in container");
TEST(parse_syscall_and_errno) {
_cleanup_free_ char *n = NULL;
@@ -166,17 +170,11 @@ TEST(syscall_filter_set_find) {
}
TEST(filter_sets) {
if (!is_seccomp_available()) {
log_notice("Seccomp not available, skipping %s", __func__);
return;
}
if (!have_seccomp_privs()) {
log_notice("Not privileged, skipping %s", __func__);
return;
}
int r;
CHECK_SECCOMP(/* skip_container = */ false);
for (unsigned i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) {
pid_t pid;
#if HAVE_VALGRIND_VALGRIND_H
if (RUNNING_ON_VALGRIND && IN_SET(i, SYSCALL_FILTER_SET_DEFAULT, SYSCALL_FILTER_SET_BASIC_IO, SYSCALL_FILTER_SET_SIGNAL)) {
@@ -195,11 +193,9 @@ TEST(filter_sets) {
log_info("Testing %s", syscall_filter_sets[i].name);
pid = fork();
assert_se(pid >= 0);
if (pid == 0) { /* Child? */
int fd, r;
ASSERT_OK(r = safe_fork("(filter_sets)", FORK_LOG | FORK_WAIT, NULL));
if (r == 0) {
int fd;
/* If we look at the default set (or one that includes it), allow-list instead of deny-list */
if (IN_SET(i, SYSCALL_FILTER_SET_DEFAULT,
@@ -222,8 +218,6 @@ TEST(filter_sets) {
_exit(EXIT_SUCCESS);
}
assert_se(wait_for_terminate_and_check(syscall_filter_sets[i].name, pid, WAIT_LOG) == EXIT_SUCCESS);
}
}
@@ -263,12 +257,10 @@ TEST(filter_sets_ordered) {
TEST(restrict_namespace) {
char *s = NULL;
unsigned long ul;
pid_t pid;
int r;
if (!have_namespaces()) {
log_notice("Testing without namespaces, skipping %s", __func__);
return;
}
if (!have_namespaces())
return (void) log_tests_skipped("Testing without namespaces");
assert_se(namespace_flags_to_string(0, &s) == 0 && isempty(s));
s = mfree(s);
@@ -297,19 +289,10 @@ TEST(restrict_namespace) {
assert_se(namespace_flags_from_string(s, &ul) == 0 && ul == NAMESPACE_FLAGS_ALL);
s = mfree(s);
if (!is_seccomp_available()) {
log_notice("Seccomp not available, skipping remaining tests in %s", __func__);
return;
}
if (!have_seccomp_privs()) {
log_notice("Not privileged, skipping remaining tests in %s", __func__);
return;
}
CHECK_SECCOMP(/* skip_container = */ false);
pid = fork();
assert_se(pid >= 0);
if (pid == 0) {
ASSERT_OK(r = safe_fork("(restrict-namespace)", FORK_LOG | FORK_WAIT, NULL));
if (r == 0) {
assert_se(seccomp_restrict_namespaces(CLONE_NEWNS|CLONE_NEWNET) >= 0);
@@ -337,7 +320,7 @@ TEST(restrict_namespace) {
assert_se(setns(0, 0) == -1);
assert_se(errno == EPERM);
pid = raw_clone(CLONE_NEWNS);
pid_t pid = raw_clone(CLONE_NEWNS);
assert_se(pid >= 0);
if (pid == 0)
_exit(EXIT_SUCCESS);
@@ -357,37 +340,21 @@ TEST(restrict_namespace) {
_exit(EXIT_SUCCESS);
}
assert_se(wait_for_terminate_and_check("nsseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
}
TEST(protect_sysctl) {
pid_t pid;
_cleanup_free_ char *seccomp = NULL;
if (!is_seccomp_available()) {
log_notice("Seccomp not available, skipping %s", __func__);
return;
}
if (!have_seccomp_privs()) {
log_notice("Not privileged, skipping %s", __func__);
return;
}
int r;
/* in containers _sysctl() is likely missing anyway */
if (detect_container() > 0) {
log_notice("Testing in container, skipping %s", __func__);
return;
}
CHECK_SECCOMP(/* skip_container = */ true);
_cleanup_free_ char *seccomp = NULL;
assert_se(get_proc_field("/proc/self/status", "Seccomp", &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);
if (pid == 0) {
ASSERT_OK(r = safe_fork("(protect-sysctl)", FORK_LOG | FORK_WAIT, NULL));
if (r == 0) {
#if defined __NR__sysctl && __NR__sysctl >= 0
assert_se(syscall(__NR__sysctl, NULL) < 0);
assert_se(IN_SET(errno, EFAULT, ENOSYS));
@@ -409,32 +376,16 @@ TEST(protect_sysctl) {
_exit(EXIT_SUCCESS);
}
assert_se(wait_for_terminate_and_check("sysctlseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
}
TEST(protect_syslog) {
pid_t pid;
if (!is_seccomp_available()) {
log_notice("Seccomp not available, skipping %s", __func__);
return;
}
if (!have_seccomp_privs()) {
log_notice("Not privileged, skipping %s", __func__);
return;
}
int r;
/* in containers syslog() is likely missing anyway */
if (detect_container() > 0) {
log_notice("Testing in container, skipping %s", __func__);
return;
}
CHECK_SECCOMP(/* skip_container = */ true);
pid = fork();
assert_se(pid >= 0);
if (pid == 0) {
ASSERT_OK(r = safe_fork("(protect-syslog)", FORK_LOG | FORK_WAIT, NULL));
if (r == 0) {
#if defined __NR_syslog && __NR_syslog >= 0
assert_se(syscall(__NR_syslog, -1, NULL, 0) < 0);
assert_se(errno == EINVAL);
@@ -449,26 +400,15 @@ TEST(protect_syslog) {
_exit(EXIT_SUCCESS);
}
assert_se(wait_for_terminate_and_check("syslogseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
}
TEST(restrict_address_families) {
pid_t pid;
int r;
if (!is_seccomp_available()) {
log_notice("Seccomp not available, skipping %s", __func__);
return;
}
if (!have_seccomp_privs()) {
log_notice("Not privileged, skipping %s", __func__);
return;
}
CHECK_SECCOMP(/* skip_container = */ false);
pid = fork();
assert_se(pid >= 0);
if (pid == 0) {
ASSERT_OK(r = safe_fork("(restrict-address-families)", FORK_LOG | FORK_WAIT, NULL));
if (r == 0) {
int fd;
Set *s;
@@ -536,34 +476,23 @@ TEST(restrict_address_families) {
_exit(EXIT_SUCCESS);
}
assert_se(wait_for_terminate_and_check("socketseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
}
TEST(restrict_realtime) {
pid_t pid;
if (!is_seccomp_available()) {
log_notice("Seccomp not available, skipping %s", __func__);
return;
}
if (!have_seccomp_privs()) {
log_notice("Not privileged, skipping %s", __func__);
return;
}
int r;
/* in containers RT privs are likely missing anyway */
if (detect_container() > 0) {
log_notice("Testing in container, skipping %s", __func__);
return;
}
CHECK_SECCOMP(/* skip_container = */ true);
pid = fork();
assert_se(pid >= 0);
if (pid == 0) {
ASSERT_OK(r = safe_fork("(restrict-realtime)", FORK_LOG | FORK_WAIT, NULL));
if (r == 0) {
/* On some CI environments, the restriction may be already enabled. */
if (sched_setscheduler(0, SCHED_FIFO, &(struct sched_param) { .sched_priority = 1 }) < 0) {
if (errno == ENOSYS) {
log_tests_skipped("sched_setscheduler() is not available or already filtered");
_exit(EXIT_SUCCESS);
}
log_full_errno(errno == EPERM ? LOG_DEBUG : LOG_WARNING, errno,
"Failed to set scheduler parameter for FIFO: %m");
assert(errno == EPERM);
@@ -591,21 +520,13 @@ TEST(restrict_realtime) {
_exit(EXIT_SUCCESS);
}
assert_se(wait_for_terminate_and_check("realtimeseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
}
TEST(memory_deny_write_execute_mmap) {
pid_t pid;
int r;
CHECK_SECCOMP(/* skip_container = */ false);
if (!is_seccomp_available()) {
log_notice("Seccomp not available, skipping %s", __func__);
return;
}
if (!have_seccomp_privs()) {
log_notice("Not privileged, skipping %s", __func__);
return;
}
#if HAVE_VALGRIND_VALGRIND_H
if (RUNNING_ON_VALGRIND) {
log_notice("Running on valgrind, skipping %s", __func__);
@@ -617,10 +538,8 @@ TEST(memory_deny_write_execute_mmap) {
return;
#endif
pid = fork();
assert_se(pid >= 0);
if (pid == 0) {
ASSERT_OK(r = safe_fork("(memory_deny_write_execute_mmap)", FORK_LOG | FORK_WAIT, NULL));
if (r == 0) {
void *p;
p = mmap(NULL, page_size(), PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
@@ -649,14 +568,11 @@ TEST(memory_deny_write_execute_mmap) {
_exit(EXIT_SUCCESS);
}
assert_se(wait_for_terminate_and_check("memoryseccomp-mmap", pid, WAIT_LOG) == EXIT_SUCCESS);
}
TEST(memory_deny_write_execute_shmat) {
int shmid;
pid_t pid;
uint32_t arch;
int r, shmid;
SECCOMP_FOREACH_LOCAL_ARCH(arch) {
log_debug("arch %s: SCMP_SYS(mmap) = %d", seccomp_arch_to_string(arch), SCMP_SYS(mmap));
@@ -666,14 +582,8 @@ TEST(memory_deny_write_execute_shmat) {
log_debug("arch %s: SCMP_SYS(shmdt) = %d", seccomp_arch_to_string(arch), SCMP_SYS(shmdt));
}
if (!is_seccomp_available()) {
log_notice("Seccomp not available, skipping %s", __func__);
return;
}
if (!have_seccomp_privs() || have_effective_cap(CAP_IPC_OWNER) <= 0) {
log_notice("Not privileged, skipping %s", __func__);
return;
}
CHECK_SECCOMP(/* skip_container = */ false);
#if HAVE_VALGRIND_VALGRIND_H
if (RUNNING_ON_VALGRIND) {
log_notice("Running on valgrind, skipping %s", __func__);
@@ -688,10 +598,8 @@ TEST(memory_deny_write_execute_shmat) {
shmid = shmget(IPC_PRIVATE, page_size(), 0);
assert_se(shmid >= 0);
pid = fork();
assert_se(pid >= 0);
if (pid == 0) {
ASSERT_OK(r = safe_fork("(memory-deny-write-execute)", FORK_LOG | FORK_WAIT, NULL));
if (r == 0) {
void *p;
p = shmat(shmid, NULL, 0);
@@ -722,26 +630,15 @@ TEST(memory_deny_write_execute_shmat) {
_exit(EXIT_SUCCESS);
}
assert_se(wait_for_terminate_and_check("memoryseccomp-shmat", pid, WAIT_LOG) == EXIT_SUCCESS);
}
TEST(restrict_archs) {
pid_t pid;
int r;
if (!is_seccomp_available()) {
log_notice("Seccomp not available, skipping %s", __func__);
return;
}
if (!have_seccomp_privs()) {
log_notice("Not privileged, skipping %s", __func__);
return;
}
CHECK_SECCOMP(/* skip_container = */ false);
pid = fork();
assert_se(pid >= 0);
if (pid == 0) {
ASSERT_OK(r = safe_fork("(restrict-archs)", FORK_LOG | FORK_WAIT, NULL));
if (r == 0) {
_cleanup_set_free_ Set *s = NULL;
assert_se(access("/", F_OK) >= 0);
@@ -760,26 +657,15 @@ TEST(restrict_archs) {
_exit(EXIT_SUCCESS);
}
assert_se(wait_for_terminate_and_check("archseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
}
TEST(load_syscall_filter_set_raw) {
pid_t pid;
int r;
if (!is_seccomp_available()) {
log_notice("Seccomp not available, skipping %s", __func__);
return;
}
if (!have_seccomp_privs()) {
log_notice("Not privileged, skipping %s", __func__);
return;
}
CHECK_SECCOMP(/* skip_container = */ false);
pid = fork();
assert_se(pid >= 0);
if (pid == 0) {
ASSERT_OK(r = safe_fork("(load-filter)", FORK_LOG | FORK_WAIT, NULL));
if (r == 0) {
_cleanup_hashmap_free_ Hashmap *s = NULL;
assert_se(access("/", F_OK) >= 0);
@@ -873,26 +759,15 @@ TEST(load_syscall_filter_set_raw) {
_exit(EXIT_SUCCESS);
}
assert_se(wait_for_terminate_and_check("syscallrawseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
}
TEST(native_syscalls_filtered) {
pid_t pid;
int r;
if (!is_seccomp_available()) {
log_notice("Seccomp not available, skipping %s", __func__);
return;
}
if (!have_seccomp_privs()) {
log_notice("Not privileged, skipping %s", __func__);
return;
}
CHECK_SECCOMP(/* skip_container = */ false);
pid = fork();
assert_se(pid >= 0);
if (pid == 0) {
ASSERT_OK(r = safe_fork("(native-syscalls)", FORK_LOG | FORK_WAIT, NULL));
if (r == 0) {
_cleanup_set_free_ Set *arch_s = NULL;
_cleanup_hashmap_free_ Hashmap *s = NULL;
@@ -931,32 +806,21 @@ TEST(native_syscalls_filtered) {
_exit(EXIT_SUCCESS);
}
assert_se(wait_for_terminate_and_check("nativeseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
}
TEST(lock_personality) {
unsigned long current_opinionated;
pid_t pid;
int r;
if (!is_seccomp_available()) {
log_notice("Seccomp not available, skipping %s", __func__);
return;
}
if (!have_seccomp_privs()) {
log_notice("Not privileged, skipping %s", __func__);
return;
}
CHECK_SECCOMP(/* skip_container = */ false);
assert_se(opinionated_personality(&current_opinionated) >= 0);
log_info("current personality=0x%lX", (unsigned long) safe_personality(PERSONALITY_INVALID));
log_info("current opinionated personality=0x%lX", current_opinionated);
pid = fork();
assert_se(pid >= 0);
if (pid == 0) {
ASSERT_OK(r = safe_fork("(lock-personality)", FORK_LOG | FORK_WAIT, NULL));
if (r == 0) {
unsigned long current;
assert_se(seccomp_lock_personality(current_opinionated) >= 0);
@@ -988,8 +852,6 @@ TEST(lock_personality) {
assert_se((current & OPINIONATED_PERSONALITY_MASK) == current_opinionated);
_exit(EXIT_SUCCESS);
}
assert_se(wait_for_terminate_and_check("lockpersonalityseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
}
static int real_open(const char *path, int flags, mode_t mode) {
@@ -1023,21 +885,12 @@ static int try_fchmodat2(int dirfd, const char *path, mode_t mode, int flags) {
}
TEST(restrict_suid_sgid) {
pid_t pid;
int r;
if (!is_seccomp_available()) {
log_notice("Seccomp not available, skipping %s", __func__);
return;
}
if (!have_seccomp_privs()) {
log_notice("Not privileged, skipping %s", __func__);
return;
}
CHECK_SECCOMP(/* skip_container = */ false);
pid = fork();
assert_se(pid >= 0);
if (pid == 0) {
ASSERT_OK(r = safe_fork("(suid-sgid)", FORK_LOG | FORK_WAIT, NULL));
if (r == 0) {
char path[] = "/tmp/suidsgidXXXXXX", dir[] = "/tmp/suidsgiddirXXXXXX";
int fd = -EBADF, k = -EBADF;
const char *z;
@@ -1224,8 +1077,6 @@ TEST(restrict_suid_sgid) {
_exit(EXIT_SUCCESS);
}
assert_se(wait_for_terminate_and_check("suidsgidseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
}
static void test_seccomp_suppress_sync_child(void) {
@@ -1258,25 +1109,15 @@ static void test_seccomp_suppress_sync_child(void) {
}
TEST(seccomp_suppress_sync) {
pid_t pid;
int r;
if (!is_seccomp_available()) {
log_notice("Seccomp not available, skipping %s", __func__);
return;
}
if (!have_seccomp_privs()) {
log_notice("Not privileged, skipping %s", __func__);
return;
}
CHECK_SECCOMP(/* skip_container = */ false);
ASSERT_OK_ERRNO(pid = fork());
if (pid == 0) {
ASSERT_OK(r = safe_fork("(suppress-sync)", FORK_LOG | FORK_WAIT, NULL));
if (r == 0) {
test_seccomp_suppress_sync_child();
_exit(EXIT_SUCCESS);
}
ASSERT_EQ(wait_for_terminate_and_check("seccomp_suppress_sync", pid, WAIT_LOG), EXIT_SUCCESS);
}
DEFINE_TEST_MAIN(LOG_DEBUG);
+1 -1
View File
@@ -192,7 +192,7 @@ if want_tests != 'false'
test('test-udev',
test_udev_py,
args : ['-v'],
env : ['UDEV_RULE_RUNNER=' + exe.full_path()],
env : test_env + { 'UDEV_RULE_RUNNER' : exe.full_path() },
depends : exe,
timeout : 180,
suite : 'udev')
+3 -3
View File
@@ -35,12 +35,12 @@ preprocess() {
}
compare() {
if ! diff -u "$TESTDIR/etc/passwd" <(preprocess "$1.expected-passwd" "$3"); then
if ! diff -u "$TESTDIR/etc/passwd" <(preprocess "$1.expected-passwd" "$3") >&2; then
echo >&2 "**** Unexpected output for $f $2"
exit 1
fi
if ! diff -u "$TESTDIR/etc/group" <(preprocess "$1.expected-group" "$3"); then
if ! diff -u "$TESTDIR/etc/group" <(preprocess "$1.expected-group" "$3") >&2; then
echo >&2 "**** Unexpected output for $f $2"
exit 1
fi
@@ -167,7 +167,7 @@ for f in $(find "$SOURCE"/unhappy-*.input | sort -V); do
prepare_testdir "${f%.input}"
cp "$f" "$TESTDIR/usr/lib/sysusers.d/test.conf"
SYSTEMD_LOG_LEVEL=info "$SYSUSERS" --root="$TESTDIR" 2>&1 | tail -n1 | sed -r 's/^[^:]+:[^:]+://' >"$TESTDIR/err"
if ! diff -u "$TESTDIR/err" "${f%.*}.expected-err"; then
if ! diff -u "$TESTDIR/err" "${f%.*}.expected-err" >&2; then
echo >&2 "**** Unexpected error output for $f"
cat >&2 "$TESTDIR/err"
exit 1