[CRIU] [PATCH 06/15] cpuinfo: x86 -- Add dump and validation

Pavel Emelyanov xemul at parallels.com
Tue Sep 23 11:07:04 PDT 2014


On 09/19/2014 06:03 PM, Cyrill Gorcunov wrote:
> 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)

static

> +{
> +	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;

We already have some --cpu-cap fpu meaning. Do we need to check one here?

> +#undef __mismatch_fpu_bit
> +	}
> +
> +	return memcmp(img_x86_entry->features, cpu_features,
> +		      min(size, sizeof(cpu_features)));

memcmp?! I believe it's not correct. If the cpu has larger feature
mask than the one from the image, then validation should pass.

> +}
> +
> +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 f0cab1b4a613..c439f20ad2b8 100644
> --- a/cr-restore.c
> +++ b/cr-restore.c
> @@ -1830,6 +1830,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 5a7edd9263db..617894bac91c 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;
> 



More information about the CRIU mailing list