Skip to content

Commit b97e8a2

Browse files
hagarhemKAGA-KOKO
authored andcommitted
irqchip/gic-v3-its: Fix potential race condition in its_vlpi_prop_update()
its_vlpi_prop_update() calls lpi_write_config() which obtains the mapping information for a VLPI without lock held. So it could race with its_vlpi_unmap(). Since all calls from its_irq_set_vcpu_affinity() require the same lock to be held, hoist the locking there instead of sprinkling the locking all over the place. This bug was discovered using Coverity Static Analysis Security Testing (SAST) by Synopsys, Inc. [ tglx: Use guard() instead of goto ] Fixes: 015ec03 ("irqchip/gic-v3-its: Add VLPI configuration handling") Suggested-by: Marc Zyngier <maz@kernel.org> Signed-off-by: Hagar Hemdan <hagarhem@amazon.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: stable@vger.kernel.org Reviewed-by: Marc Zyngier <maz@kernel.org> Link: https://lore.kernel.org/r/20240531162144.28650-1-hagarhem@amazon.com
1 parent e306a89 commit b97e8a2

File tree

1 file changed

+12
-32
lines changed

1 file changed

+12
-32
lines changed

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

Lines changed: 12 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1846,28 +1846,22 @@ static int its_vlpi_map(struct irq_data *d, struct its_cmd_info *info)
18461846
{
18471847
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
18481848
u32 event = its_get_event_id(d);
1849-
int ret = 0;
18501849

18511850
if (!info->map)
18521851
return -EINVAL;
18531852

1854-
raw_spin_lock(&its_dev->event_map.vlpi_lock);
1855-
18561853
if (!its_dev->event_map.vm) {
18571854
struct its_vlpi_map *maps;
18581855

18591856
maps = kcalloc(its_dev->event_map.nr_lpis, sizeof(*maps),
18601857
GFP_ATOMIC);
1861-
if (!maps) {
1862-
ret = -ENOMEM;
1863-
goto out;
1864-
}
1858+
if (!maps)
1859+
return -ENOMEM;
18651860

18661861
its_dev->event_map.vm = info->map->vm;
18671862
its_dev->event_map.vlpi_maps = maps;
18681863
} else if (its_dev->event_map.vm != info->map->vm) {
1869-
ret = -EINVAL;
1870-
goto out;
1864+
return -EINVAL;
18711865
}
18721866

18731867
/* Get our private copy of the mapping information */
@@ -1899,46 +1893,32 @@ static int its_vlpi_map(struct irq_data *d, struct its_cmd_info *info)
18991893
its_dev->event_map.nr_vlpis++;
19001894
}
19011895

1902-
out:
1903-
raw_spin_unlock(&its_dev->event_map.vlpi_lock);
1904-
return ret;
1896+
return 0;
19051897
}
19061898

19071899
static int its_vlpi_get(struct irq_data *d, struct its_cmd_info *info)
19081900
{
19091901
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
19101902
struct its_vlpi_map *map;
1911-
int ret = 0;
1912-
1913-
raw_spin_lock(&its_dev->event_map.vlpi_lock);
19141903

19151904
map = get_vlpi_map(d);
19161905

1917-
if (!its_dev->event_map.vm || !map) {
1918-
ret = -EINVAL;
1919-
goto out;
1920-
}
1906+
if (!its_dev->event_map.vm || !map)
1907+
return -EINVAL;
19211908

19221909
/* Copy our mapping information to the incoming request */
19231910
*info->map = *map;
19241911

1925-
out:
1926-
raw_spin_unlock(&its_dev->event_map.vlpi_lock);
1927-
return ret;
1912+
return 0;
19281913
}
19291914

19301915
static int its_vlpi_unmap(struct irq_data *d)
19311916
{
19321917
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
19331918
u32 event = its_get_event_id(d);
1934-
int ret = 0;
1935-
1936-
raw_spin_lock(&its_dev->event_map.vlpi_lock);
19371919

1938-
if (!its_dev->event_map.vm || !irqd_is_forwarded_to_vcpu(d)) {
1939-
ret = -EINVAL;
1940-
goto out;
1941-
}
1920+
if (!its_dev->event_map.vm || !irqd_is_forwarded_to_vcpu(d))
1921+
return -EINVAL;
19421922

19431923
/* Drop the virtual mapping */
19441924
its_send_discard(its_dev, event);
@@ -1962,9 +1942,7 @@ static int its_vlpi_unmap(struct irq_data *d)
19621942
kfree(its_dev->event_map.vlpi_maps);
19631943
}
19641944

1965-
out:
1966-
raw_spin_unlock(&its_dev->event_map.vlpi_lock);
1967-
return ret;
1945+
return 0;
19681946
}
19691947

19701948
static int its_vlpi_prop_update(struct irq_data *d, struct its_cmd_info *info)
@@ -1992,6 +1970,8 @@ static int its_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
19921970
if (!is_v4(its_dev->its))
19931971
return -EINVAL;
19941972

1973+
guard(raw_spinlock_irq)(&its_dev->event_map.vlpi_lock);
1974+
19951975
/* Unmap request? */
19961976
if (!info)
19971977
return its_vlpi_unmap(d);

0 commit comments

Comments
 (0)