Skip to content

Commit 1442ee0

Browse files
Marc ZyngierKAGA-KOKO
authored andcommitted
irqchip/gic-v4: Don't allow a VMOVP on a dying VPE
Kunkun Jiang reported that there is a small window of opportunity for userspace to force a change of affinity for a VPE while the VPE has already been unmapped, but the corresponding doorbell interrupt still visible in /proc/irq/. Plug the race by checking the value of vmapp_count, which tracks whether the VPE is mapped ot not, and returning an error in this case. This involves making vmapp_count common to both GICv4.1 and its v4.0 ancestor. Fixes: 64edfaa ("irqchip/gic-v4.1: Implement the v4.1 flavour of VMAPP") Reported-by: Kunkun Jiang <[email protected]> Signed-off-by: Marc Zyngier <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Cc: [email protected] Link: https://lore.kernel.org/r/[email protected] Link: https://lore.kernel.org/all/[email protected]
1 parent 6eabf65 commit 1442ee0

File tree

2 files changed

+15
-7
lines changed

2 files changed

+15
-7
lines changed

drivers/irqchip/irq-gic-v3-its.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -797,8 +797,8 @@ static struct its_vpe *its_build_vmapp_cmd(struct its_node *its,
797797
its_encode_valid(cmd, desc->its_vmapp_cmd.valid);
798798

799799
if (!desc->its_vmapp_cmd.valid) {
800+
alloc = !atomic_dec_return(&desc->its_vmapp_cmd.vpe->vmapp_count);
800801
if (is_v4_1(its)) {
801-
alloc = !atomic_dec_return(&desc->its_vmapp_cmd.vpe->vmapp_count);
802802
its_encode_alloc(cmd, alloc);
803803
/*
804804
* Unmapping a VPE is self-synchronizing on GICv4.1,
@@ -817,13 +817,13 @@ static struct its_vpe *its_build_vmapp_cmd(struct its_node *its,
817817
its_encode_vpt_addr(cmd, vpt_addr);
818818
its_encode_vpt_size(cmd, LPI_NRBITS - 1);
819819

820+
alloc = !atomic_fetch_inc(&desc->its_vmapp_cmd.vpe->vmapp_count);
821+
820822
if (!is_v4_1(its))
821823
goto out;
822824

823825
vconf_addr = virt_to_phys(page_address(desc->its_vmapp_cmd.vpe->its_vm->vprop_page));
824826

825-
alloc = !atomic_fetch_inc(&desc->its_vmapp_cmd.vpe->vmapp_count);
826-
827827
its_encode_alloc(cmd, alloc);
828828

829829
/*
@@ -3806,6 +3806,13 @@ static int its_vpe_set_affinity(struct irq_data *d,
38063806
struct cpumask *table_mask;
38073807
unsigned long flags;
38083808

3809+
/*
3810+
* Check if we're racing against a VPE being destroyed, for
3811+
* which we don't want to allow a VMOVP.
3812+
*/
3813+
if (!atomic_read(&vpe->vmapp_count))
3814+
return -EINVAL;
3815+
38093816
/*
38103817
* Changing affinity is mega expensive, so let's be as lazy as
38113818
* we can and only do it if we really have to. Also, if mapped
@@ -4463,9 +4470,8 @@ static int its_vpe_init(struct its_vpe *vpe)
44634470
raw_spin_lock_init(&vpe->vpe_lock);
44644471
vpe->vpe_id = vpe_id;
44654472
vpe->vpt_page = vpt_page;
4466-
if (gic_rdists->has_rvpeid)
4467-
atomic_set(&vpe->vmapp_count, 0);
4468-
else
4473+
atomic_set(&vpe->vmapp_count, 0);
4474+
if (!gic_rdists->has_rvpeid)
44694475
vpe->vpe_proxy_event = -1;
44704476

44714477
return 0;

include/linux/irqchip/arm-gic-v4.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,12 @@ struct its_vpe {
6666
bool enabled;
6767
bool group;
6868
} sgi_config[16];
69-
atomic_t vmapp_count;
7069
};
7170
};
7271

72+
/* Track the VPE being mapped */
73+
atomic_t vmapp_count;
74+
7375
/*
7476
* Ensures mutual exclusion between affinity setting of the
7577
* vPE and vLPI operations using vpe->col_idx.

0 commit comments

Comments
 (0)