[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen master] x86/vPIC: check values loaded from state save record
commit 69c89dd78745c0284aff62ab5869737fb8477b1b Author: Jan Beulich <jbeulich@xxxxxxxx> AuthorDate: Mon Jan 15 12:18:43 2024 +0100 Commit: Jan Beulich <jbeulich@xxxxxxxx> CommitDate: Mon Jan 15 12:18:43 2024 +0100 x86/vPIC: check values loaded from state save record Loading is_master from the state save record can lead to out-of-bounds accesses via at least the two container_of() uses by vpic_domain() and __vpic_lock(). Make sure the value is consistent with the instance being loaded. For ->int_output (which for whatever reason isn't a 1-bit bitfield), besides bounds checking also take ->init_state into account. For ELCR follow what vpic_intercept_elcr_io()'s write path and vpic_reset() do, i.e. don't insist on the internal view of the value to be saved. Move the instance range check as well, leaving just an assertion in the load handler. Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> Reviewed-by: Roger Pau Monné <roger.pau@xxxxxxxxxx> --- xen/arch/x86/hvm/vpic.c | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/xen/arch/x86/hvm/vpic.c b/xen/arch/x86/hvm/vpic.c index 8a6244921d..4e23247a46 100644 --- a/xen/arch/x86/hvm/vpic.c +++ b/xen/arch/x86/hvm/vpic.c @@ -429,6 +429,38 @@ static int cf_check vpic_save(struct vcpu *v, hvm_domain_context_t *h) return 0; } +static int cf_check vpic_check(const struct domain *d, hvm_domain_context_t *h) +{ + unsigned int inst = hvm_load_instance(h); + const struct hvm_hw_vpic *s; + + if ( !has_vpic(d) ) + return -ENODEV; + + /* Which PIC is this? */ + if ( inst >= ARRAY_SIZE(d->arch.hvm.vpic) ) + return -ENOENT; + + s = hvm_get_entry(PIC, h); + if ( !s ) + return -ENODATA; + + /* + * Check to-be-loaded values are within valid range, for them to represent + * actually reachable state. Uses of some of the values elsewhere assume + * this is the case. + */ + if ( s->int_output > 1 ) + return -EDOM; + + if ( s->is_master != !inst || + (s->int_output && s->init_state) || + (s->elcr & ~vpic_elcr_mask(s, 1)) ) + return -EINVAL; + + return 0; +} + static int cf_check vpic_load(struct domain *d, hvm_domain_context_t *h) { struct hvm_hw_vpic *s; @@ -438,18 +470,21 @@ static int cf_check vpic_load(struct domain *d, hvm_domain_context_t *h) return -ENODEV; /* Which PIC is this? */ - if ( inst > 1 ) - return -ENOENT; + ASSERT(inst < ARRAY_SIZE(d->arch.hvm.vpic)); s = &d->arch.hvm.vpic[inst]; /* Load the state */ if ( hvm_load_entry(PIC, h, s) != 0 ) return -EINVAL; + if ( s->is_master ) + s->elcr |= 1 << 2; + return 0; } -HVM_REGISTER_SAVE_RESTORE(PIC, vpic_save, NULL, vpic_load, 2, HVMSR_PER_DOM); +HVM_REGISTER_SAVE_RESTORE(PIC, vpic_save, vpic_check, vpic_load, 2, + HVMSR_PER_DOM); void vpic_reset(struct domain *d) { -- generated by git-patchbot for /home/xen/git/xen.git#master
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |