⬢ DragonFlyBSD Kernel Audit
DF-5138 / fix.diff
← back to finding ↓ download raw
--- sys/dev/drm/linux_wwmutex.c.orig
+++ sys/dev/drm/linux_wwmutex.c
@@ -85,6 +85,26 @@
 	int flags = LK_EXCLUSIVE;
 	int error;
 
+	/*
+	 * The lock is already held with this acquire context (a duplicate
+	 * buffer object in a ttm_eu_reserve_buffers() validation list, or
+	 * a drm_modeset_lock() re-lock).  The Linux ww_mutex contract that
+	 * both consumers code against returns -EALREADY here so the caller
+	 * can move the duplicate aside (ttm_execbuf_util.c:119-124) or
+	 * treat the relock as a no-op (drm_modeset_lock.c:270-276).
+	 *
+	 * Without this, the LK_CANRECURSE lockmgr silently succeeds a
+	 * second time and ww_mutex_unlock() then decrements ctx->acquired
+	 * only once (the second unlock sees ww->ctx == NULL), desyncing
+	 * the ticket accounting.
+	 *
+	 * ctx is private to the calling thread, so observing
+	 * ww->ctx == ctx implies we hold the lock; a same-thread store is
+	 * visible to our own load, and no other thread can store our ctx.
+	 */
+	if (ctx != NULL && ww->ctx == ctx)
+		return (-EALREADY);
+
 	if (intr)
 		flags |= LK_PCATCH;