Race between cdput() and cdget() - if we have the only reference to
char_device and call cdput() while somebody else does cdget() on
another CPU, we are going to hit a race:
cdget:
	grabs cdev_lock
	searches the lists
				cdput:
					decrements ->count to 0
					spins on attempt to get cdev_lock
	find the structure
	increments ->count
	drops cdev_lock
	returns pointer to found	acquires cdev_lock
					removes the structure from lists
					frees it
caller of cdget:
	dereferences the returned value
	oops
This is exactly the same scenario as we had in d_lookup()/dput() - one
that lead to introduction of atomic_dec_and_lock().  Fix is trivial.
Please, apply.
--- linux/fs/char_dev.c	Thu May 24 18:26:45 2001
+++ /tmp/char_dev.c	Mon Oct 29 13:43:41 2001
@@ -104,8 +104,7 @@
 
 void cdput(struct char_device *cdev)
 {
-	if (atomic_dec_and_test(&cdev->count)) {
-		spin_lock(&cdev_lock);
+	if (atomic_dec_and_lock(&cdev->count, &cdev_lock)) {
 		list_del(&cdev->hash);
 		spin_unlock(&cdev_lock);
 		destroy_cdev(cdev);
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/