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: 015ec0386ab6 ("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

authored by Hagar Hemdan and committed by Thomas Gleixner b97e8a2f e306a894

+12 -32
+12 -32
drivers/irqchip/irq-gic-v3-its.c
··· 1846 1846 { 1847 1847 struct its_device *its_dev = irq_data_get_irq_chip_data(d); 1848 1848 u32 event = its_get_event_id(d); 1849 - int ret = 0; 1850 1849 1851 1850 if (!info->map) 1852 1851 return -EINVAL; 1853 - 1854 - raw_spin_lock(&its_dev->event_map.vlpi_lock); 1855 1852 1856 1853 if (!its_dev->event_map.vm) { 1857 1854 struct its_vlpi_map *maps; 1858 1855 1859 1856 maps = kcalloc(its_dev->event_map.nr_lpis, sizeof(*maps), 1860 1857 GFP_ATOMIC); 1861 - if (!maps) { 1862 - ret = -ENOMEM; 1863 - goto out; 1864 - } 1858 + if (!maps) 1859 + return -ENOMEM; 1865 1860 1866 1861 its_dev->event_map.vm = info->map->vm; 1867 1862 its_dev->event_map.vlpi_maps = maps; 1868 1863 } else if (its_dev->event_map.vm != info->map->vm) { 1869 - ret = -EINVAL; 1870 - goto out; 1864 + return -EINVAL; 1871 1865 } 1872 1866 1873 1867 /* Get our private copy of the mapping information */ ··· 1893 1899 its_dev->event_map.nr_vlpis++; 1894 1900 } 1895 1901 1896 - out: 1897 - raw_spin_unlock(&its_dev->event_map.vlpi_lock); 1898 - return ret; 1902 + return 0; 1899 1903 } 1900 1904 1901 1905 static int its_vlpi_get(struct irq_data *d, struct its_cmd_info *info) 1902 1906 { 1903 1907 struct its_device *its_dev = irq_data_get_irq_chip_data(d); 1904 1908 struct its_vlpi_map *map; 1905 - int ret = 0; 1906 - 1907 - raw_spin_lock(&its_dev->event_map.vlpi_lock); 1908 1909 1909 1910 map = get_vlpi_map(d); 1910 1911 1911 - if (!its_dev->event_map.vm || !map) { 1912 - ret = -EINVAL; 1913 - goto out; 1914 - } 1912 + if (!its_dev->event_map.vm || !map) 1913 + return -EINVAL; 1915 1914 1916 1915 /* Copy our mapping information to the incoming request */ 1917 1916 *info->map = *map; 1918 1917 1919 - out: 1920 - raw_spin_unlock(&its_dev->event_map.vlpi_lock); 1921 - return ret; 1918 + return 0; 1922 1919 } 1923 1920 1924 1921 static int its_vlpi_unmap(struct irq_data *d) 1925 1922 { 1926 1923 struct its_device *its_dev = irq_data_get_irq_chip_data(d); 1927 1924 u32 event = its_get_event_id(d); 1928 - int ret = 0; 1929 1925 1930 - raw_spin_lock(&its_dev->event_map.vlpi_lock); 1931 - 1932 - if (!its_dev->event_map.vm || !irqd_is_forwarded_to_vcpu(d)) { 1933 - ret = -EINVAL; 1934 - goto out; 1935 - } 1926 + if (!its_dev->event_map.vm || !irqd_is_forwarded_to_vcpu(d)) 1927 + return -EINVAL; 1936 1928 1937 1929 /* Drop the virtual mapping */ 1938 1930 its_send_discard(its_dev, event); ··· 1942 1962 kfree(its_dev->event_map.vlpi_maps); 1943 1963 } 1944 1964 1945 - out: 1946 - raw_spin_unlock(&its_dev->event_map.vlpi_lock); 1947 - return ret; 1965 + return 0; 1948 1966 } 1949 1967 1950 1968 static int its_vlpi_prop_update(struct irq_data *d, struct its_cmd_info *info) ··· 1969 1991 /* Need a v4 ITS */ 1970 1992 if (!is_v4(its_dev->its)) 1971 1993 return -EINVAL; 1994 + 1995 + guard(raw_spinlock_irq)(&its_dev->event_map.vlpi_lock); 1972 1996 1973 1997 /* Unmap request? */ 1974 1998 if (!info)