[PATCH] fix for cdput() race

From: Alexander Viro (viro@math.psu.edu)
Date: Sat Nov 03 2001 - 13:57:09 EST


        Resend - that area hadn't changed and bug is still there.

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/



This archive was generated by hypermail 2b29 : Wed Nov 07 2001 - 21:00:21 EST