mock_context_alloc() creates ce->ring before allocating and pinning the
context timeline. mock_ring() initializes the ring reference count and
returns the initial reference to the context.

If intel_timeline_create() fails, mock_context_alloc() returns without
dropping the ring reference. The same leak occurs when
mock_timeline_pin() fails after the timeline has been created. Since
context allocation did not complete, CONTEXT_ALLOC_BIT is not set and
the later context teardown does not release the ring.

Drop the initial ring reference with kref_put() on both failure paths.
When the reference count reaches zero, intel_ring_free() releases the
ring VMA and frees the ring allocation. Clear ce->ring after dropping
the reference to avoid retaining a stale pointer.

The issue was identified by a static analysis tool I developed and
confirmed by manual review.

Fixes: 75d0a7f31eec ("drm/i915: Lift timeline into intel_context")
Cc: [email protected]
Signed-off-by: Guangshuo Li <[email protected]>
---
 drivers/gpu/drm/i915/gt/mock_engine.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/i915/gt/mock_engine.c 
b/drivers/gpu/drm/i915/gt/mock_engine.c
index 79741f043f03..fa4368730d33 100644
--- a/drivers/gpu/drm/i915/gt/mock_engine.c
+++ b/drivers/gpu/drm/i915/gt/mock_engine.c
@@ -170,6 +170,8 @@ static int mock_context_alloc(struct intel_context *ce)
 
        ce->timeline = intel_timeline_create(ce->engine->gt);
        if (IS_ERR(ce->timeline)) {
+               kref_put(&ce->ring->ref, intel_ring_free);
+               ce->ring = NULL;
                kfree(ce->engine);
                return PTR_ERR(ce->timeline);
        }
@@ -178,6 +180,8 @@ static int mock_context_alloc(struct intel_context *ce)
        if (err) {
                intel_timeline_put(ce->timeline);
                ce->timeline = NULL;
+               kref_put(&ce->ring->ref, intel_ring_free);
+               ce->ring = NULL;
                return err;
        }
 
-- 
2.43.0

Reply via email to