IGT mmap testing in i915 uses current task's address space to
allocate new userspace mapping, without registering real user
for that address space in mm_struct.

It was observed that mm->mm_users would occasionally drop to 0
during tests, which reaped userspace mappings, further leading
to failures upon reading from userland memory.

Prevent this by artificially increasing mm_users counter for the
duration of the test.

Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14204
Signed-off-by: Krzysztof Karas <[email protected]>
---
During testing I also found out that this problem affects
another function, __igt_mmap(), which also utilizes userspace
VMAs.

v2:
 * use mmget/mmput() (Jani);
 * include __igt_mmap() in the scope;
 * change comments and commit message;

 .../drm/i915/gem/selftests/i915_gem_mman.c    | 24 +++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c 
b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
index 0d250d57496a..82ab090f66c8 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
@@ -916,6 +916,13 @@ static int __igt_mmap(struct drm_i915_private *i915,
        if (err)
                return err;
 
+       /*
+        * Get a reference to tasks's mm_struct to artificially increase 
mm_users
+        * and ensure the kernel does not try to clean up the userspace mappings
+        * of the current task during the test.
+        */
+       mmget_not_zero(current->mm);
+
        addr = igt_mmap_offset(i915, offset, obj->base.size, PROT_WRITE, 
MAP_SHARED);
        if (IS_ERR_VALUE(addr))
                return addr;
@@ -968,6 +975,11 @@ static int __igt_mmap(struct drm_i915_private *i915,
                err = gtt_check(obj);
 out_unmap:
        vm_munmap(addr, obj->base.size);
+       /*
+        * mmput() is not supposed to be called on task's own
+        * mm_struct, so let kernel handle that.
+        */
+       mmput_async(current->mm);
        return err;
 }
 
@@ -1177,6 +1189,13 @@ static int __igt_mmap_migrate(struct intel_memory_region 
**placements,
        if (err)
                goto out_put;
 
+       /*
+        * Get a reference to tasks's mm_struct to artificially increase 
mm_users
+        * and ensure the kernel does not try to clean up the userspace mappings
+        * of the current task during the test.
+        */
+       mmget_not_zero(current->mm);
+
        /*
         * This will eventually create a GEM context, due to opening dummy drm
         * file, which needs a tiny amount of mappable device memory for the top
@@ -1293,6 +1312,11 @@ static int __igt_mmap_migrate(struct intel_memory_region 
**placements,
 
 out_addr:
        vm_munmap(addr, obj->base.size);
+       /*
+        * mmput() is not supposed to be called on task's own
+        * mm_struct, so let kernel handle that.
+        */
+       mmput_async(current->mm);
 
 out_put:
        i915_gem_object_put(obj);
-- 
2.43.0


-- 
Best Regards,
Krzysztof

Reply via email to