⬢ DragonFlyBSD Kernel Audit
DF-4197 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/drm/include/linux/seqlock.h
+++ b/sys/dev/drm/include/linux/seqlock.h
@@ -77,7 +77,11 @@
 static inline void
 write_sequnlock(seqlock_t *sl)
 {
-	sl->sequence--;
+	/* Advance the sequence count monotonically instead of returning it
+	 * to its pre-write value: a reader that started before this writer
+	 * must observe a changed sequence on read_seqretry() or it will
+	 * accept a torn snapshot. */
+	sl->sequence++;
 	spin_unlock(&sl->lock);
 	cpu_sfence();
 }
@@ -90,7 +94,18 @@
 static inline unsigned
 read_seqbegin(const seqlock_t *sl)
 {
-	return READ_ONCE(sl->sequence);
+	unsigned ret;
+
+	/* Wait until the sequence count is even, i.e. no writer holds the
+	 * seqlock write section (matches Linux read_seqcount_begin()). */
+	do {
+		ret = READ_ONCE(sl->sequence);
+		if ((ret & 1) == 0)
+			break;
+		cpu_pause();
+	} while (1);
+
+	return ret;
 }
 
 static inline unsigned