|
Alexander Graf |
17a802 |
From: Christoffer Dall <cdall@linaro.org>
|
|
Alexander Graf |
17a802 |
Date: Tue, 16 May 2017 12:41:18 +0200
|
|
Alexander Graf |
17a802 |
Subject: KVM: arm/arm64: Disallow userspace control of in-kernel IRQ lines
|
|
Alexander Graf |
17a802 |
Patch-mainline: v4.13-rc1
|
|
Alexander Graf |
17a802 |
Git-commit: cb3f0ad881a6cee39c6a652b4aa4f12f341d98f0
|
|
Alexander Graf |
17a802 |
References: bsc#1077761
|
|
Alexander Graf |
17a802 |
|
|
Alexander Graf |
17a802 |
When injecting an IRQ to the VGIC, you now have to present an owner
|
|
Alexander Graf |
17a802 |
token for that IRQ line to show that you are the owner of that line.
|
|
Alexander Graf |
17a802 |
|
|
Alexander Graf |
17a802 |
IRQ lines driven from userspace or via an irqfd do not have an owner and
|
|
Alexander Graf |
17a802 |
will simply pass a NULL pointer.
|
|
Alexander Graf |
17a802 |
|
|
Alexander Graf |
17a802 |
Also get rid of the unused kvm_vgic_inject_mapped_irq prototype.
|
|
Alexander Graf |
17a802 |
|
|
Alexander Graf |
17a802 |
Signed-off-by: Christoffer Dall <cdall@linaro.org>
|
|
Alexander Graf |
17a802 |
Acked-by: Marc Zyngier <marc.zyngier@arm.com>
|
|
Alexander Graf |
17a802 |
Acked-by: Alexander Graf <agraf@suse.de>
|
|
Alexander Graf |
17a802 |
---
|
|
Alexander Graf |
17a802 |
include/kvm/arm_vgic.h | 4 +---
|
|
Alexander Graf |
17a802 |
virt/kvm/arm/arch_timer.c | 3 ++-
|
|
Alexander Graf |
17a802 |
virt/kvm/arm/arm.c | 4 ++--
|
|
Alexander Graf |
17a802 |
virt/kvm/arm/pmu.c | 3 ++-
|
|
Alexander Graf |
17a802 |
virt/kvm/arm/vgic/vgic-irqfd.c | 2 +-
|
|
Alexander Graf |
17a802 |
virt/kvm/arm/vgic/vgic.c | 15 +++++++++++----
|
|
Alexander Graf |
17a802 |
6 files changed, 19 insertions(+), 12 deletions(-)
|
|
Alexander Graf |
17a802 |
|
|
Alexander Graf |
17a802 |
--- a/include/kvm/arm_vgic.h
|
|
Alexander Graf |
17a802 |
+++ b/include/kvm/arm_vgic.h
|
|
Alexander Graf |
17a802 |
@@ -303,9 +303,7 @@
|
|
Alexander Graf |
17a802 |
void kvm_vgic_init_cpu_hardware(void);
|
|
Alexander Graf |
17a802 |
|
|
Alexander Graf |
17a802 |
int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
|
|
Alexander Graf |
17a802 |
- bool level);
|
|
Alexander Graf |
17a802 |
-int kvm_vgic_inject_mapped_irq(struct kvm *kvm, int cpuid, unsigned int intid,
|
|
Alexander Graf |
17a802 |
- bool level);
|
|
Alexander Graf |
17a802 |
+ bool level, void *owner);
|
|
Alexander Graf |
17a802 |
int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, u32 virt_irq, u32 phys_irq);
|
|
Alexander Graf |
17a802 |
int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq);
|
|
Alexander Graf |
17a802 |
bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
|
|
Alexander Graf |
17a802 |
--- a/virt/kvm/arm/arch_timer.c
|
|
Alexander Graf |
17a802 |
+++ b/virt/kvm/arm/arch_timer.c
|
|
Alexander Graf |
17a802 |
@@ -226,7 +226,8 @@
|
|
Alexander Graf |
17a802 |
if (likely(irqchip_in_kernel(vcpu->kvm))) {
|
|
Alexander Graf |
17a802 |
ret = kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id,
|
|
Alexander Graf |
17a802 |
timer_ctx->irq.irq,
|
|
Alexander Graf |
17a802 |
- timer_ctx->irq.level);
|
|
Alexander Graf |
17a802 |
+ timer_ctx->irq.level,
|
|
Alexander Graf |
17a802 |
+ timer_ctx);
|
|
Alexander Graf |
17a802 |
WARN_ON(ret);
|
|
Alexander Graf |
17a802 |
}
|
|
Alexander Graf |
17a802 |
}
|
|
Alexander Graf |
17a802 |
--- a/virt/kvm/arm/arm.c
|
|
Alexander Graf |
17a802 |
+++ b/virt/kvm/arm/arm.c
|
|
Alexander Graf |
17a802 |
@@ -832,7 +832,7 @@
|
|
Alexander Graf |
17a802 |
if (irq_num < VGIC_NR_SGIS || irq_num >= VGIC_NR_PRIVATE_IRQS)
|
|
Alexander Graf |
17a802 |
return -EINVAL;
|
|
Alexander Graf |
17a802 |
|
|
Alexander Graf |
17a802 |
- return kvm_vgic_inject_irq(kvm, vcpu->vcpu_id, irq_num, level);
|
|
Alexander Graf |
17a802 |
+ return kvm_vgic_inject_irq(kvm, vcpu->vcpu_id, irq_num, level, NULL);
|
|
Alexander Graf |
17a802 |
case KVM_ARM_IRQ_TYPE_SPI:
|
|
Alexander Graf |
17a802 |
if (!irqchip_in_kernel(kvm))
|
|
Alexander Graf |
17a802 |
return -ENXIO;
|
|
Alexander Graf |
17a802 |
@@ -840,7 +840,7 @@
|
|
Alexander Graf |
17a802 |
if (irq_num < VGIC_NR_PRIVATE_IRQS)
|
|
Alexander Graf |
17a802 |
return -EINVAL;
|
|
Alexander Graf |
17a802 |
|
|
Alexander Graf |
17a802 |
- return kvm_vgic_inject_irq(kvm, 0, irq_num, level);
|
|
Alexander Graf |
17a802 |
+ return kvm_vgic_inject_irq(kvm, 0, irq_num, level, NULL);
|
|
Alexander Graf |
17a802 |
}
|
|
Alexander Graf |
17a802 |
|
|
Alexander Graf |
17a802 |
return -EINVAL;
|
|
Alexander Graf |
17a802 |
--- a/virt/kvm/arm/pmu.c
|
|
Alexander Graf |
17a802 |
+++ b/virt/kvm/arm/pmu.c
|
|
Alexander Graf |
17a802 |
@@ -215,7 +215,8 @@
|
|
Alexander Graf |
17a802 |
|
|
Alexander Graf |
17a802 |
if (likely(irqchip_in_kernel(vcpu->kvm))) {
|
|
Alexander Graf |
17a802 |
int ret = kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id,
|
|
Alexander Graf |
17a802 |
- pmu->irq_num, overflow);
|
|
Alexander Graf |
17a802 |
+ pmu->irq_num, overflow,
|
|
Alexander Graf |
17a802 |
+ &vcpu->arch.pmu);
|
|
Alexander Graf |
17a802 |
WARN_ON(ret);
|
|
Alexander Graf |
17a802 |
}
|
|
Alexander Graf |
17a802 |
}
|
|
Alexander Graf |
17a802 |
--- a/virt/kvm/arm/vgic/vgic-irqfd.c
|
|
Alexander Graf |
17a802 |
+++ b/virt/kvm/arm/vgic/vgic-irqfd.c
|
|
Alexander Graf |
17a802 |
@@ -34,7 +34,7 @@
|
|
Alexander Graf |
17a802 |
|
|
Alexander Graf |
17a802 |
if (!vgic_valid_spi(kvm, spi_id))
|
|
Alexander Graf |
17a802 |
return -EINVAL;
|
|
Alexander Graf |
17a802 |
- return kvm_vgic_inject_irq(kvm, 0, spi_id, level);
|
|
Alexander Graf |
17a802 |
+ return kvm_vgic_inject_irq(kvm, 0, spi_id, level, NULL);
|
|
Alexander Graf |
17a802 |
}
|
|
Alexander Graf |
17a802 |
|
|
Alexander Graf |
17a802 |
/**
|
|
Alexander Graf |
17a802 |
--- a/virt/kvm/arm/vgic/vgic.c
|
|
Alexander Graf |
17a802 |
+++ b/virt/kvm/arm/vgic/vgic.c
|
|
Alexander Graf |
17a802 |
@@ -235,10 +235,14 @@
|
|
Alexander Graf |
17a802 |
|
|
Alexander Graf |
17a802 |
/*
|
|
Alexander Graf |
17a802 |
* Only valid injection if changing level for level-triggered IRQs or for a
|
|
Alexander Graf |
17a802 |
- * rising edge.
|
|
Alexander Graf |
17a802 |
+ * rising edge, and in-kernel connected IRQ lines can only be controlled by
|
|
Alexander Graf |
17a802 |
+ * their owner.
|
|
Alexander Graf |
17a802 |
*/
|
|
Alexander Graf |
17a802 |
-static bool vgic_validate_injection(struct vgic_irq *irq, bool level)
|
|
Alexander Graf |
17a802 |
+static bool vgic_validate_injection(struct vgic_irq *irq, bool level, void *owner)
|
|
Alexander Graf |
17a802 |
{
|
|
Alexander Graf |
17a802 |
+ if (irq->owner != owner)
|
|
Alexander Graf |
17a802 |
+ return false;
|
|
Alexander Graf |
17a802 |
+
|
|
Alexander Graf |
17a802 |
switch (irq->config) {
|
|
Alexander Graf |
17a802 |
case VGIC_CONFIG_LEVEL:
|
|
Alexander Graf |
17a802 |
return irq->line_level != level;
|
|
Alexander Graf |
17a802 |
@@ -350,13 +354,16 @@
|
|
Alexander Graf |
17a802 |
* false: to ignore the call
|
|
Alexander Graf |
17a802 |
* Level-sensitive true: raise the input signal
|
|
Alexander Graf |
17a802 |
* false: lower the input signal
|
|
Alexander Graf |
17a802 |
+ * @owner: The opaque pointer to the owner of the IRQ being raised to verify
|
|
Alexander Graf |
17a802 |
+ * that the caller is allowed to inject this IRQ. Userspace
|
|
Alexander Graf |
17a802 |
+ * injections will have owner == NULL.
|
|
Alexander Graf |
17a802 |
*
|
|
Alexander Graf |
17a802 |
* The VGIC is not concerned with devices being active-LOW or active-HIGH for
|
|
Alexander Graf |
17a802 |
* level-sensitive interrupts. You can think of the level parameter as 1
|
|
Alexander Graf |
17a802 |
* being HIGH and 0 being LOW and all devices being active-HIGH.
|
|
Alexander Graf |
17a802 |
*/
|
|
Alexander Graf |
17a802 |
int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
|
|
Alexander Graf |
17a802 |
- bool level)
|
|
Alexander Graf |
17a802 |
+ bool level, void *owner)
|
|
Alexander Graf |
17a802 |
{
|
|
Alexander Graf |
17a802 |
struct kvm_vcpu *vcpu;
|
|
Alexander Graf |
17a802 |
struct vgic_irq *irq;
|
|
Alexander Graf |
17a802 |
@@ -378,7 +385,7 @@
|
|
Alexander Graf |
17a802 |
|
|
Alexander Graf |
17a802 |
spin_lock(&irq->irq_lock);
|
|
Alexander Graf |
17a802 |
|
|
Alexander Graf |
17a802 |
- if (!vgic_validate_injection(irq, level)) {
|
|
Alexander Graf |
17a802 |
+ if (!vgic_validate_injection(irq, level, owner)) {
|
|
Alexander Graf |
17a802 |
/* Nothing to see here, move along... */
|
|
Alexander Graf |
17a802 |
spin_unlock(&irq->irq_lock);
|
|
Alexander Graf |
17a802 |
vgic_put_irq(kvm, irq);
|