Skip to contentSkip to conversation

irqchip/gic-v3-its: Fix potential race condition in its_vlpi_prop_update()

PATCH Superseded Hagar Hemdan 2 participants 6 messages May 31, 2024

Subsystems (2)

v2 of 4 Superseded Latest is v4 →

lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 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. So instead of peppering the locking all over the place, we hoist the locking into its_irq_set_vcpu_affinity().

This bug was discovered and resolved using Coverity Static Analysis Security Testing (SAST) by Synopsys, Inc.

Fixes 015ec0386ab6 ("irqchip/gic-v3-its: Add VLPI configuration handling")

---
v2: moved the lock to its_irq_set_vcpu_affinity(). Only compile-tested, no access to HW.

---
 drivers/irqchip/irq-gic-v3-its.c | 65 +++++++++++++-------------------
 1 file changed, 27 insertions(+), 38 deletions(-)
drivers/irqchip/irq-gic-v3-its.c +27 -38
index 40ebf1726393..f9e824ad1523 100644
@@ -1846,28 +1846,22 @@ static int its_vlpi_map(struct irq_data *d, struct its_cmd_info *info)
 {
 	struct its_device *its_dev = irq_data_get_irq_chip_data(d);
 	u32 event = its_get_event_id(d);
-	int ret = 0;
 
 	if (!info->map)
 		return -EINVAL;
 
-	raw_spin_lock(&its_dev->event_map.vlpi_lock);
-
 	if (!its_dev->event_map.vm) {
 		struct its_vlpi_map *maps;
 
 		maps = kcalloc(its_dev->event_map.nr_lpis, sizeof(*maps),
 			       GFP_ATOMIC);
-		if (!maps) {
-			ret = -ENOMEM;
-			goto out;
-		}
+		if (!maps)
+			return -ENOMEM;
 
 		its_dev->event_map.vm = info->map->vm;
 		its_dev->event_map.vlpi_maps = maps;
 	} else if (its_dev->event_map.vm != info->map->vm) {
-		ret = -EINVAL;
-		goto out;
+		return -EINVAL;
 	}
 
 	/* 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)
 		its_dev->event_map.nr_vlpis++;
 	}
 
-out:
-	raw_spin_unlock(&its_dev->event_map.vlpi_lock);
-	return ret;
+	return 0;
 }
 
 static int its_vlpi_get(struct irq_data *d, struct its_cmd_info *info)
 {
 	struct its_device *its_dev = irq_data_get_irq_chip_data(d);
 	struct its_vlpi_map *map;
-	int ret = 0;
-
-	raw_spin_lock(&its_dev->event_map.vlpi_lock);
 
 	map = get_vlpi_map(d);
 
-	if (!its_dev->event_map.vm || !map) {
-		ret = -EINVAL;
-		goto out;
-	}
+	if (!its_dev->event_map.vm || !map)
+		return -EINVAL;
 
 	/* Copy our mapping information to the incoming request */
 	*info->map = *map;
 
-out:
-	raw_spin_unlock(&its_dev->event_map.vlpi_lock);
-	return ret;
+	return 0;
 }
 
 static int its_vlpi_unmap(struct irq_data *d)
 {
 	struct its_device *its_dev = irq_data_get_irq_chip_data(d);
 	u32 event = its_get_event_id(d);
-	int ret = 0;
 
-	raw_spin_lock(&its_dev->event_map.vlpi_lock);
-
-	if (!its_dev->event_map.vm || !irqd_is_forwarded_to_vcpu(d)) {
-		ret = -EINVAL;
-		goto out;
-	}
+	if (!its_dev->event_map.vm || !irqd_is_forwarded_to_vcpu(d))
+		return -EINVAL;
 
 	/* Drop the virtual mapping */
 	its_send_discard(its_dev, event);
@@ -1962,9 +1942,7 @@ static int its_vlpi_unmap(struct irq_data *d)
 		kfree(its_dev->event_map.vlpi_maps);
 	}
 
-out:
-	raw_spin_unlock(&its_dev->event_map.vlpi_lock);
-	return ret;
+	return 0;
 }
 
 static int its_vlpi_prop_update(struct irq_data *d, struct its_cmd_info *info)
@@ -1987,29 +1965,40 @@ static int its_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
 {
 	struct its_device *its_dev = irq_data_get_irq_chip_data(d);
 	struct its_cmd_info *info = vcpu_info;
+	int ret;
 
 	/* Need a v4 ITS */
 	if (!is_v4(its_dev->its))
 		return -EINVAL;
 
+	raw_spin_lock(&its_dev->event_map.vlpi_lock);
+
 	/* Unmap request? */
-	if (!info)
-		return its_vlpi_unmap(d);
+	if (!info) {
+		ret = its_vlpi_unmap(d);
+		goto out;
+	}
 
 	switch (info->cmd_type) {
 	case MAP_VLPI:
-		return its_vlpi_map(d, info);
+		ret = its_vlpi_map(d, info);
+		break;
 
 	case GET_VLPI:
-		return its_vlpi_get(d, info);
+		ret = its_vlpi_get(d, info);
+		break;
 
 	case PROP_UPDATE_VLPI:
 	case PROP_UPDATE_AND_INV_VLPI:
-		return its_vlpi_prop_update(d, info);
+		ret = its_vlpi_prop_update(d, info);
+		break;
 
 	default:
-		return -EINVAL;
+		ret = -EINVAL;
 	}
+out:
+	raw_spin_unlock(&its_dev->event_map.vlpi_lock);
+	return ret;
 }
 
 static struct irq_chip its_irq_chip = {
Signature · 1 line
2.40.1
maintainer
#1 lore raw
Quoted 8 lines · Hagar Hemdan

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. So instead of peppering the locking all over the place, we hoist the locking into its_irq_set_vcpu_affinity().

Quoted 5 lines

This bug was discovered and resolved using Coverity Static Analysis Security Testing (SAST) by Synopsys, Inc.

Fixes 015ec0386ab6 ("irqchip/gic-v3-its: Add VLPI configuration handling")

Given that you have lifted both my proposed patch and part of my reply as a commit message, you may at least credit me with a
Suggested-by: tag. Not to mention that the blatant advertising doesn't really apply in this case.

Quoted 3 lines

---
v2: moved the lock to its_irq_set_vcpu_affinity(). Only compile-tested, no access to HW.

Was the initial patch tested at all?

	M.
Signature · 1 line
Without deviation from the norm, progress is not possible.
#2 lore raw
Quoted 13 lines · Marc Zyngier
Quoted 11 lines · Hagar Hemdan

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. So instead of peppering the locking all over the place, we hoist the locking into its_irq_set_vcpu_affinity().

This bug was discovered and resolved using Coverity Static Analysis Security Testing (SAST) by Synopsys, Inc.

Quoted 7 lines
Quoted 2 lines
Fixes 015ec0386ab6 ("irqchip/gic-v3-its: Add VLPI configuration handling")

Given that you have lifted both my proposed patch and part of my reply as a commit message, you may at least credit me with a
Suggested-by: tag. Not to mention that the blatant advertising doesn't really apply in this case.

ok, I will add this tag in rev3 and we need to add that disclaimer as it is a commercial tool. thanks!

Quoted 6 lines
Quoted 4 lines

---
v2: moved the lock to its_irq_set_vcpu_affinity(). Only compile-tested, no access to HW.

Was the initial patch tested at all?

No, the initial one was only compile tested, forgot to add that hint in the first patch.

Quoted 5 lines
	M.
Signature · 1 line
Without deviation from the norm, progress is not possible.
maintainer
#3 lore raw
Quoted 18 lines · Hagar Hemdan
Quoted 16 lines · Marc Zyngier
Quoted 13 lines · Hagar Hemdan

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. So instead of peppering the locking all over the place, we hoist the locking into its_irq_set_vcpu_affinity().

This bug was discovered and resolved using Coverity Static Analysis Security Testing (SAST) by Synopsys, Inc.

Fixes 015ec0386ab6 ("irqchip/gic-v3-its: Add VLPI configuration handling")
Quoted 7 lines
Quoted 4 lines

Given that you have lifted both my proposed patch and part of my reply as a commit message, you may at least credit me with a
Suggested-by: tag. Not to mention that the blatant advertising doesn't really apply in this case.

ok, I will add this tag in rev3 and we need to add that disclaimer as it is a commercial tool. thanks!

Sorry, but I'm not bound by this requirement. I'm happy to credit *you* for reporting a defect, but certainly not a tool that hasn't "resolved" anything, despite what the message says.

	M.
Signature · 1 line
Without deviation from the norm, progress is not possible.
#4 lore raw
Quoted 25 lines · Marc Zyngier
Quoted 23 lines · Hagar Hemdan
Quoted 20 lines · Marc Zyngier
Quoted 8 lines · Hagar Hemdan

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. So instead of peppering the locking all over the place, we hoist the locking into its_irq_set_vcpu_affinity().

Quoted 5 lines

This bug was discovered and resolved using Coverity Static Analysis Security Testing (SAST) by Synopsys, Inc.

Fixes 015ec0386ab6 ("irqchip/gic-v3-its: Add VLPI configuration handling")

Given that you have lifted both my proposed patch and part of my reply as a commit message, you may at least credit me with a
Suggested-by: tag. Not to mention that the blatant advertising doesn't really apply in this case.

Quoted 6 lines
Quoted 2 lines

ok, I will add this tag in rev3 and we need to add that disclaimer as it is a commercial tool. thanks!

Sorry, but I'm not bound by this requirement. I'm happy to credit *you* for reporting a defect, but certainly not a tool that hasn't "resolved" anything, despite what the message says.

Ok, I will drop the resolved part as the modified fix is suggested by you. Is it ok?

Quoted 10 lines
	M.
Signature · 6 lines
Without deviation from the norm, progress is not possible.

_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
maintainer
#5 lore raw
Quoted 30 lines · Hagar Hemdan
Quoted 28 lines · Marc Zyngier
Quoted 25 lines · Hagar Hemdan
Quoted 13 lines · Marc Zyngier
Quoted 11 lines · Hagar Hemdan

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. So instead of peppering the locking all over the place, we hoist the locking into its_irq_set_vcpu_affinity().

This bug was discovered and resolved using Coverity Static Analysis Security Testing (SAST) by Synopsys, Inc.

Quoted 7 lines
Quoted 2 lines
Fixes 015ec0386ab6 ("irqchip/gic-v3-its: Add VLPI configuration handling")

Given that you have lifted both my proposed patch and part of my reply as a commit message, you may at least credit me with a
Suggested-by: tag. Not to mention that the blatant advertising doesn't really apply in this case.

ok, I will add this tag in rev3 and we need to add that disclaimer as it is a commercial tool. thanks!

Quoted 6 lines
Quoted 3 lines

Sorry, but I'm not bound by this requirement. I'm happy to credit *you* for reporting a defect, but certainly not a tool that hasn't "resolved" anything, despite what the message says.

Ok, I will drop the resolved part as the modified fix is suggested by you. Is it ok?

Yes, this seems fair to me.

Thanks again,

	M.
Signature · 1 line
Without deviation from the norm, progress is not possible.