60 lines
2.0 KiB
Diff
60 lines
2.0 KiB
Diff
---
|
|
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 36 ++++++++++++++-----
|
|
1 file changed, 27 insertions(+), 9 deletions(-)
|
|
|
|
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
|
index 86ffa0c2880f..710edc70e37e 100644
|
|
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
|
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
|
@@ -8717,20 +8717,38 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
|
|
* the same resource. If we have a new DC context as part of
|
|
* the DM atomic state from validation we need to free it and
|
|
* retain the existing one instead.
|
|
+ *
|
|
+ * Furthermore, since the DM atomic state only contains the DC
|
|
+ * context and can safely be annulled, we can free the state
|
|
+ * and clear the associated private object now to free
|
|
+ * some memory and avoid a possible use-after-free later.
|
|
*/
|
|
- struct dm_atomic_state *new_dm_state, *old_dm_state;
|
|
|
|
- new_dm_state = dm_atomic_get_new_state(state);
|
|
- old_dm_state = dm_atomic_get_old_state(state);
|
|
+ for (i = 0; i < state->num_private_objs; i++) {
|
|
+ struct drm_private_obj *obj = state->private_objs[i].ptr;
|
|
|
|
- if (new_dm_state && old_dm_state) {
|
|
- if (new_dm_state->context)
|
|
- dc_release_state(new_dm_state->context);
|
|
+ if (obj->funcs == adev->dm.atomic_obj.funcs) {
|
|
+ int j = state->num_private_objs-1;
|
|
|
|
- new_dm_state->context = old_dm_state->context;
|
|
+ dm_atomic_destroy_state(obj,
|
|
+ state->private_objs[i].state);
|
|
+
|
|
+ /* If i is not at the end of the array then the
|
|
+ * last element needs to be moved to where i was
|
|
+ * before the array can safely be truncated.
|
|
+ */
|
|
+ if (i != j)
|
|
+ state->private_objs[i] =
|
|
+ state->private_objs[j];
|
|
|
|
- if (old_dm_state->context)
|
|
- dc_retain_state(old_dm_state->context);
|
|
+ state->private_objs[j].ptr = NULL;
|
|
+ state->private_objs[j].state = NULL;
|
|
+ state->private_objs[j].old_state = NULL;
|
|
+ state->private_objs[j].new_state = NULL;
|
|
+
|
|
+ state->num_private_objs = j;
|
|
+ break;
|
|
+ }
|
|
}
|
|
}
|
|
|
|
--
|
|
2.27.0
|
|
|
|
|