[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH] xvmalloc: extend to cover multi-dimensional arrays
Take care of the multiplication(s) involved in determining overall size in the macros themselves, saturating to ULONG_MAX. This way on 64-bit systems the subsequent check against UINT_MAX will fail, while on 32- bit systems allocations of this size simply cannot be fulfilled anyway (such an allocation would consume the entire address space). The only place where we truly consume guest input (but constrained to hwdom) is cpufreq_statistic_init(). Play safe however and convert the other three instances where a multiplication is involved as well. While touching those sites also switch to xv*alloc_array(), following what was settled upon when those were introduced. Don't bother extending x*alloc_array() the same way. Reported-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> --- To my surprise code gen even improves a tiny bit for do_memory_op(), in surrounding code (with gcc14). --- a/xen/arch/x86/cpu/mcheck/mctelem.c +++ b/xen/arch/x86/cpu/mcheck/mctelem.c @@ -20,6 +20,7 @@ #include <xen/sched.h> #include <xen/cpumask.h> #include <xen/event.h> +#include <xen/xvmalloc.h> #include <asm/processor.h> #include <asm/system.h> @@ -340,7 +341,7 @@ void __init mctelem_init(unsigned int da if ((mctctl.mctc_elems = xmalloc_array(struct mctelem_ent, MC_NENT)) == NULL || - (datarr = xmalloc_bytes(MC_NENT * datasz)) == NULL) { + (datarr = xvmalloc_array(char, MC_NENT, datasz)) == NULL) { xfree(mctctl.mctc_elems); printk("Allocations for MCA telemetry failed\n"); return; --- a/xen/common/domctl.c +++ b/xen/common/domctl.c @@ -26,6 +26,8 @@ #include <xen/hypercall.h> #include <xen/vm_event.h> #include <xen/monitor.h> +#include <xen/xvmalloc.h> + #include <asm/current.h> #include <asm/irq.h> #include <asm/page.h> @@ -160,7 +162,7 @@ void vnuma_destroy(struct vnuma_info *vn { xfree(vnuma->vmemrange); xfree(vnuma->vcpu_to_vnode); - xfree(vnuma->vdistance); + xvfree(vnuma->vdistance); xfree(vnuma->vnode_to_pnode); xfree(vnuma); } @@ -197,7 +199,7 @@ static struct vnuma_info *vnuma_alloc(un if ( !vnuma ) return ERR_PTR(-ENOMEM); - vnuma->vdistance = xmalloc_array(unsigned int, nr_vnodes * nr_vnodes); + vnuma->vdistance = xvmalloc_array(unsigned int, nr_vnodes, nr_vnodes); vnuma->vcpu_to_vnode = xmalloc_array(unsigned int, nr_vcpus); vnuma->vnode_to_pnode = xmalloc_array(nodeid_t, nr_vnodes); vnuma->vmemrange = xmalloc_array(xen_vmemrange_t, nr_ranges); --- a/xen/common/memory.c +++ b/xen/common/memory.c @@ -26,6 +26,8 @@ #include <xen/sections.h> #include <xen/trace.h> #include <xen/types.h> +#include <xen/xvmalloc.h> + #include <asm/current.h> #include <asm/hardirq.h> #include <asm/p2m.h> @@ -1750,7 +1752,7 @@ long do_memory_op(unsigned long cmd, XEN read_unlock(&d->vnuma_rwlock); - tmp.vdistance = xmalloc_array(unsigned int, dom_vnodes * dom_vnodes); + tmp.vdistance = xvmalloc_array(unsigned int, dom_vnodes, dom_vnodes); tmp.vmemrange = xmalloc_array(xen_vmemrange_t, dom_vranges); tmp.vcpu_to_vnode = xmalloc_array(unsigned int, dom_vcpus); @@ -1813,7 +1815,7 @@ long do_memory_op(unsigned long cmd, XEN vnumainfo_out: rcu_unlock_domain(d); - xfree(tmp.vdistance); + xvfree(tmp.vdistance); xfree(tmp.vmemrange); xfree(tmp.vcpu_to_vnode); break; --- a/xen/drivers/acpi/pmstat.c +++ b/xen/drivers/acpi/pmstat.c @@ -36,6 +36,7 @@ #include <xen/percpu.h> #include <xen/domain.h> #include <xen/acpi.h> +#include <xen/xvmalloc.h> #include <public/sysctl.h> #include <acpi/cpufreq/cpufreq.h> @@ -126,7 +127,7 @@ int cpufreq_statistic_init(unsigned int } per_cpu(cpufreq_statistic_data, cpu) = pxpt; - pxpt->u.trans_pt = xzalloc_array(uint64_t, count * count); + pxpt->u.trans_pt = xvzalloc_array(uint64_t, count, count); if ( !pxpt->u.trans_pt ) { xfree(pxpt); @@ -137,7 +138,7 @@ int cpufreq_statistic_init(unsigned int pxpt->u.pt = xzalloc_array(struct pm_px_val, count); if ( !pxpt->u.pt ) { - xfree(pxpt->u.trans_pt); + xvfree(pxpt->u.trans_pt); xfree(pxpt); spin_unlock(cpufreq_statistic_lock); return -ENOMEM; @@ -171,7 +172,7 @@ void cpufreq_statistic_exit(unsigned int return; } - xfree(pxpt->u.trans_pt); + xvfree(pxpt->u.trans_pt); xfree(pxpt->u.pt); xfree(pxpt); per_cpu(cpufreq_statistic_data, cpu) = NULL; --- a/xen/include/xen/xvmalloc.h +++ b/xen/include/xen/xvmalloc.h @@ -22,11 +22,24 @@ (typeof(*(ptr)) *)p_; \ }) +#define DIM_MUL1(n) (n) +#define DIM_MUL2(n1, n2) ({ \ + unsigned long res_; \ + __builtin_umull_overflow(n1, n2, &res_) ? ULONG_MAX : res_; \ +}) +#define DIM_MUL3(n1, n2, n3) DIM_MUL2(DIM_MUL2(n1, n2), n3) +#define DIM_MUL4(n1, n2, n3, n4) DIM_MUL2(DIM_MUL2(n1, n2), \ + DIM_MUL2(n3, n4)) +#define DIM_MUL_(n, nums...) DIM_MUL##n(nums) +#define DIM_MUL(n, nums...) DIM_MUL_(n, ## nums) + /* Allocate space for array of typed objects. */ -#define xvmalloc_array(_type, _num) \ - ((_type *)_xvmalloc_array(sizeof(_type), __alignof__(_type), _num)) -#define xvzalloc_array(_type, _num) \ - ((_type *)_xvzalloc_array(sizeof(_type), __alignof__(_type), _num)) +#define xvmalloc_array(type, num, nums...) \ + ((type *)_xvmalloc_array(sizeof(type), __alignof__(type), \ + DIM_MUL(count_args(num, ## nums), num, ## nums))) +#define xvzalloc_array(type, num, nums...) \ + ((type *)_xvzalloc_array(sizeof(type), __alignof__(type), \ + DIM_MUL(count_args(num, ## nums), num, ## nums))) /* Allocate space for a structure with a flexible array of typed objects. */ #define xvzalloc_flex_struct(type, field, nr) \
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |