lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Mon, 26 Feb 2018 21:22:24 +0100
From:   Greg Kroah-Hartman <gregkh@...uxfoundation.org>
To:     linux-kernel@...r.kernel.org
Cc:     Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
        stable@...r.kernel.org, Chris Wilson <chris@...is-wilson.co.uk>,
        Joonas Lahtinen <joonas.lahtinen@...ux.intel.com>,
        Daniel Vetter <daniel.vetter@...ll.ch>
Subject: [PATCH 4.14 47/54] drm: Handle unexpected holes in color-eviction

4.14-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Chris Wilson <chris@...is-wilson.co.uk>

commit b8ff1802815913aad52695898cccbc9f77b7e726 upstream.

During eviction, the driver may free more than one hole in the drm_mm
due to the side-effects in evicting the scanned nodes. However,
drm_mm_scan_color_evict() expects that the scan result is the first
available hole (in the mru freed hole_stack list):

  kernel BUG at drivers/gpu/drm/drm_mm.c:844!
  invalid opcode: 0000 [#1] PREEMPT SMP KASAN PTI
  Dumping ftrace buffer:
     (ftrace buffer empty)
  Modules linked in: i915 snd_hda_codec_analog snd_hda_codec_generic coretemp snd_hda_intel snd_hda_codec snd_hwdep snd_hda_core lpc_ich snd_pcm e1000e mei_me prime_numbers mei
  CPU: 1 PID: 1490 Comm: gem_userptr_bli Tainted: G     U           4.16.0-rc1-g740f57c54ecf-kasan_6+ #1
  Hardware name: Dell Inc. OptiPlex 755                 /0PU052, BIOS A08 02/19/2008
  RIP: 0010:drm_mm_scan_color_evict+0x2b8/0x3d0
  RSP: 0018:ffff880057a573f8 EFLAGS: 00010287
  RAX: ffff8800611f5980 RBX: ffff880057a575d0 RCX: dffffc0000000000
  RDX: 00000000029d5000 RSI: 1ffff1000af4aec1 RDI: ffff8800611f5a10
  RBP: ffff88005ab884d0 R08: ffff880057a57600 R09: 000000000afff000
  R10: 1ffff1000b5710b5 R11: 0000000000001000 R12: 1ffff1000af4ae82
  R13: ffff8800611f59b0 R14: ffff8800611f5980 R15: ffff880057a57608
  FS:  00007f2de0c2e8c0(0000) GS:ffff88006ac40000(0000) knlGS:0000000000000000
  CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
  CR2: 00007f2ddde1e000 CR3: 00000000609b2000 CR4: 00000000000006e0
  Call Trace:
   ? drm_mm_scan_remove_block+0x330/0x330
   ? drm_mm_scan_remove_block+0x151/0x330
   i915_gem_evict_something+0x711/0xbd0 [i915]
   ? igt_evict_contexts+0x50/0x50 [i915]
   ? nop_clear_range+0x10/0x10 [i915]
   ? igt_evict_something+0x90/0x90 [i915]
   ? i915_gem_gtt_reserve+0x1a1/0x320 [i915]
   i915_gem_gtt_insert+0x237/0x400 [i915]
   __i915_vma_do_pin+0xc25/0x1a20 [i915]
   eb_lookup_vmas+0x1c63/0x3790 [i915]
   ? i915_gem_check_execbuffer+0x250/0x250 [i915]
   ? trace_hardirqs_on_caller+0x33f/0x590
   ? _raw_spin_unlock_irqrestore+0x39/0x60
   ? __pm_runtime_resume+0x7d/0xf0
   i915_gem_do_execbuffer+0x86a/0x2ff0 [i915]
   ? __kmalloc+0x132/0x340
   ? i915_gem_execbuffer2_ioctl+0x10f/0x760 [i915]
   ? drm_ioctl_kernel+0x12e/0x1c0
   ? drm_ioctl+0x662/0x980
   ? eb_relocate_slow+0xa90/0xa90 [i915]
   ? i915_gem_execbuffer2_ioctl+0x10f/0x760 [i915]
   ? __might_fault+0xea/0x1a0
   i915_gem_execbuffer2_ioctl+0x3cc/0x760 [i915]
   ? i915_gem_execbuffer_ioctl+0xba0/0xba0 [i915]
   ? lock_acquire+0x3c0/0x3c0
   ? i915_gem_execbuffer_ioctl+0xba0/0xba0 [i915]
   drm_ioctl_kernel+0x12e/0x1c0
   drm_ioctl+0x662/0x980
   ? i915_gem_execbuffer_ioctl+0xba0/0xba0 [i915]
   ? drm_getstats+0x20/0x20
   ? debug_check_no_obj_freed+0x2a6/0x8c0
   do_vfs_ioctl+0x170/0xe70
   ? ioctl_preallocate+0x170/0x170
   ? task_work_run+0xbe/0x160
   ? lock_acquire+0x3c0/0x3c0
   ? trace_hardirqs_on_caller+0x33f/0x590
   ? _raw_spin_unlock_irq+0x2f/0x50
   SyS_ioctl+0x36/0x70
   ? do_vfs_ioctl+0xe70/0xe70
   do_syscall_64+0x18c/0x5d0
   entry_SYSCALL_64_after_hwframe+0x26/0x9b
  RIP: 0033:0x7f2ddf13b587
  RSP: 002b:00007fff15c4f9d8 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
  RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 00007f2ddf13b587
  RDX: 00007fff15c4fa20 RSI: 0000000040406469 RDI: 0000000000000003
  RBP: 00007fff15c4fa20 R08: 0000000000000000 R09: 00007f2ddf3fe120
  R10: 0000000000000073 R11: 0000000000000246 R12: 0000000040406469
  R13: 0000000000000003 R14: 00007fff15c4fa20 R15: 00000000000000c7
  Code: 00 00 00 4a c7 44 22 08 00 00 00 00 42 c7 44 22 10 00 00 00 00 48 81 c4 b8 00 00 00 5b 5d 41 5c 41 5d 41 5e 41 5f c3 0f 0b 0f 0b <0f> 0b 31 c0 eb c0 4c 89 ef e8 9a 09 41 ff e9 1e fe ff ff 4c 89
  RIP: drm_mm_scan_color_evict+0x2b8/0x3d0 RSP: ffff880057a573f8

We can trivially relax this assumption by searching the hole_stack for
the scan result and warn instead if the driver called us without any
result.

Fixes: 3fa489dabea9 ("drm: Apply tight eviction scanning to color_adjust")
Signed-off-by: Chris Wilson <chris@...is-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahtinen@...ux.intel.com>
Cc: <stable@...r.kernel.org> # v4.11+
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@...ux.intel.com>
Reviewed-by: Daniel Vetter <daniel.vetter@...ll.ch>
Link: https://patchwork.freedesktop.org/patch/msgid/20180219113543.8010-1-chris@chris-wilson.co.uk
Signed-off-by: Greg Kroah-Hartman <gregkh@...uxfoundation.org>

---
 drivers/gpu/drm/drm_mm.c |   21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

--- a/drivers/gpu/drm/drm_mm.c
+++ b/drivers/gpu/drm/drm_mm.c
@@ -834,9 +834,24 @@ struct drm_mm_node *drm_mm_scan_color_ev
 	if (!mm->color_adjust)
 		return NULL;
 
-	hole = list_first_entry(&mm->hole_stack, typeof(*hole), hole_stack);
-	hole_start = __drm_mm_hole_node_start(hole);
-	hole_end = hole_start + hole->hole_size;
+	/*
+	 * The hole found during scanning should ideally be the first element
+	 * in the hole_stack list, but due to side-effects in the driver it
+	 * may not be.
+	 */
+	list_for_each_entry(hole, &mm->hole_stack, hole_stack) {
+		hole_start = __drm_mm_hole_node_start(hole);
+		hole_end = hole_start + hole->hole_size;
+
+		if (hole_start <= scan->hit_start &&
+		    hole_end >= scan->hit_end)
+			break;
+	}
+
+	/* We should only be called after we found the hole previously */
+	DRM_MM_BUG_ON(&hole->hole_stack == &mm->hole_stack);
+	if (unlikely(&hole->hole_stack == &mm->hole_stack))
+		return NULL;
 
 	DRM_MM_BUG_ON(hole_start > scan->hit_start);
 	DRM_MM_BUG_ON(hole_end < scan->hit_end);


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ