[libvirt] [PATCH] qemu: clear seccomp capability if TSYNC is not supported by host
Daniel P. Berrangé
berrange at redhat.com
Thu Aug 30 12:23:27 UTC 2018
On Thu, Aug 30, 2018 at 02:09:41PM +0200, marcandre.lureau at redhat.com wrote:
> From: Marc-André Lureau <marcandre.lureau at 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 at 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;
This all looks fine, but it will trigger a latent bug in virQEMUCapsIsValid.
It only checks kernelVersion for match for the -accel kvm case. We need
to check kernelVersion unconditionally for all emulators we cache.
Regards,
Daniel
--
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o- https://fstop138.berrange.com :|
|: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
More information about the libvir-list
mailing list