IB/uverbs: Improve lockdep_check
authorJason Gunthorpe <jgg@mellanox.com>
Tue, 13 Feb 2018 10:18:38 +0000 (12:18 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 15 Mar 2018 09:54:28 +0000 (10:54 +0100)
commit 104f268d439b3c21c83708e52946a4d8d37f3d0f upstream.

This is really being used as an assert that the expected usecnt
is being held and implicitly that the usecnt is valid. Rename it to
assert_uverbs_usecnt and tighten the checks to only accept valid
values of usecnt (eg 0 and < -1 are invalid).

The tigher checkes make the assertion cover more cases and is more
likely to find bugs via syzkaller/etc.

Fixes: 3832125624b7 ("IB/core: Add support for idr types")
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/infiniband/core/rdma_core.c

index 4e1f767308558eb70898bfc132cdab0d00a17e8e..9cb801d1fe5432c918d1dba398b30ca58e8902f1 100644 (file)
@@ -407,13 +407,13 @@ static int __must_check remove_commit_fd_uobject(struct ib_uobject *uobj,
        return ret;
 }
 
-static void lockdep_check(struct ib_uobject *uobj, bool exclusive)
+static void assert_uverbs_usecnt(struct ib_uobject *uobj, bool exclusive)
 {
 #ifdef CONFIG_LOCKDEP
        if (exclusive)
-               WARN_ON(atomic_read(&uobj->usecnt) > 0);
+               WARN_ON(atomic_read(&uobj->usecnt) != -1);
        else
-               WARN_ON(atomic_read(&uobj->usecnt) == -1);
+               WARN_ON(atomic_read(&uobj->usecnt) <= 0);
 #endif
 }
 
@@ -452,7 +452,7 @@ int __must_check rdma_remove_commit_uobject(struct ib_uobject *uobj)
                WARN(true, "ib_uverbs: Cleanup is running while removing an uobject\n");
                return 0;
        }
-       lockdep_check(uobj, true);
+       assert_uverbs_usecnt(uobj, true);
        ret = _rdma_remove_commit_uobject(uobj, RDMA_REMOVE_DESTROY);
 
        up_read(&ucontext->cleanup_rwsem);
@@ -482,7 +482,7 @@ int rdma_explicit_destroy(struct ib_uobject *uobject)
                WARN(true, "ib_uverbs: Cleanup is running while removing an uobject\n");
                return 0;
        }
-       lockdep_check(uobject, true);
+       assert_uverbs_usecnt(uobject, true);
        ret = uobject->type->type_class->remove_commit(uobject,
                                                       RDMA_REMOVE_DESTROY);
        if (ret)
@@ -569,7 +569,7 @@ static void lookup_put_fd_uobject(struct ib_uobject *uobj, bool exclusive)
 
 void rdma_lookup_put_uobject(struct ib_uobject *uobj, bool exclusive)
 {
-       lockdep_check(uobj, exclusive);
+       assert_uverbs_usecnt(uobj, exclusive);
        uobj->type->type_class->lookup_put(uobj, exclusive);
        /*
         * In order to unlock an object, either decrease its usecnt for