[CRIU] [PATCH 1/5] cpuinfo: x86 -- Add dump and validation

Cyrill Gorcunov gorcunov at openvz.org
Mon Sep 8 14:39:36 PDT 2014


Make sure the processor we're restoring on
is not less capable in features.

Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
 arch/aarch64/cpu.c   |  10 +++++
 arch/arm/cpu.c       |  10 +++++
 arch/x86/cpu.c       | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++
 cr-dump.c            |   5 +++
 cr-restore.c         |   3 ++
 include/cpu.h        |   2 +
 include/cr_options.h |   1 +
 7 files changed, 144 insertions(+)

diff --git a/arch/aarch64/cpu.c b/arch/aarch64/cpu.c
index 6f4b5284a377..f13d635c2c5a 100644
--- a/arch/aarch64/cpu.c
+++ b/arch/aarch64/cpu.c
@@ -16,3 +16,13 @@ int cpu_init(void)
 {
 	return 0;
 }
+
+int cpu_dump_cpuinfo(void)
+{
+	return 0;
+}
+
+int cpu_validate_image_cpuinfo(void)
+{
+	return 0;
+}
diff --git a/arch/arm/cpu.c b/arch/arm/cpu.c
index 6f4b5284a377..f13d635c2c5a 100644
--- a/arch/arm/cpu.c
+++ b/arch/arm/cpu.c
@@ -16,3 +16,13 @@ int cpu_init(void)
 {
 	return 0;
 }
+
+int cpu_dump_cpuinfo(void)
+{
+	return 0;
+}
+
+int cpu_validate_image_cpuinfo(void)
+{
+	return 0;
+}
diff --git a/arch/x86/cpu.c b/arch/x86/cpu.c
index 1ff8de1831ad..d43fdbbeac04 100644
--- a/arch/x86/cpu.c
+++ b/arch/x86/cpu.c
@@ -13,6 +13,7 @@
 
 #include "compiler.h"
 
+#include "cr_options.h"
 #include "proc_parse.h"
 #include "util.h"
 #include "log.h"
@@ -337,3 +338,115 @@ int cpu_init(void)
 
 	return 0;
 }
+
+int cpu_dump_cpuinfo(void)
+{
+	int fd;
+
+	fd = open_image(CR_FD_CPUINFO, O_DUMP);
+	if (fd < 0)
+		return -1;
+
+	if (pb_write_one(fd, &cpu_info, PB_CPUINFO) < 0)
+		return -1;
+
+	close(fd);
+	return 0;
+}
+
+int cpu_validate_features(CpuinfoX86Entry *img_x86_entry)
+{
+	size_t size;
+
+	/*
+	 * A user knows what he is doing and disabled
+	 * capabilities check.
+	 */
+	if (opts.cpu_cap == CPU_CAP_NONE)
+		return 0;
+
+	size = img_x86_entry->n_features * sizeof(img_x86_entry->features[0]);
+	if (size > sizeof(cpu_features)) {
+		/*
+		 * Image carries more bits that we know of.
+		 * Simply reject, we can't guarantee anything
+		 * in such case.
+		 */
+		pr_err("Size of features in image exceed "
+		       "one provided by run time CPU (%d:%d)\n",
+		       (unsigned)size, (unsigned)sizeof(cpu_features));
+		return -1;
+	}
+
+	if (opts.cpu_cap & CPU_CAP_FPU) {
+		/*
+		 * Check if runtime CPU has all FPU related
+		 * bits non less capable.
+		 */
+
+		/*
+		 * FIXME Make sure the image @features
+		 * is big enough to keep FPU bits.
+		 */
+
+#define __mismatch_fpu_bit(__bit)					\
+		(test_bit(__bit, (void *)img_x86_entry->features) &&	\
+		 !cpu_has_feature(__bit))
+
+		if (__mismatch_fpu_bit(X86_FEATURE_FPU)		||
+		    __mismatch_fpu_bit(X86_FEATURE_FXSR)	||
+		    __mismatch_fpu_bit(X86_FEATURE_XSAVE)){
+			pr_err("FPU feature required by image "
+			       "is not supported on host.\n");
+			return false;
+		} else
+			return 0;
+#undef __mismatch_fpu_bit
+	}
+
+	return memcmp(img_x86_entry->features, cpu_features,
+		      min(size, sizeof(cpu_features)));
+}
+
+int cpu_validate_image_cpuinfo(void)
+{
+	CpuinfoX86Entry *img_x86_entry;
+	CpuinfoEntry *img_cpu_info;
+	int fd, ret = -1;
+
+	fd = open_image(CR_FD_CPUINFO, O_RSTR | O_OPT);
+	if (fd < 0) {
+		if (fd == -ENOENT)
+			return 0;
+		return -1;
+	}
+
+	if (pb_read_one(fd, &img_cpu_info, PB_CPUINFO) < 0)
+		goto err;
+
+	if (img_cpu_info->n_x86_entry != 1) {
+		pr_err("No x86 related cpuinfo in image, "
+		       "corruption (n_x86_entry = %zi)\n",
+		       img_cpu_info->n_x86_entry);
+		goto err;
+	}
+
+	img_x86_entry = img_cpu_info->x86_entry[0];
+	if (img_x86_entry->vendor_id != CPUINFO_X86_ENTRY__VENDOR__INTEL &&
+	    img_x86_entry->vendor_id != CPUINFO_X86_ENTRY__VENDOR__AMD) {
+		pr_err("Unknown cpu vendor %d\n", img_x86_entry->vendor_id);
+		goto err;
+	}
+
+	if (img_x86_entry->n_features != protobuf_features_words) {
+		pr_err("Image carries only %u words while %u expected\n",
+		       (unsigned)img_x86_entry->n_features,
+		       (unsigned)protobuf_features_words);
+		return -1;
+	}
+
+	ret = cpu_validate_features(img_x86_entry);
+err:
+	close(fd);
+	return ret;
+}
diff --git a/cr-dump.c b/cr-dump.c
index 91336e82407f..50f03f14e9de 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -1781,6 +1781,11 @@ int cr_dump_tasks(pid_t pid)
 	if (write_img_inventory())
 		goto err;
 
+	if (opts.cpu_cap & CPU_CAP_CPUINFO) {
+		if (cpu_dump_cpuinfo())
+			goto err;
+	}
+
 	if (connect_to_page_server())
 		goto err;
 
diff --git a/cr-restore.c b/cr-restore.c
index d4a2a4619b65..b811f9f735ef 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -1813,6 +1813,9 @@ int cr_restore_tasks(void)
 	if (vdso_init())
 		goto err;
 
+	if (cpu_validate_image_cpuinfo())
+		goto err;
+
 	if (prepare_task_entries() < 0)
 		goto err;
 
diff --git a/include/cpu.h b/include/cpu.h
index 08220cfa7616..c3e3cc6edc2e 100644
--- a/include/cpu.h
+++ b/include/cpu.h
@@ -6,5 +6,7 @@
 extern void cpu_set_feature(unsigned int feature);
 extern bool cpu_has_feature(unsigned int feature);
 extern int cpu_init(void);
+extern int cpu_dump_cpuinfo(void);
+extern int cpu_validate_image_cpuinfo(void);
 
 #endif /* __CR_CPU_H__ */
diff --git a/include/cr_options.h b/include/cr_options.h
index e00d0751217c..2be676563d6e 100644
--- a/include/cr_options.h
+++ b/include/cr_options.h
@@ -10,6 +10,7 @@
  */
 #define CPU_CAP_FPU		(1u)
 #define CPU_CAP_ALL		(-1u)
+#define CPU_CAP_NONE		(0u)
 
 struct cg_root_opt {
 	struct list_head node;
-- 
1.9.3



More information about the CRIU mailing list