From: Frantisek Sumsal Date: Wed, 22 Jul 2026 12:34:05 +0000 (+0200) Subject: seccomp-util: allow openat2() with --suppress-sync=yes X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fb736873708f24ee6625c55d29a4a9683430d99f;p=thirdparty%2Fsystemd.git seccomp-util: allow openat2() with --suppress-sync=yes When --suppress-sync=yes was introduced in 4a4654e0241fbeabecb8587fd3520b6b39264b9c it filtered out openat2() completely, as we can't check its "flags" argument because it's hidden in an indirect struct. This was perfectly fine at that time, as openat2() was quite new and software shipped with a fallback to open()/openat() if the syscall wasn't present. However, today the situation is different and an increasing number of software is moving to openat2() without any fallback - tar [0] being the most common one in the recent reports and workarounds, and attr recently fixed a CVE by switching to openat2() [1] as well, to name a few. Given that we already block all the sync-family syscalls and calling openat2() with O_SYNC is relatively rare, let's just blanket-enable it in the --suppress-sync=yes mode. This means that we might issue a synchronous write when something calls openat2() with O_SYNC, but not breaking the apps here feels like a reasonable trade-off, at least until a better solution pops up. Note that the same situation is in seccomp_restrict_sxid(), but allowing the openat2() syscall there could actually have some security-related implications under certain circumstances. Resolves: #41868 [0] https://cgit.git.savannah.gnu.org/cgit/tar.git/commit/?id=75b03fdff48916bd0654677ed21379bdb0db016d [1] https://cgit.git.savannah.gnu.org/cgit/attr.git/commit/?id=1cea2fc5e8b5c8a5f29abf1141399e01a57a3154 --- diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c index f02280e4549..0a0471bcb18 100644 --- a/src/shared/seccomp-util.c +++ b/src/shared/seccomp-util.c @@ -2515,18 +2515,16 @@ static int block_open_flag(scmp_filter_ctx seccomp, int flag) { else any = true; -#if defined(__SNR_openat2) - /* The new openat2() system call can't be filtered sensibly, see above. */ - r = sym_seccomp_rule_add_exact( - seccomp, - SCMP_ACT_ERRNO(ENOSYS), - SCMP_SYS(openat2), - 0); - if (r < 0) - log_debug_errno(r, "Failed to add filter for openat2: %m"); - else - any = true; -#endif + /* We can't reasonably filter openat2() here, because the flags are in an indirect struct instead of + * a regular scalar argument, see also the comment in seccomp_restrict_sxid() above. However, + * blocking it here causes an increasing number of issues as more software moves to openat2() without + * any fallback to open()/openat(). + * + * Given that calling openat2() with O_SYNC is rather rare, and most of the heavy-lifting is done by + * filtering out the sync-family syscalls in seccomp_suppress_sync() below, let's just blanket-allow + * openat2() to avoid unnecessarily breaking stuff left and right when nspawn is running with + * --suppress-sync=yes. This means that we might issue a synchronous write when something calls + * openat2() with O_SYNC, but it is the best we can do at least until a better solution pops up. */ return any ? 0 : r; } @@ -2538,7 +2536,7 @@ int seccomp_suppress_sync(void) { /* This behaves slightly differently from SystemCallFilter=~@sync:0, in that negative fds (which * we can determine to be invalid) are still refused with EBADF. See #34478. * - * Additionally, O_SYNC/O_DSYNC are masked. */ + * Additionally, O_SYNC/O_DSYNC are masked (except for openat2(), see above). */ r = dlopen_libseccomp(LOG_DEBUG); if (r < 0)