Currently we may mark the subsequent sg entry as the last, instead of
the actual last element we used. If a later iterator only used
sg_is_last() (such as sg_next()) then we may access the NULL page stored
in the elements beyond the contracted table. This may explain the
occasional NULL dereference we see in insert pages, such as
https://bugzilla.redhat.com/show_bug.cgi?id=1227892

Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk>
Cc: Imre Deak <imre.d...@intel.com>
Cc: sta...@vger.kernel.org
---
 drivers/gpu/drm/i915/i915_gem.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index be35f0486202..f3b66461dc68 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2195,7 +2195,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object 
*obj)
        int page_count, i;
        struct address_space *mapping;
        struct sg_table *st;
-       struct scatterlist *sg;
+       struct scatterlist *sg, *end;
        struct sg_page_iter sg_iter;
        struct page *page;
        unsigned long last_pfn = 0;     /* suppress gcc warning */
@@ -2227,7 +2227,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object 
*obj)
        gfp = mapping_gfp_mask(mapping);
        gfp |= __GFP_NORETRY | __GFP_NOWARN | __GFP_NO_KSWAPD;
        gfp &= ~(__GFP_IO | __GFP_WAIT);
-       sg = st->sgl;
+       end = sg = st->sgl;
        st->nents = 0;
        for (i = 0; i < page_count; i++) {
                page = shmem_read_mapping_page_gfp(mapping, i, gfp);
@@ -2253,13 +2253,13 @@ i915_gem_object_get_pages_gtt(struct 
drm_i915_gem_object *obj)
                if (swiotlb_nr_tbl()) {
                        st->nents++;
                        sg_set_page(sg, page, PAGE_SIZE, 0);
-                       sg = sg_next(sg);
+                       sg = sg_next(end = sg);
                        continue;
                }
 #endif
                if (!i || page_to_pfn(page) != last_pfn + 1) {
                        if (i)
-                               sg = sg_next(sg);
+                               sg = sg_next(end = sg);
                        st->nents++;
                        sg_set_page(sg, page, PAGE_SIZE, 0);
                } else {
@@ -2273,7 +2273,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object 
*obj)
 #ifdef CONFIG_SWIOTLB
        if (!swiotlb_nr_tbl())
 #endif
-               sg_mark_end(sg);
+               sg_mark_end(end);
        obj->pages = st;
 
        if (i915_gem_object_needs_bit17_swizzle(obj))
-- 
2.1.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to