aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJason Gunthorpe <jgg@mellanox.com>2018-02-13 12:18:38 +0200
committerJason Gunthorpe <jgg@mellanox.com>2018-02-15 14:59:47 -0700
commit104f268d439b3c21c83708e52946a4d8d37f3d0f (patch)
treed0e0b27d0a5e658e5e2bcb191b08b395ed8f8ccb /drivers
parentRDMA/uverbs: Protect from races between lookup and destroy of uobjects (diff)
downloadlinux-dev-104f268d439b3c21c83708e52946a4d8d37f3d0f.tar.xz
linux-dev-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')
-rw-r--r--drivers/infiniband/core/rdma_core.c14
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