diff options
author | Jason Gunthorpe <jgg@mellanox.com> | 2018-02-13 11:18:38 +0100 |
---|---|---|
committer | Jason Gunthorpe <jgg@mellanox.com> | 2018-02-15 22:59:47 +0100 |
commit | 104f268d439b3c21c83708e52946a4d8d37f3d0f (patch) | |
tree | d0e0b27d0a5e658e5e2bcb191b08b395ed8f8ccb /drivers/infiniband | |
parent | RDMA/uverbs: Protect from races between lookup and destroy of uobjects (diff) | |
download | linux-104f268d439b3c21c83708e52946a4d8d37f3d0f.tar.xz linux-104f268d439b3c21c83708e52946a4d8d37f3d0f.zip |
IB/uverbs: Improve lockdep_check
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>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/core/rdma_core.c | 14 |
1 files changed, 7 insertions, 7 deletions
diff --git a/drivers/infiniband/core/rdma_core.c b/drivers/infiniband/core/rdma_core.c index f1f805a0d31a..cfd257e34e02 100644 --- a/drivers/infiniband/core/rdma_core.c +++ b/drivers/infiniband/core/rdma_core.c @@ -412,13 +412,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 } @@ -457,7 +457,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); @@ -487,7 +487,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) @@ -541,7 +541,7 @@ int rdma_alloc_commit_uobject(struct ib_uobject *uobj) } /* matches atomic_set(-1) in alloc_uobj */ - lockdep_check(uobj, true); + assert_uverbs_usecnt(uobj, true); atomic_set(&uobj->usecnt, 0); uobj->type->type_class->alloc_commit(uobj); @@ -578,7 +578,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 |