[1/9] x86: cpu -- Save xsave frame sizes in image

Submitted by Cyrill Gorcunov on Aug. 7, 2018, 4:35 p.m.

Details

Message ID 20180807163517.21669-2-gorcunov@gmail.com
State New
Series "x86: cpu -- Rework feature testing"
Headers show

Commit Message

Cyrill Gorcunov Aug. 7, 2018, 4:35 p.m.
Keep xsave sizes in image to be sure that on restore
the application won't override memory out of xsave
frame size if been calling xsave instruction directly
(we noticed at least libc did so).

Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
---
 criu/arch/x86/cpu.c  | 33 ++++++++++++++++++++++++++++++---
 images/cpuinfo.proto |  2 ++
 2 files changed, 32 insertions(+), 3 deletions(-)

Patch hide | download patch | download mbox

diff --git a/criu/arch/x86/cpu.c b/criu/arch/x86/cpu.c
index 35660929d17a..9eed742e1b7a 100644
--- a/criu/arch/x86/cpu.c
+++ b/criu/arch/x86/cpu.c
@@ -92,6 +92,10 @@  int cpu_dump_cpuinfo(void)
 	cpu_x86_info.capability = (void *)rt_cpu_info.x86_capability;
 	cpu_x86_info.has_xfeatures_mask = true;
 	cpu_x86_info.xfeatures_mask = rt_cpu_info.xfeatures_mask;
+	cpu_x86_info.has_xsave_size = true;
+	cpu_x86_info.xsave_size = rt_cpu_info.xsave_size;
+	cpu_x86_info.has_xsave_size_max = true;
+	cpu_x86_info.xsave_size_max = rt_cpu_info.xsave_size_max;
 
 	if (rt_cpu_info.x86_model_id[0])
 		cpu_x86_info.model_id = rt_cpu_info.x86_model_id;
@@ -259,14 +263,25 @@  static int cpu_validate_features(compel_cpuinfo_t *cpu_info)
 	}
 
 	/*
-	 * Make sure the xsave features are at least not less
-	 * than current cpu supports.
+	 * Make sure the xsave features are compatible. We already hit the
+	 * issue with libc where we've checkpointed the container on old
+	 * machine but restored on more modern one and libc fetched new
+	 * xsave frame size directly by xsave instruction with greedy
+	 * feature mask causing programs to misbehave.
 	 */
-	if (cpu_info->xfeatures_mask > rt_cpu_info.xfeatures_mask) {
+	if (cpu_info->xfeatures_mask != rt_cpu_info.xfeatures_mask) {
 		uint64_t m = cpu_info->xfeatures_mask & ~rt_cpu_info.xfeatures_mask;
 		pr_err("CPU xfeatures has unsupported bits (%#llx)\n",
 		       (unsigned long long)m);
 		return -1;
+	} else if (cpu_info->xsave_size != rt_cpu_info.xsave_size) {
+		pr_err("CPU xsave size mismatch (%u/%u)\n",
+		       cpu_info->xsave_size, rt_cpu_info.xsave_size);
+		return -1;
+	} else if (cpu_info->xsave_size_max != rt_cpu_info.xsave_size_max) {
+		pr_err("CPU xsave max size mismatch (%u/%u)\n",
+		       cpu_info->xsave_size_max, rt_cpu_info.xsave_size_max);
+		return -1;
 	}
 
 	/*
@@ -370,6 +385,18 @@  static compel_cpuinfo_t *img_to_cpuinfo(CpuinfoX86Entry *img_x86_entry)
 	} else
 		cpu_info->xfeatures_mask = img_x86_entry->xfeatures_mask;
 
+	/*
+	 * Same for other fields.
+	 */
+	if (!img_x86_entry->has_xsave_size)
+		cpu_info->xsave_size = rt_cpu_info.xsave_size;
+	else
+		cpu_info->xsave_size = img_x86_entry->xsave_size;
+	if (!img_x86_entry->has_xsave_size_max)
+		cpu_info->xsave_size_max = rt_cpu_info.xsave_size_max;
+	else
+		cpu_info->xsave_size_max = img_x86_entry->xsave_size_max;
+
 	return cpu_info;
 }
 
diff --git a/images/cpuinfo.proto b/images/cpuinfo.proto
index b399503bdb48..8ee629c2c912 100644
--- a/images/cpuinfo.proto
+++ b/images/cpuinfo.proto
@@ -17,6 +17,8 @@  message cpuinfo_x86_entry {
 	optional string			model_id	= 7;
 
 	optional uint64			xfeatures_mask	= 8;
+	optional uint32			xsave_size	= 9;
+	optional uint32			xsave_size_max	= 10;
 }
 
 message cpuinfo_ppc64_entry {