Message ID | 1325611865-19192-3-git-send-email-apw@canonical.com |
---|---|
State | New |
Headers | show |
On 01/03/2012 09:31 AM, Andy Whitcroft wrote: > From: Jan Kiszka<jan.kiszka@siemens.com> > > User space may create the PIT and forgets about setting up the irqchips. > In that case, firing PIT IRQs will crash the host: > > BUG: unable to handle kernel NULL pointer dereference at 0000000000000128 > IP: [<ffffffffa10f6280>] kvm_set_irq+0x30/0x170 [kvm] > ... > Call Trace: > [<ffffffffa11228c1>] pit_do_work+0x51/0xd0 [kvm] > [<ffffffff81071431>] process_one_work+0x111/0x4d0 > [<ffffffff81071bb2>] worker_thread+0x152/0x340 > [<ffffffff81075c8e>] kthread+0x7e/0x90 > [<ffffffff815a4474>] kernel_thread_helper+0x4/0x10 > > Prevent this by checking the irqchip mode before starting a timer. We > can't deny creating the PIT if the irqchips aren't set up yet as > current user land expects this order to work. > > Signed-off-by: Jan Kiszka<jan.kiszka@siemens.com> > Signed-off-by: Marcelo Tosatti<mtosatti@redhat.com> > > (cherry picked from commit 0924ab2cfa98b1ece26c033d696651fd62896c69) > CVE-2011-4622 > BugLink: http://bugs.launchpad.net/bugs/911303 > Signed-off-by: Andy Whitcroft<apw@canonical.com> > --- > arch/x86/kvm/i8254.c | 10 +++++++--- > 1 files changed, 7 insertions(+), 3 deletions(-) > > diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c > index 0150aff..ac06e2a 100644 > --- a/arch/x86/kvm/i8254.c > +++ b/arch/x86/kvm/i8254.c > @@ -280,11 +280,15 @@ static struct kvm_timer_ops kpit_ops = { > .is_periodic = kpit_is_periodic, > }; > > -static void create_pit_timer(struct kvm_kpit_state *ps, u32 val, int is_period) > +static void create_pit_timer(struct kvm *kvm, u32 val, int is_period) > { > + struct kvm_kpit_state *ps =&kvm->arch.vpit->pit_state; > struct kvm_timer *pt =&ps->pit_timer; > s64 interval; > > + if (!irqchip_in_kernel(kvm)) > + return; > + > interval = muldiv64(val, NSEC_PER_SEC, KVM_PIT_FREQ); > > pr_debug("create pit timer, interval is %llu nsec\n", interval); > @@ -336,13 +340,13 @@ static void pit_load_count(struct kvm *kvm, int channel, u32 val) > /* FIXME: enhance mode 4 precision */ > case 4: > if (!(ps->flags& KVM_PIT_FLAGS_HPET_LEGACY)) { > - create_pit_timer(ps, val, 0); > + create_pit_timer(kvm, val, 0); > } > break; > case 2: > case 3: > if (!(ps->flags& KVM_PIT_FLAGS_HPET_LEGACY)){ > - create_pit_timer(ps, val, 1); > + create_pit_timer(kvm, val, 1); > } > break; > default:
diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c index 0150aff..ac06e2a 100644 --- a/arch/x86/kvm/i8254.c +++ b/arch/x86/kvm/i8254.c @@ -280,11 +280,15 @@ static struct kvm_timer_ops kpit_ops = { .is_periodic = kpit_is_periodic, }; -static void create_pit_timer(struct kvm_kpit_state *ps, u32 val, int is_period) +static void create_pit_timer(struct kvm *kvm, u32 val, int is_period) { + struct kvm_kpit_state *ps = &kvm->arch.vpit->pit_state; struct kvm_timer *pt = &ps->pit_timer; s64 interval; + if (!irqchip_in_kernel(kvm)) + return; + interval = muldiv64(val, NSEC_PER_SEC, KVM_PIT_FREQ); pr_debug("create pit timer, interval is %llu nsec\n", interval); @@ -336,13 +340,13 @@ static void pit_load_count(struct kvm *kvm, int channel, u32 val) /* FIXME: enhance mode 4 precision */ case 4: if (!(ps->flags & KVM_PIT_FLAGS_HPET_LEGACY)) { - create_pit_timer(ps, val, 0); + create_pit_timer(kvm, val, 0); } break; case 2: case 3: if (!(ps->flags & KVM_PIT_FLAGS_HPET_LEGACY)){ - create_pit_timer(ps, val, 1); + create_pit_timer(kvm, val, 1); } break; default: