[libvirt PATCH] qemu: Enable unprivileged userfaultfd for post-copy migration

Jiri Denemark posted 1 patch 2 years, 4 months ago
Test syntax-check failed
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/libvirt tags/patchew/8815ca4f94c2e713e4b4b2cf1c8bf751f5b2da65.1638460609.git.jdenemar@redhat.com
There is a newer version of this series
src/qemu/qemu_migration_params.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
[libvirt PATCH] qemu: Enable unprivileged userfaultfd for post-copy migration
Posted by Jiri Denemark 2 years, 4 months ago
Userfaultfd is by default allowed only for privileged processes. Since
libvirt runs QEMU unprivileged, we need to enable unprivileged access to
userfaultfd before starting post-copy migration.

Rather than providing a static sysctl configuration file, we set the
sysctl knob in runtime once post-copy migration is requested. This way
unprivileged_userfaultfd is only enabled once actually used.

https://bugzilla.redhat.com/show_bug.cgi?id=1945420

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
 src/qemu/qemu_migration_params.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/src/qemu/qemu_migration_params.c b/src/qemu/qemu_migration_params.c
index dbc3219826..a9449ed1ff 100644
--- a/src/qemu/qemu_migration_params.c
+++ b/src/qemu/qemu_migration_params.c
@@ -804,6 +804,24 @@ qemuMigrationCapsToJSON(virBitmap *caps,
 }
 
 
+static void
+qemuMigrationParamsEnableUserfaultfd(virDomainObj *vm)
+{
+    const char *sysctl = "/proc/sys/vm/unprivileged_userfaultfd";
+
+    if (!virFileExists(sysctl))
+        return;
+
+    VIR_DEBUG("Enabling unprivileged userfaultfd for post-copy migration of "
+              "domain %s", vm->def->name);
+
+    if (virFileWriteStr(sysctl, "1", 0) < 0) {
+        virReportSystemError(errno, "%s",
+                             _("failed to enable unprivileged userfaultfd"));
+    }
+}
+
+
 /**
  * qemuMigrationParamsApply
  * @driver: qemu driver
@@ -839,6 +857,13 @@ qemuMigrationParamsApply(virQEMUDriver *driver,
             goto cleanup;
         }
     } else {
+        /* userfaultfd may only be enabled for privileged processes by default,
+         * we need to make sure QEMU can use it before enabling post-copy
+         * migration */
+        if (virBitmapIsBitSet(priv->migrationCaps, QEMU_MIGRATION_CAP_POSTCOPY) &&
+            virBitmapIsBitSet(migParams->caps, QEMU_MIGRATION_CAP_POSTCOPY))
+            qemuMigrationParamsEnableUserfaultfd(vm);
+
         if (!(caps = qemuMigrationCapsToJSON(priv->migrationCaps, migParams->caps)))
             goto cleanup;
 
-- 
2.34.1

Re: [libvirt PATCH] qemu: Enable unprivileged userfaultfd for post-copy migration
Posted by Michal Prívozník 2 years, 4 months ago
On 12/2/21 16:56, Jiri Denemark wrote:
> Userfaultfd is by default allowed only for privileged processes. Since
> libvirt runs QEMU unprivileged, we need to enable unprivileged access to
> userfaultfd before starting post-copy migration.
> 
> Rather than providing a static sysctl configuration file, we set the
> sysctl knob in runtime once post-copy migration is requested. This way
> unprivileged_userfaultfd is only enabled once actually used.
> 
> https://bugzilla.redhat.com/show_bug.cgi?id=1945420
> 
> Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
> ---
>  src/qemu/qemu_migration_params.c | 25 +++++++++++++++++++++++++
>  1 file changed, 25 insertions(+)
> 
> diff --git a/src/qemu/qemu_migration_params.c b/src/qemu/qemu_migration_params.c
> index dbc3219826..a9449ed1ff 100644
> --- a/src/qemu/qemu_migration_params.c
> +++ b/src/qemu/qemu_migration_params.c
> @@ -804,6 +804,24 @@ qemuMigrationCapsToJSON(virBitmap *caps,
>  }
>  
>  
> +static void
> +qemuMigrationParamsEnableUserfaultfd(virDomainObj *vm)
> +{
> +    const char *sysctl = "/proc/sys/vm/unprivileged_userfaultfd";
> +
> +    if (!virFileExists(sysctl))
> +        return;
> +
> +    VIR_DEBUG("Enabling unprivileged userfaultfd for post-copy migration of "
> +              "domain %s", vm->def->name);
> +
> +    if (virFileWriteStr(sysctl, "1", 0) < 0) {
> +        virReportSystemError(errno, "%s",
> +                             _("failed to enable unprivileged userfaultfd"));
> +    }

I can imagine a wild scenario where libvirtd is run inside a restricted
container but with the proper value set. How about we check whether the
expected value isn't set already?

No need to resend, the change is trivial enough to be done before push.

Reviewed-by: Michal Privoznik <mprivozn@redhat.com>

Michal