Skip to content

Commit 0933840

Browse files
Jiri OlsaIngo Molnar
authored andcommitted
perf/core: Protect PMU device removal with a 'pmu_bus_running' check, to fix CONFIG_DEBUG_TEST_DRIVER_REMOVE=y kernel panic
CAI Qian reported a crash in the PMU uncore device removal code, enabled by the CONFIG_DEBUG_TEST_DRIVER_REMOVE=y option: https://marc.info/?l=linux-kernel&m=147688837328451 The reason for the crash is that perf_pmu_unregister() tries to remove a PMU device which is not added at this point. We add PMU devices only after pmu_bus is registered, which happens in the perf_event_sysfs_init() call and sets the 'pmu_bus_running' flag. The fix is to get the 'pmu_bus_running' flag state at the point the PMU is taken out of the PMU list and remove the device later only if it's set. Reported-by: CAI Qian <[email protected]> Tested-by: CAI Qian <[email protected]> Signed-off-by: Jiri Olsa <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Cc: Alexander Shishkin <[email protected]> Cc: Arnaldo Carvalho de Melo <[email protected]> Cc: Greg Kroah-Hartman <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: Kan Liang <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Rob Herring <[email protected]> Cc: Thomas Gleixner <[email protected]> Link: http://lkml.kernel.org/r/20161020111011.GA13361@krava Signed-off-by: Ingo Molnar <[email protected]>
1 parent 889882b commit 0933840

File tree

1 file changed

+9
-4
lines changed

1 file changed

+9
-4
lines changed

kernel/events/core.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8855,7 +8855,10 @@ EXPORT_SYMBOL_GPL(perf_pmu_register);
88558855

88568856
void perf_pmu_unregister(struct pmu *pmu)
88578857
{
8858+
int remove_device;
8859+
88588860
mutex_lock(&pmus_lock);
8861+
remove_device = pmu_bus_running;
88598862
list_del_rcu(&pmu->entry);
88608863
mutex_unlock(&pmus_lock);
88618864

@@ -8869,10 +8872,12 @@ void perf_pmu_unregister(struct pmu *pmu)
88698872
free_percpu(pmu->pmu_disable_count);
88708873
if (pmu->type >= PERF_TYPE_MAX)
88718874
idr_remove(&pmu_idr, pmu->type);
8872-
if (pmu->nr_addr_filters)
8873-
device_remove_file(pmu->dev, &dev_attr_nr_addr_filters);
8874-
device_del(pmu->dev);
8875-
put_device(pmu->dev);
8875+
if (remove_device) {
8876+
if (pmu->nr_addr_filters)
8877+
device_remove_file(pmu->dev, &dev_attr_nr_addr_filters);
8878+
device_del(pmu->dev);
8879+
put_device(pmu->dev);
8880+
}
88768881
free_pmu_context(pmu);
88778882
}
88788883
EXPORT_SYMBOL_GPL(perf_pmu_unregister);

0 commit comments

Comments
 (0)