drm/xe: Fix unreffed ptr leak on engine lookup
authorMika Kuoppala <mika.kuoppala@linux.intel.com>
Fri, 2 Jun 2023 17:27:32 +0000 (20:27 +0300)
committerRodrigo Vivi <rodrigo.vivi@intel.com>
Thu, 21 Dec 2023 16:34:55 +0000 (11:34 -0500)
The engine xarray holds a ref to engine, guarded by the lock.
While we do lookup for engine, we need to take the ref inside
the lock to prevent unreffed pointer escaping and
causing potential use-after-free after.

v2: remove branch prediction hint (Thomas)

Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Signed-off-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Reviewed-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230602172732.1001057-1-mika.kuoppala@linux.intel.com
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
drivers/gpu/drm/xe/xe_engine.c

index e72a94a944d0030de70dfabc253a0abf409aaf5f..097a1ea06002faef395431de91e6edf62e9e0a57 100644 (file)
@@ -162,10 +162,9 @@ struct xe_engine *xe_engine_lookup(struct xe_file *xef, u32 id)
 
        mutex_lock(&xef->engine.lock);
        e = xa_load(&xef->engine.xa, id);
-       mutex_unlock(&xef->engine.lock);
-
        if (e)
                xe_engine_get(e);
+       mutex_unlock(&xef->engine.lock);
 
        return e;
 }
@@ -644,26 +643,27 @@ int xe_engine_get_property_ioctl(struct drm_device *dev, void *data,
        struct xe_file *xef = to_xe_file(file);
        struct drm_xe_engine_get_property *args = data;
        struct xe_engine *e;
+       int ret;
 
        if (XE_IOCTL_ERR(xe, args->reserved[0] || args->reserved[1]))
                return -EINVAL;
 
-       mutex_lock(&xef->engine.lock);
-       e = xa_load(&xef->engine.xa, args->engine_id);
-       mutex_unlock(&xef->engine.lock);
-
+       e = xe_engine_lookup(xef, args->engine_id);
        if (XE_IOCTL_ERR(xe, !e))
                return -ENOENT;
 
        switch (args->property) {
        case XE_ENGINE_GET_PROPERTY_BAN:
                args->value = !!(e->flags & ENGINE_FLAG_BANNED);
+               ret = 0;
                break;
        default:
-               return -EINVAL;
+               ret = -EINVAL;
        }
 
-       return 0;
+       xe_engine_put(e);
+
+       return ret;
 }
 
 static void engine_kill_compute(struct xe_engine *e)