[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 1/2] tools/libxc: Fix issues with libxc and Xen having different featureset lengths
In almost all cases, Xen and libxc will agree on the featureset length, because they are built from the same source. However, there are circumstances (e.g. security hotfixes) where the featureset gets longer and dom0 will, after installing updates, be running with an old Xen but new libxc. Despite writing the code with this scenario in mind, there were some bugs. First, xen-cpuid's get_featureset() erroneously allocates a buffer based on Xen's featureset length, but records libxc's length, which is longer. The hypercall bounce buffer code reads/writes the recorded length, which is beyond the end of the allocated object, and a later free() encounters corrupt heap metadata. Fix this by recording the same length that we allocate. Secondly, get_cpuid_domain_info() has a related bug when the passed-in featureset is a different length to libxc's. A large amount of the libxc cpuid functionality depends on info->featureset being as long as expected, and it is allocated appropriately. However, in the case that a shorter external featureset is passed in, the logic to check for trailing nonzero bits may read off the end of it. Rework the logic to use the correct upper bound. In addition, leave a comment next to the fields in struct cpuid_domain_info explaining the relationship between the various lengths, and how to cope with different lengths. Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> --- CC: Ian Jackson <Ian.Jackson@xxxxxxxxxx> CC: Wei Liu <wei.liu2@xxxxxxxxxx> CC: Sergey Dyasli <sergey.dyasli@xxxxxxxxxx> --- tools/libxc/xc_cpuid_x86.c | 23 +++++++++++++++++++++-- tools/misc/xen-cpuid.c | 2 +- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/tools/libxc/xc_cpuid_x86.c b/tools/libxc/xc_cpuid_x86.c index 9e47fc8..13862b9 100644 --- a/tools/libxc/xc_cpuid_x86.c +++ b/tools/libxc/xc_cpuid_x86.c @@ -239,6 +239,18 @@ struct cpuid_domain_info bool hvm; uint64_t xfeature_mask; + /* + * Careful with featureset lengths. + * + * Code in this file requires featureset to have at least + * xc_get_cpu_featureset_size() entries. This is a libxc compiletime + * constant. + * + * The featureset length used by the hypervisor may be different. If the + * hypervisor version is longer, XEN_SYSCTL_get_cpu_featureset will fail + * with -ENOBUFS, and libxc really does need rebuilding. If the + * hypervisor version is shorter, it is safe to zero-extend. + */ uint32_t *featureset; unsigned int nr_features; @@ -309,11 +321,18 @@ static int get_cpuid_domain_info(xc_interface *xch, uint32_t domid, if ( featureset ) { + /* + * The user supplied featureset may be shorter or longer than + * host_nr_features. Shorter is fine, and we will zero-extend. + * Longer is fine, so long as it only padded with zeros. + */ + unsigned int fslen = min(host_nr_features, nr_features); + memcpy(info->featureset, featureset, - min(host_nr_features, nr_features) * sizeof(*info->featureset)); + fslen * sizeof(*info->featureset)); /* Check for truncated set bits. */ - for ( i = nr_features; i < host_nr_features; ++i ) + for ( i = fslen; i < nr_features; ++i ) if ( featureset[i] != 0 ) return -EOPNOTSUPP; } diff --git a/tools/misc/xen-cpuid.c b/tools/misc/xen-cpuid.c index 04b11d7..6e7ca8b 100644 --- a/tools/misc/xen-cpuid.c +++ b/tools/misc/xen-cpuid.c @@ -231,7 +231,7 @@ static void get_featureset(xc_interface *xch, unsigned int idx) { struct fsinfo *f = &featuresets[idx]; - f->len = xc_get_cpu_featureset_size(); + f->len = nr_features; f->fs = calloc(nr_features, sizeof(*f->fs)); if ( !f->fs ) -- 2.1.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |