Skip to content

Commit f4af13b

Browse files
author
Marc Zyngier
committed
Merge branch kvm-arm64/vgic-6.8 into kvmarm-master/next
* kvm-arm64/vgic-6.8: : . : Fix for the GICv4.1 vSGI pending state being set/cleared from : userspace, and some cleanup to the MMIO and userspace accessors : for the pending state. : : Also a fix for a potential UAF in the ITS translation cache. : . KVM: arm64: vgic-its: Avoid potential UAF in LPI translation cache KVM: arm64: vgic-v3: Reinterpret user ISPENDR writes as I{C,S}PENDR KVM: arm64: vgic: Use common accessor for writes to ICPENDR KVM: arm64: vgic: Use common accessor for writes to ISPENDR KVM: arm64: vgic-v4: Restore pending state on host userspace write Signed-off-by: Marc Zyngier <maz@kernel.org>
2 parents d016264 + ad362fe commit f4af13b

3 files changed

Lines changed: 53 additions & 81 deletions

File tree

arch/arm64/kvm/vgic/vgic-its.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,7 +590,11 @@ static struct vgic_irq *vgic_its_check_cache(struct kvm *kvm, phys_addr_t db,
590590
unsigned long flags;
591591

592592
raw_spin_lock_irqsave(&dist->lpi_list_lock, flags);
593+
593594
irq = __vgic_its_check_cache(dist, db, devid, eventid);
595+
if (irq)
596+
vgic_get_irq_kref(irq);
597+
594598
raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
595599

596600
return irq;
@@ -769,6 +773,7 @@ int vgic_its_inject_cached_translation(struct kvm *kvm, struct kvm_msi *msi)
769773
raw_spin_lock_irqsave(&irq->irq_lock, flags);
770774
irq->pending_latch = true;
771775
vgic_queue_irq_unlock(kvm, irq, flags);
776+
vgic_put_irq(kvm, irq);
772777

773778
return 0;
774779
}

arch/arm64/kvm/vgic/vgic-mmio-v3.c

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -357,31 +357,13 @@ static int vgic_v3_uaccess_write_pending(struct kvm_vcpu *vcpu,
357357
gpa_t addr, unsigned int len,
358358
unsigned long val)
359359
{
360-
u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
361-
int i;
362-
unsigned long flags;
363-
364-
for (i = 0; i < len * 8; i++) {
365-
struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
366-
367-
raw_spin_lock_irqsave(&irq->irq_lock, flags);
368-
if (test_bit(i, &val)) {
369-
/*
370-
* pending_latch is set irrespective of irq type
371-
* (level or edge) to avoid dependency that VM should
372-
* restore irq config before pending info.
373-
*/
374-
irq->pending_latch = true;
375-
vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
376-
} else {
377-
irq->pending_latch = false;
378-
raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
379-
}
360+
int ret;
380361

381-
vgic_put_irq(vcpu->kvm, irq);
382-
}
362+
ret = vgic_uaccess_write_spending(vcpu, addr, len, val);
363+
if (ret)
364+
return ret;
383365

384-
return 0;
366+
return vgic_uaccess_write_cpending(vcpu, addr, len, ~val);
385367
}
386368

387369
/* We want to avoid outer shareable. */

arch/arm64/kvm/vgic/vgic-mmio.c

Lines changed: 43 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -301,9 +301,8 @@ static bool is_vgic_v2_sgi(struct kvm_vcpu *vcpu, struct vgic_irq *irq)
301301
vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2);
302302
}
303303

304-
void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
305-
gpa_t addr, unsigned int len,
306-
unsigned long val)
304+
static void __set_pending(struct kvm_vcpu *vcpu, gpa_t addr, unsigned int len,
305+
unsigned long val, bool is_user)
307306
{
308307
u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
309308
int i;
@@ -312,14 +311,22 @@ void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
312311
for_each_set_bit(i, &val, len * 8) {
313312
struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
314313

315-
/* GICD_ISPENDR0 SGI bits are WI */
316-
if (is_vgic_v2_sgi(vcpu, irq)) {
314+
/* GICD_ISPENDR0 SGI bits are WI when written from the guest. */
315+
if (is_vgic_v2_sgi(vcpu, irq) && !is_user) {
317316
vgic_put_irq(vcpu->kvm, irq);
318317
continue;
319318
}
320319

321320
raw_spin_lock_irqsave(&irq->irq_lock, flags);
322321

322+
/*
323+
* GICv2 SGIs are terribly broken. We can't restore
324+
* the source of the interrupt, so just pick the vcpu
325+
* itself as the source...
326+
*/
327+
if (is_vgic_v2_sgi(vcpu, irq))
328+
irq->source |= BIT(vcpu->vcpu_id);
329+
323330
if (irq->hw && vgic_irq_is_sgi(irq->intid)) {
324331
/* HW SGI? Ask the GIC to inject it */
325332
int err;
@@ -335,41 +342,26 @@ void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
335342
}
336343

337344
irq->pending_latch = true;
338-
if (irq->hw)
345+
if (irq->hw && !is_user)
339346
vgic_irq_set_phys_active(irq, true);
340347

341348
vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
342349
vgic_put_irq(vcpu->kvm, irq);
343350
}
344351
}
345352

353+
void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
354+
gpa_t addr, unsigned int len,
355+
unsigned long val)
356+
{
357+
__set_pending(vcpu, addr, len, val, false);
358+
}
359+
346360
int vgic_uaccess_write_spending(struct kvm_vcpu *vcpu,
347361
gpa_t addr, unsigned int len,
348362
unsigned long val)
349363
{
350-
u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
351-
int i;
352-
unsigned long flags;
353-
354-
for_each_set_bit(i, &val, len * 8) {
355-
struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
356-
357-
raw_spin_lock_irqsave(&irq->irq_lock, flags);
358-
irq->pending_latch = true;
359-
360-
/*
361-
* GICv2 SGIs are terribly broken. We can't restore
362-
* the source of the interrupt, so just pick the vcpu
363-
* itself as the source...
364-
*/
365-
if (is_vgic_v2_sgi(vcpu, irq))
366-
irq->source |= BIT(vcpu->vcpu_id);
367-
368-
vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
369-
370-
vgic_put_irq(vcpu->kvm, irq);
371-
}
372-
364+
__set_pending(vcpu, addr, len, val, true);
373365
return 0;
374366
}
375367

@@ -394,9 +386,9 @@ static void vgic_hw_irq_cpending(struct kvm_vcpu *vcpu, struct vgic_irq *irq)
394386
vgic_irq_set_phys_active(irq, false);
395387
}
396388

397-
void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
398-
gpa_t addr, unsigned int len,
399-
unsigned long val)
389+
static void __clear_pending(struct kvm_vcpu *vcpu,
390+
gpa_t addr, unsigned int len,
391+
unsigned long val, bool is_user)
400392
{
401393
u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
402394
int i;
@@ -405,14 +397,22 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
405397
for_each_set_bit(i, &val, len * 8) {
406398
struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
407399

408-
/* GICD_ICPENDR0 SGI bits are WI */
409-
if (is_vgic_v2_sgi(vcpu, irq)) {
400+
/* GICD_ICPENDR0 SGI bits are WI when written from the guest. */
401+
if (is_vgic_v2_sgi(vcpu, irq) && !is_user) {
410402
vgic_put_irq(vcpu->kvm, irq);
411403
continue;
412404
}
413405

414406
raw_spin_lock_irqsave(&irq->irq_lock, flags);
415407

408+
/*
409+
* More fun with GICv2 SGIs! If we're clearing one of them
410+
* from userspace, which source vcpu to clear? Let's not
411+
* even think of it, and blow the whole set.
412+
*/
413+
if (is_vgic_v2_sgi(vcpu, irq))
414+
irq->source = 0;
415+
416416
if (irq->hw && vgic_irq_is_sgi(irq->intid)) {
417417
/* HW SGI? Ask the GIC to clear its pending bit */
418418
int err;
@@ -427,7 +427,7 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
427427
continue;
428428
}
429429

430-
if (irq->hw)
430+
if (irq->hw && !is_user)
431431
vgic_hw_irq_cpending(vcpu, irq);
432432
else
433433
irq->pending_latch = false;
@@ -437,33 +437,18 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
437437
}
438438
}
439439

440+
void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
441+
gpa_t addr, unsigned int len,
442+
unsigned long val)
443+
{
444+
__clear_pending(vcpu, addr, len, val, false);
445+
}
446+
440447
int vgic_uaccess_write_cpending(struct kvm_vcpu *vcpu,
441448
gpa_t addr, unsigned int len,
442449
unsigned long val)
443450
{
444-
u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
445-
int i;
446-
unsigned long flags;
447-
448-
for_each_set_bit(i, &val, len * 8) {
449-
struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
450-
451-
raw_spin_lock_irqsave(&irq->irq_lock, flags);
452-
/*
453-
* More fun with GICv2 SGIs! If we're clearing one of them
454-
* from userspace, which source vcpu to clear? Let's not
455-
* even think of it, and blow the whole set.
456-
*/
457-
if (is_vgic_v2_sgi(vcpu, irq))
458-
irq->source = 0;
459-
460-
irq->pending_latch = false;
461-
462-
raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
463-
464-
vgic_put_irq(vcpu->kvm, irq);
465-
}
466-
451+
__clear_pending(vcpu, addr, len, val, true);
467452
return 0;
468453
}
469454

0 commit comments

Comments
 (0)