Repository: systemd/systemd (C)

Issue:
test: test-seccomp randomly fails on CentOS CI (CentOS 7/8)
https://jenkins-systemd.apps.ocp.ci.centos.org/job/upstream-centos7/127/artifact//systemd-centos-ci/artifacts_xC5blF/testsuite-logs-upstream.rAb/ninja-test_FAIL.log
https://jenkins-systemd.apps.ocp.ci.centos.org/job/upstream-centos7/132/artifact//systemd-centos-ci/artifacts_ic4A9k/testsuite-logs-upstream.aZx/ninja-test_FAIL.log
```
303/476 test-seccomp                            FAIL     0.98 s (killed by signal 6 SIGABRT)

--- command ---
SYSTEMD_LANGUAGE_FALLBACK_MAP='/root/systemd/src/locale/language-fallback-map' PATH='/root/systemd/build:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin' SYSTEMD_KBD_MODEL_MAP='/root/systemd/src/locale/kbd-model-map' /root/systemd/build/test-seccomp
--- Listing only the last 100 lines from a long log. ---
System call semtimedop_time64 is not known, ignoring.
Failed to add rule for system call send() / -109, ignoring: Numerical argument out of domain
Failed to add rule for system call sendfile64() / -10043, ignoring: Numerical argument out of domain
Failed to add rule for system call setfsgid32() / -10044, ignoring: Numerical argument out of domain
Failed to add rule for system call setfsuid32() / -10045, ignoring: Numerical argument out of domain
Failed to add rule for system call setgid32() / -10046, ignoring: Numerical argument out of domain
Failed to add rule for system call setgroups32() / -10047, ignoring: Numerical argument out of domain
System call sethae is not known, ignoring.
System call setpgrp is not known, ignoring.
Failed to add rule for system call setregid32() / -10048, ignoring: Numerical argument out of domain
Failed to add rule for system call setresgid32() / -10049, ignoring: Numerical argument out of domain
Failed to add rule for system call setresuid32() / -10050, ignoring: Numerical argument out of domain
Failed to add rule for system call setreuid32() / -10051, ignoring: Numerical argument out of domain
Failed to add rule for system call setuid32() / -10052, ignoring: Numerical argument out of domain
Failed to add rule for system call sgetmask() / -10053, ignoring: Numerical argument out of domain
Failed to add rule for system call sigaction() / -10054, ignoring: Numerical argument out of domain
Failed to add rule for system call signal() / -10055, ignoring: Numerical argument out of domain
Failed to add rule for system call sigpending() / -10056, ignoring: Numerical argument out of domain
Failed to add rule for system call sigprocmask() / -10057, ignoring: Numerical argument out of domain
Failed to add rule for system call sigreturn() / -10058, ignoring: Numerical argument out of domain
Failed to add rule for system call sigsuspend() / -10059, ignoring: Numerical argument out of domain
Failed to add rule for system call socketcall() / -10060, ignoring: Numerical argument out of domain
Failed to add rule for system call spu_create() / -10188, ignoring: Numerical argument out of domain
Failed to add rule for system call spu_run() / -10189, ignoring: Numerical argument out of domain
Failed to add rule for system call ssetmask() / -10061, ignoring: Numerical argument out of domain
Failed to add rule for system call stat64() / -10062, ignoring: Numerical argument out of domain
Failed to add rule for system call statfs64() / -10063, ignoring: Numerical argument out of domain
Failed to add rule for system call stime() / -10064, ignoring: Numerical argument out of domain
Failed to add rule for system call subpage_prot() / -10189, ignoring: Numerical argument out of domain
Failed to add rule for system call swapcontext() / -10190, ignoring: Numerical argument out of domain
Failed to add rule for system call switch_endian() / -10191, ignoring: Numerical argument out of domain
Failed to add rule for system call sync_file_range2() / -10089, ignoring: Numerical argument out of domain
Failed to add rule for system call sys_debug_setcontext() / -10191, ignoring: Numerical argument out of domain
Failed to add rule for system call syscall() / -10090, ignoring: Numerical argument out of domain
Failed to add rule for system call sysmips() / -10106, ignoring: Numerical argument out of domain
System call timer_gettime64 is not known, ignoring.
System call timer_settime64 is not known, ignoring.
Failed to add rule for system call timerfd() / -10107, ignoring: Numerical argument out of domain
System call timerfd_gettime64 is not known, ignoring.
System call timerfd_settime64 is not known, ignoring.
Failed to add rule for system call truncate64() / -10066, ignoring: Numerical argument out of domain
System call udftrap is not known, ignoring.
Failed to add rule for system call ugetrlimit() / -10068, ignoring: Numerical argument out of domain
Failed to add rule for system call umount() / -10070, ignoring: Numerical argument out of domain
System call utimensat_time64 is not known, ignoring.
System call utimesat is not known, ignoring.
System call utrap_install is not known, ignoring.
Failed to add rule for system call vm86() / -10071, ignoring: Numerical argument out of domain
Failed to add rule for system call vm86old() / -10072, ignoring: Numerical argument out of domain
Failed to add rule for system call waitpid() / -10073, ignoring: Numerical argument out of domain
@known succeeded.
/* test_filter_sets_ordered */
/* test_restrict_namespace */
Restricting namespace to: net mnt.
Operating on architecture: x86
Blocking cgroup.
Blocking ipc.
Permitting net.
Permitting mnt.
Blocking pid.
Blocking user.
Blocking uts.
Operating on architecture: x32
Blocking cgroup.
Blocking ipc.
Permitting net.
Permitting mnt.
Blocking pid.
Blocking user.
Blocking uts.
Operating on architecture: x86-64
Blocking cgroup.
Blocking ipc.
Permitting net.
Permitting mnt.
Blocking pid.
Blocking user.
Blocking uts.
nsseccomp succeeded.
/* test_protect_sysctl */
Operating on architecture: x86
Operating on architecture: x32
Operating on architecture: x86-64
sysctlseccomp succeeded.
/* test_protect_syslog */
syslogseccomp succeeded.
/* test_restrict_address_families */
Operating on architecture: x86
Operating on architecture: x32
Operating on architecture: x86-64
Operating on architecture: x86
Operating on architecture: x32
Operating on architecture: x86-64
socketseccomp succeeded.
/* test_restrict_realtime */
Assertion 'sched_setscheduler(0, SCHED_FIFO, &(struct sched_param) { .sched_priority = 1 }) >= 0' failed at src/test/test-seccomp.c:492, function test_restrict_realtime(). Aborting.
realtimeseccomp terminated by signal ABRT.
Assertion 'wait_for_terminate_and_check("realtimeseccomp", pid, WAIT_LOG) == EXIT_SUCCESS' failed at src/test/test-seccomp.c:512, function test_restrict_realtime(). Aborting.
-------
```


Discussion:
I checked last ~60 CentOS 7 builds and the issue seems to be gone (given the previous frequency of the fails). Closing this for now, please reopen if the issue reoccurs.
*Sigh*, looks like the issue resurfaced one again... I wonder what set it off.

 * https://jenkins-systemd.apps.ocp.ci.centos.org/job/upstream-centos7/1694/artifact//systemd-centos-ci/artifacts_yczT54/testsuite-logs-upstream.P5E/ninja-test_FAIL.log
 *  https://jenkins-systemd.apps.ocp.ci.centos.org/job/upstream-centos7/1692/artifact//systemd-centos-ci/artifacts_kO2sZf/testsuite-logs-upstream.i7I/ninja-test_FAIL.log

@mrc0mmand Is this still relevant?
I'll reenable the test in CI to check it.



Patch:
diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c
index 882547d655fba..cd0915e2b2661 100644
--- a/src/shared/seccomp-util.c
+++ b/src/shared/seccomp-util.c
@@ -1602,7 +1602,7 @@ int seccomp_restrict_address_families(Set *address_families, bool allow_list) {
         return 0;
 }
 
-int seccomp_restrict_realtime(void) {
+int seccomp_restrict_realtime_full(int error_code) {
         static const int permitted_policies[] = {
                 SCHED_OTHER,
                 SCHED_BATCH,
@@ -1613,6 +1613,8 @@ int seccomp_restrict_realtime(void) {
         uint32_t arch;
         unsigned i;
 
+        assert(error_code > 0);
+
         /* Determine the highest policy constant we want to allow */
         for (i = 0; i < ELEMENTSOF(permitted_policies); i++)
                 if (permitted_policies[i] > max_policy)
@@ -1646,7 +1648,7 @@ int seccomp_restrict_realtime(void) {
                         /* Deny this policy */
                         r = seccomp_rule_add_exact(
                                         seccomp,
-                                        SCMP_ACT_ERRNO(EPERM),
+                                        SCMP_ACT_ERRNO(error_code),
                                         SCMP_SYS(sched_setscheduler),
                                         1,
                                         SCMP_A1(SCMP_CMP_EQ, p));
@@ -1660,7 +1662,7 @@ int seccomp_restrict_realtime(void) {
                  * are unsigned here, hence no need no check for < 0 values. */
                 r = seccomp_rule_add_exact(
                                 seccomp,
-                                SCMP_ACT_ERRNO(EPERM),
+                                SCMP_ACT_ERRNO(error_code),
                                 SCMP_SYS(sched_setscheduler),
                                 1,
                                 SCMP_A1(SCMP_CMP_GT, max_policy));
diff --git a/src/shared/seccomp-util.h b/src/shared/seccomp-util.h
index aa249539f33d1..3f1a993e11cdc 100644
--- a/src/shared/seccomp-util.h
+++ b/src/shared/seccomp-util.h
@@ -96,7 +96,10 @@ int seccomp_restrict_namespaces(unsigned long retain);
 int seccomp_protect_sysctl(void);
 int seccomp_protect_syslog(void);
 int seccomp_restrict_address_families(Set *address_families, bool allow_list);
-int seccomp_restrict_realtime(void);
+int seccomp_restrict_realtime_full(int error_code); /* This is mostly for testing code. */
+static inline int seccomp_restrict_realtime(void) {
+        return seccomp_restrict_realtime_full(EPERM);
+}
 int seccomp_memory_deny_write_execute(void);
 int seccomp_lock_personality(unsigned long personality);
 int seccomp_protect_hostname(void);


Test patch:
diff --git a/src/test/test-seccomp.c b/src/test/test-seccomp.c
index 3aaeb7147ef00..4c704badbd71c 100644
--- a/src/test/test-seccomp.c
+++ b/src/test/test-seccomp.c
@@ -559,22 +559,32 @@ TEST(restrict_realtime) {
         assert_se(pid >= 0);
 
         if (pid == 0) {
-                assert_se(sched_setscheduler(0, SCHED_FIFO, &(struct sched_param) { .sched_priority = 1 }) >= 0);
-                assert_se(sched_setscheduler(0, SCHED_RR, &(struct sched_param) { .sched_priority = 1 }) >= 0);
+                /* On some CI environments, the restriction may be already enabled. */
+                if (sched_setscheduler(0, SCHED_FIFO, &(struct sched_param) { .sched_priority = 1 }) < 0) {
+                        log_full_errno(errno == EPERM ? LOG_DEBUG : LOG_WARNING, errno,
+                                       "Failed to set scheduler parameter for FIFO: %m");
+                        assert(errno == EPERM);
+                }
+                if (sched_setscheduler(0, SCHED_RR, &(struct sched_param) { .sched_priority = 1 }) < 0) {
+                        log_full_errno(errno == EPERM ? LOG_DEBUG : LOG_WARNING, errno,
+                                       "Failed to set scheduler parameter for RR: %m");
+                        assert(errno == EPERM);
+                }
+
                 assert_se(sched_setscheduler(0, SCHED_IDLE, &(struct sched_param) { .sched_priority = 0 }) >= 0);
                 assert_se(sched_setscheduler(0, SCHED_BATCH, &(struct sched_param) { .sched_priority = 0 }) >= 0);
                 assert_se(sched_setscheduler(0, SCHED_OTHER, &(struct sched_param) {}) >= 0);
 
-                assert_se(seccomp_restrict_realtime() >= 0);
+                assert_se(seccomp_restrict_realtime_full(ENOANO) >= 0);
 
                 assert_se(sched_setscheduler(0, SCHED_IDLE, &(struct sched_param) { .sched_priority = 0 }) >= 0);
                 assert_se(sched_setscheduler(0, SCHED_BATCH, &(struct sched_param) { .sched_priority = 0 }) >= 0);
                 assert_se(sched_setscheduler(0, SCHED_OTHER, &(struct sched_param) {}) >= 0);
 
                 assert_se(sched_setscheduler(0, SCHED_FIFO, &(struct sched_param) { .sched_priority = 1 }) < 0);
-                assert_se(errno == EPERM);
+                assert_se(errno == ENOANO);
                 assert_se(sched_setscheduler(0, SCHED_RR, &(struct sched_param) { .sched_priority = 1 }) < 0);
-                assert_se(errno == EPERM);
+                assert_se(errno == ENOANO);
 
                 _exit(EXIT_SUCCESS);
         }