Avoid using intel_context_put() before intel_context_init() in
execlists_create_virtual() as the kref_put() inside would lead
to NULL deref on the IOCTL path when sched_engine allocation fails.

Discovered using AI-assisted static analysis confirmed by
Intel Product Security.

Reported-by: Martin Hodo <[email protected]>
Fixes: 3e28d37146db ("drm/i915: Move priolist to new i915_sched_engine object")
Cc: Matthew Brost <[email protected]>
Cc: Daniele Ceraolo Spurio <[email protected]>
Cc: Tvrtko Ursulin <[email protected]>
Cc: <[email protected]> # v5.15+
Signed-off-by: Joonas Lahtinen <[email protected]>
---
 .../drm/i915/gt/intel_execlists_submission.c  | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c 
b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
index 1359fc9cb88e..e693b0c9d2a3 100644
--- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
+++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
@@ -3932,11 +3932,11 @@ execlists_create_virtual(struct intel_engine_cs 
**siblings, unsigned int count,
        struct drm_i915_private *i915 = siblings[0]->i915;
        struct virtual_engine *ve;
        unsigned int n;
-       int err;
+       int err = -ENOMEM;
 
        ve = kzalloc_flex(*ve, siblings, count);
        if (!ve)
-               return ERR_PTR(-ENOMEM);
+               goto err;
 
        ve->base.i915 = i915;
        ve->base.gt = siblings[0]->gt;
@@ -3968,10 +3968,8 @@ execlists_create_virtual(struct intel_engine_cs 
**siblings, unsigned int count,
        intel_engine_init_execlists(&ve->base);
 
        ve->base.sched_engine = i915_sched_engine_create(ENGINE_VIRTUAL);
-       if (!ve->base.sched_engine) {
-               err = -ENOMEM;
-               goto err_put;
-       }
+       if (!ve->base.sched_engine)
+               goto err_noput;
        ve->base.sched_engine->private_data = &ve->base;
 
        ve->base.cops = &virtual_context_ops;
@@ -3987,10 +3985,8 @@ execlists_create_virtual(struct intel_engine_cs 
**siblings, unsigned int count,
        intel_context_init(&ve->context, &ve->base);
 
        ve->base.breadcrumbs = intel_breadcrumbs_create(NULL);
-       if (!ve->base.breadcrumbs) {
-               err = -ENOMEM;
+       if (!ve->base.breadcrumbs)
                goto err_put;
-       }
 
        for (n = 0; n < count; n++) {
                struct intel_engine_cs *sibling = siblings[n];
@@ -4065,8 +4061,13 @@ execlists_create_virtual(struct intel_engine_cs 
**siblings, unsigned int count,
        virtual_engine_initial_hint(ve);
        return &ve->context;
 
+err_noput:
+       kfree(ve);
+       goto err;
+
 err_put:
        intel_context_put(&ve->context);
+err:
        return ERR_PTR(err);
 }
 
-- 
2.54.0

Reply via email to