diff options
Diffstat (limited to 'drivers/xen/xenbus/xenbus_probe.c')
| -rw-r--r-- | drivers/xen/xenbus/xenbus_probe.c | 27 | 
1 files changed, 26 insertions, 1 deletions
| diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c index bd003ca8acbe..fe360c33ce71 100644 --- a/drivers/xen/xenbus/xenbus_probe.c +++ b/drivers/xen/xenbus/xenbus_probe.c @@ -909,7 +909,7 @@ static struct notifier_block xenbus_resume_nb = {  static int __init xenbus_init(void)  { -	int err = 0; +	int err;  	uint64_t v = 0;  	xen_store_domain_type = XS_UNKNOWN; @@ -949,6 +949,29 @@ static int __init xenbus_init(void)  		err = hvm_get_parameter(HVM_PARAM_STORE_PFN, &v);  		if (err)  			goto out_error; +		/* +		 * Uninitialized hvm_params are zero and return no error. +		 * Although it is theoretically possible to have +		 * HVM_PARAM_STORE_PFN set to zero on purpose, in reality it is +		 * not zero when valid. If zero, it means that Xenstore hasn't +		 * been properly initialized. Instead of attempting to map a +		 * wrong guest physical address return error. +		 * +		 * Also recognize all bits set as an invalid value. +		 */ +		if (!v || !~v) { +			err = -ENOENT; +			goto out_error; +		} +		/* Avoid truncation on 32-bit. */ +#if BITS_PER_LONG == 32 +		if (v > ULONG_MAX) { +			pr_err("%s: cannot handle HVM_PARAM_STORE_PFN=%llx > ULONG_MAX\n", +			       __func__, v); +			err = -EINVAL; +			goto out_error; +		} +#endif  		xen_store_gfn = (unsigned long)v;  		xen_store_interface =  			xen_remap(xen_store_gfn << XEN_PAGE_SHIFT, @@ -983,8 +1006,10 @@ static int __init xenbus_init(void)  	 */  	proc_create_mount_point("xen");  #endif +	return 0;  out_error: +	xen_store_domain_type = XS_UNKNOWN;  	return err;  } |