On 31/10/2025 11:42, Krzysztof Karas wrote:
Hi Krzysztof,

Set eb->vma[i+1].vma to NULL to prevent eb_release_vmas() from
processing unitialized data, leading to a potential NULL dereference.

During the execution of eb_lookup_vmas(), the eb->vma array is
successively filled up with struct eb_vma objects. This process includes
calling eb_add_vma(), which might fail; however, even in the event of
failure, eb->vma[i].vma is set for the currently processes buffer.
processes -> processed


If eb_add_vma() fails, eb_lookup_vmas() returns with an error, which
prompts a call to eb_release_vmas() to clean up the mess. Since
eb_lookup_vmas() might fail during processing any (possibly not first)
buffer, eb_release_vmas() checks whether a buffer's vma is NULL to know
which one has failed first. The NULL is set if the vma cannot be set or
is invalid in some way, but during and after the eb_add_vma() call, it
is set to a valid pointer for the currently processed eb_vma.

This means that during the check in eb_release_vmas(), the buffer that
failed eb_add_vma() (say, eb->vma[i]) is processed (and rightfully so,
since the vma associated with it still needs cleanup), but eb->vma[i+1]
is left completely uninitialized (since the loop was broken prematurely
after failing on eb_add_vma() for eb->vma[i]). Therefore
eb->vma[i+1].vma has junk in it, and if that junk is not NULL, that vma
will be processed by eb_release_vmas(), leading to memory corruption.

Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15062

Reported-by: 김강민 <[email protected]>
Signed-off-by: Krzysztof Niemiec <[email protected]>
---
  .../gpu/drm/i915/gem/i915_gem_execbuffer.c    | 19 ++++++++++++++-----
  1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c 
b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
index 39c7c32e1e74..0f8f02e22c03 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
@@ -960,18 +960,27 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb)
                }
err = eb_add_vma(eb, &current_batch, i, vma);
-               if (err)
+               if (err) {
+                       if (i + 1 < eb->buffer_count) {
+                               /*
+                                * Execbuffer code expects last vma entry to be 
NULL,
+                                * since we already initialized this entry,
+                                * set the next value to NULL or we mess up
+                                * cleanup handling.
+                                */
+                               eb->vma[i + 1].vma = NULL;
+                       }
+
                        return err;
+               }
if (i915_gem_object_is_userptr(vma->obj)) {
                        err = i915_gem_object_userptr_submit_init(vma->obj);
                        if (err) {
                                if (i + 1 < eb->buffer_count) {
                                        /*
-                                        * Execbuffer code expects last vma 
entry to be NULL,
-                                        * since we already initialized this 
entry,
-                                        * set the next value to NULL or we 
mess up
-                                        * cleanup handling.
+                                        * Set the next vma to null, for the 
same
null -> NULL to be more explicit and to match the previous
comment.

+                                        * reason as above.
                                         */
                                        eb->vma[i + 1].vma = NULL;
                                }

After above are addressed (maybe during merge, to avoid
re-sending?):
Reviewed-by: Krzysztof Karas <[email protected]>

Could you please also figure out the right Fixes: / stable?

I initially suspected either 544460c33821 or ed29c2691188 could be related. In any case bug looks serious enough to warrant backporting for stable.

Regards,

Tvrtko

Reply via email to