From: Marc-André Lureau <marcandre.lureau(a)redhat.com>
With qemu <= 3.0, when using "-seccomp on", the seccomp policy is only
applied to the main thread, the vcpu worker thread and other worker
threads created after seccomp policy is applied; the seccomp policy is
not applied to e.g. the RCU thread because it is created before the
seccomp policy is applied.
Since qemu commit 70dfabeaa79ba4d7a3b699abe1a047c8012db114 "seccomp:
set the seccomp filter to all threads", qemu will require seccomp
TSYNC flag, and will fail to start if the flag isn't available.
Without it, sandboxing is flawed. Disable seccomp capability if the
host is not capable of using seccomp TSYNC.
Signed-off-by: Marc-André Lureau <marcandre.lureau(a)redhat.com>
---
configure.ac | 2 +-
src/qemu/qemu_capabilities.c | 27 +++++++++++++++++++++++++++
2 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/configure.ac b/configure.ac
index da940e34df..c206de1cad 100644
--- a/configure.ac
+++ b/configure.ac
@@ -330,7 +330,7 @@ AC_CHECK_FUNCS_ONCE([cfmakeraw fallocate geteuid getgid getgrnam_r \
dnl Availability of various common headers (non-fatal if missing).
AC_CHECK_HEADERS([pwd.h regex.h sys/un.h \
- sys/poll.h syslog.h mntent.h net/ethernet.h linux/magic.h \
+ sys/poll.h syslog.h mntent.h net/ethernet.h linux/magic.h linux/seccomp.h \
sys/un.h sys/syscall.h sys/sysctl.h netinet/tcp.h ifaddrs.h \
libtasn1.h sys/ucred.h sys/mount.h stdarg.h])
dnl Check whether endian provides handy macros.
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index a075677421..dd62246eb4 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -54,6 +54,10 @@
#include <sys/wait.h>
#include <stdarg.h>
#include <sys/utsname.h>
+#if defined(HAVE_LINUX_SECCOMP_H) && defined(HAVE_SYS_SYSCALL_H)
+#include <linux/seccomp.h>
+#include <sys/syscall.h>
+#endif
#define VIR_FROM_THIS VIR_FROM_QEMU
@@ -4615,6 +4619,15 @@ virQEMUCapsLogProbeFailure(const char *binary)
}
+#if defined(HAVE_LINUX_SECCOMP_H) && defined(HAVE_SYS_SYSCALL_H)
+static int
+virSeccomp(unsigned int op, unsigned int flags, void *args)
+{
+ errno = 0;
+ return syscall(__NR_seccomp, op, flags, args);
+}
+#endif
+
virQEMUCapsPtr
virQEMUCapsNewForBinaryInternal(virArch hostArch,
const char *binary,
@@ -4679,6 +4692,20 @@ virQEMUCapsNewForBinaryInternal(virArch hostArch,
goto error;
}
+ if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SECCOMP_SANDBOX)) {
+ bool have_seccomp = false;
+#if defined(HAVE_LINUX_SECCOMP_H) && defined(HAVE_SYS_SYSCALL_H)
+ /* check the TSYNC flag - it returns errno == ENOSYS if unavailable */
+ if (virSeccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC, NULL) < 0
&&
+ errno == EFAULT) {
+ have_seccomp = true;
+ }
+#endif
+ if (!have_seccomp) {
+ virQEMUCapsClear(qemuCaps, QEMU_CAPS_SECCOMP_SANDBOX);
+ }
+ }
+
cleanup:
VIR_FREE(qmperr);
return qemuCaps;
--
2.19.0.rc0.48.gb9dfa238d5