perf/smmuv3: Validate group size
authorRobin Murphy <robin.murphy@arm.com>
Thu, 1 Aug 2019 15:22:44 +0000 (16:22 +0100)
committerWill Deacon <will@kernel.org>
Tue, 27 Aug 2019 18:37:04 +0000 (19:37 +0100)
Ensure that a group will actually fit into the available counters.

Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Signed-off-by: Will Deacon <will@kernel.org>
drivers/perf/arm_smmuv3_pmu.c

index da71c74..c65c197 100644 (file)
@@ -323,6 +323,7 @@ static int smmu_pmu_event_init(struct perf_event *event)
        struct smmu_pmu *smmu_pmu = to_smmu_pmu(event->pmu);
        struct device *dev = smmu_pmu->dev;
        struct perf_event *sibling;
+       int group_num_events = 1;
        u16 event_id;
 
        if (event->attr.type != event->pmu->type)
@@ -347,18 +348,23 @@ static int smmu_pmu_event_init(struct perf_event *event)
        }
 
        /* Don't allow groups with mixed PMUs, except for s/w events */
-       if (event->group_leader->pmu != event->pmu &&
-           !is_software_event(event->group_leader)) {
-               dev_dbg(dev, "Can't create mixed PMU group\n");
-               return -EINVAL;
+       if (!is_software_event(event->group_leader)) {
+               if (event->group_leader->pmu != event->pmu)
+                       return -EINVAL;
+
+               if (++group_num_events > smmu_pmu->num_counters)
+                       return -EINVAL;
        }
 
        for_each_sibling_event(sibling, event->group_leader) {
-               if (sibling->pmu != event->pmu &&
-                   !is_software_event(sibling)) {
-                       dev_dbg(dev, "Can't create mixed PMU group\n");
+               if (is_software_event(sibling))
+                       continue;
+
+               if (sibling->pmu != event->pmu)
+                       return -EINVAL;
+
+               if (++group_num_events > smmu_pmu->num_counters)
                        return -EINVAL;
-               }
        }
 
        hwc->idx = -1;