From: Maíra Canal mcanal@igalia.com
stable inclusion from stable-v6.6.57 commit 937943c042503dc6087438bf3557f9057a588ba0 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/IB2YWQ CVE: CVE-2024-50187
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
--------------------------------
commit 0b2ad4f6f2bec74a5287d96cb2325a5e11706f22 upstream.
Upon closing the file descriptor, the active performance monitor is not stopped. Although all perfmons are destroyed in `vc4_perfmon_close_file()`, the active performance monitor's pointer (`vc4->active_perfmon`) is still retained.
If we open a new file descriptor and submit a few jobs with performance monitors, the driver will attempt to stop the active performance monitor using the stale pointer in `vc4->active_perfmon`. However, this pointer is no longer valid because the previous process has already terminated, and all performance monitors associated with it have been destroyed and freed.
To fix this, when the active performance monitor belongs to a given process, explicitly stop it before destroying and freeing it.
Cc: stable@vger.kernel.org # v4.17+ Cc: Boris Brezillon bbrezillon@kernel.org Cc: Juan A. Suarez Romero jasuarez@igalia.com Fixes: 65101d8c9108 ("drm/vc4: Expose performance counters to userspace") Signed-off-by: Maíra Canal mcanal@igalia.com Reviewed-by: Juan A. Suarez jasuarez@igalia.com Link: https://patchwork.freedesktop.org/patch/msgid/20241004123817.890016-2-mcanal... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Conflicts: drivers/gpu/drm/vc4/vc4_perfmon.c drivers/gpu/drm/vc4/vc4_drv.h [HULK-5.10 don't merge stable inclusion patch 30f8c74ca9b7b3a2db55f6bb1d2e9f8c47a79f94 ("drm/vc4: Warn if some v3d code is run on BCM2711"). Add struct vc4_dev *dev in struct vc4_file] Signed-off-by: Kaixiong Yu yukaixiong@huawei.com --- drivers/gpu/drm/vc4/vc4_drv.h | 2 ++ drivers/gpu/drm/vc4/vc4_perfmon.c | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 921463625d82..a094ca5b19b1 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -673,6 +673,8 @@ struct vc4_exec_info { * released when the DRM file is closed should be placed here. */ struct vc4_file { + struct vc4_dev *dev; + struct { struct idr idr; struct mutex lock; diff --git a/drivers/gpu/drm/vc4/vc4_perfmon.c b/drivers/gpu/drm/vc4/vc4_perfmon.c index f4aa75efd16b..8aa0825aa85b 100644 --- a/drivers/gpu/drm/vc4/vc4_perfmon.c +++ b/drivers/gpu/drm/vc4/vc4_perfmon.c @@ -83,6 +83,11 @@ void vc4_perfmon_open_file(struct vc4_file *vc4file) static int vc4_perfmon_idr_del(int id, void *elem, void *data) { struct vc4_perfmon *perfmon = elem; + struct vc4_dev *vc4 = (struct vc4_dev *)data; + + /* If the active perfmon is being destroyed, stop it first */ + if (perfmon == vc4->active_perfmon) + vc4_perfmon_stop(vc4, perfmon, false);
vc4_perfmon_put(perfmon);
@@ -92,7 +97,7 @@ static int vc4_perfmon_idr_del(int id, void *elem, void *data) void vc4_perfmon_close_file(struct vc4_file *vc4file) { mutex_lock(&vc4file->perfmon.lock); - idr_for_each(&vc4file->perfmon.idr, vc4_perfmon_idr_del, NULL); + idr_for_each(&vc4file->perfmon.idr, vc4_perfmon_idr_del, vc4file->dev); idr_destroy(&vc4file->perfmon.idr); mutex_unlock(&vc4file->perfmon.lock); }