[CRIU] [PATCH v3 2/2] cr-service: require non-cooperative userfaultfd for lazy-pages

Mike Rapoport rppt at linux.vnet.ibm.com
Wed Aug 16 10:32:26 MSK 2017


Without non-cooperative userfaultfd some programs may fail during lazy
restore because they perform operations that cannot be handled by the
lazy-pages daemon.

Signed-off-by: Mike Rapoport <rppt at linux.vnet.ibm.com>
---
 criu/cr-check.c     |  9 ++-------
 criu/cr-service.c   | 10 ++--------
 criu/include/uffd.h |  1 +
 criu/uffd.c         |  7 +++++++
 4 files changed, 12 insertions(+), 15 deletions(-)

diff --git a/criu/cr-check.c b/criu/cr-check.c
index caf6422..3bf335b 100644
--- a/criu/cr-check.c
+++ b/criu/cr-check.c
@@ -50,7 +50,7 @@
 #include "libnetlink.h"
 #include "net.h"
 #include "restorer.h"
-#include "linux/userfaultfd.h"
+#include "uffd.h"
 
 static char *feature_name(int (*func)());
 
@@ -1043,15 +1043,10 @@ static int check_uffd(void)
 
 static int check_uffd_noncoop(void)
 {
-	unsigned long features = UFFD_FEATURE_EVENT_FORK |
-		UFFD_FEATURE_EVENT_REMAP |
-		UFFD_FEATURE_EVENT_UNMAP |
-		UFFD_FEATURE_EVENT_REMOVE;
-
 	if (check_uffd())
 		return -1;
 
-	if ((kdat.uffd_features & features) != features) {
+	if (!uffd_noncooperative()) {
 		pr_err("Non-cooperative UFFD is not supported\n");
 		return -1;
 	}
diff --git a/criu/cr-service.c b/criu/cr-service.c
index f0bdfa8..33d4173 100644
--- a/criu/cr-service.c
+++ b/criu/cr-service.c
@@ -40,6 +40,7 @@
 #include <sys/un.h>
 #include <sys/socket.h>
 #include "common/scm.h"
+#include "uffd.h"
 
 #include "setproctitle.h"
 
@@ -888,14 +889,7 @@ static int handle_feature_check(int sk, CriuReq * msg)
 
 		if ((msg->features->has_lazy_pages == 1) &&
 		    (msg->features->lazy_pages == true))
-			/*
-			 * Not checking for specific UFFD features yet.
-			 * If no error is returned it is probably
-			 * enough for basic UFFD functionality. This can
-			 * be extended in the future for a more detailed
-			 * UFFD feature check.
-			 */
-			feat.lazy_pages = kdat.has_uffd;
+			feat.lazy_pages = kdat.has_uffd && uffd_noncooperative();
 
 		resp.features = &feat;
 		resp.type = msg->type;
diff --git a/criu/include/uffd.h b/criu/include/uffd.h
index e2b9be6..79abc16 100644
--- a/criu/include/uffd.h
+++ b/criu/include/uffd.h
@@ -4,6 +4,7 @@
 struct task_restore_args;
 
 extern int uffd_open(int flags, unsigned long *features);
+extern bool uffd_noncooperative(void);
 extern int setup_uffd(int pid, struct task_restore_args *task_args);
 extern int lazy_pages_setup_zombie(int pid);
 extern int prepare_lazy_pages_socket(void);
diff --git a/criu/uffd.c b/criu/uffd.c
index d3142ae..077724b 100644
--- a/criu/uffd.c
+++ b/criu/uffd.c
@@ -211,6 +211,13 @@ int lazy_pages_setup_zombie(int pid)
 	return 0;
 }
 
+bool uffd_noncooperative(void)
+{
+	unsigned long features = NEED_UFFD_API_FEATURES;
+
+	return (kdat.uffd_features & features) == features;
+}
+
 int uffd_open(int flags, unsigned long *features)
 {
 	struct uffdio_api uffdio_api = { 0 };
-- 
2.7.4



More information about the CRIU mailing list