DragonFlyBSD Kernel Audit
DF-1881 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/drm/include/linux/dma-fence.h b/sys/dev/drm/include/linux/dma-fence.h
--- a/sys/dev/drm/include/linux/dma-fence.h
+++ b/sys/dev/drm/include/linux/dma-fence.h
@@ -97,9 +97,14 @@
 static inline struct dma_fence *
 dma_fence_get_rcu(struct dma_fence *fence)
 {
+	/* Must use kref_get_unless_zero so that RCU readers in
+	 * linux_reservation.c (reservation_object_get_fences_rcu etc.) can
+	 * detect a fence mid-teardown (refcount already 0) and retry.
+	 * Unconditional kref_get made their if(!dma_fence_get_rcu(..)) retry
+	 * logic dead code and caused double-frees. */
 	if (fence)
-		kref_get(&fence->refcount);
-	return fence;
+		return kref_get_unless_zero(&fence->refcount) ? fence : NULL;
+	return NULL;
 }
 
 static inline void