Skip to contentSkip to conversation

IB/ucma: Fix theoretical user triggered use-after-free

PATCH In review Jason Gunthorpe 3 participants 3 messages Aug 4, 2015 – Aug 15, 2015 2 messages not in the archive InfiniBand

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 IB/ucma: Fix theoretical user triggered use-after-free

Something like this:

CPU A CPU B
======================== ================================
ucma_destroy_id()
wait_for_completion()

                              .. anything
                                ucma_put_ctx()
                                  complete()
 .. continues ...
                              ucma_leave_multicast()
                               mutex_lock(mut)
                                 atomic_inc(ctx->ref)
                               mutex_unlock(mut)
 ucma_free_ctx()
  ucma_cleanup_multicast()
   mutex_lock(mut)
     kfree(mc)
                               rdma_leave_multicast(mc->ctx->cm_id,..

Fix it by latching the ref at 0. Once it goes to 0 mc and ctx cannot leave the mutex(mut) protection.

The other atomic_inc in ucma_get_ctx is OK because mutex(mut) protects it from racing with ucma_destroy_id.

---
 drivers/infiniband/core/ucma.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/infiniband/core/ucma.c +3 -3
index 29b21213ea75..acac9eafdbf6 100644
@@ -1321,10 +1321,10 @@ static ssize_t ucma_leave_multicast(struct ucma_file *file,
 		mc = ERR_PTR(-ENOENT);
 	else if (mc->ctx->file != file)
 		mc = ERR_PTR(-EINVAL);
-	else {
+	else if (!atomic_inc_not_zero(&mc->ctx->ref))
+		mc = ERR_PTR(-ENXIO);
+	else
 		idr_remove(&multicast_idr, mc->id);
-		atomic_inc(&mc->ctx->ref);
-	}
 	mutex_unlock(&mut);
 
 	if (IS_ERR(mc)) {
Signature · 6 lines
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

A message that is not in the archive (sent off-list or not yet received): 20150804231332.GA22959-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org

Acked-by
#2 lore raw
Quoted 20 lines

Something like this:

CPU A CPU B
======================== ================================
ucma_destroy_id()
wait_for_completion()

                              .. anything
                                ucma_put_ctx()
                                  complete()
 .. continues ...
                              ucma_leave_multicast()
                               mutex_lock(mut)
                                 atomic_inc(ctx->ref)
                               mutex_unlock(mut)
 ucma_free_ctx()
  ucma_cleanup_multicast()
   mutex_lock(mut)
     kfree(mc)
                               rdma_leave_multicast(mc->ctx->cm_id,..
Quoted 7 lines

Fix it by latching the ref at 0. Once it goes to 0 mc and ctx cannot leave the mutex(mut) protection.

The other atomic_inc in ucma_get_ctx is OK because mutex(mut) protects it from racing with ucma_destroy_id.

Quoted 23 lines
---
 drivers/infiniband/core/ucma.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/infiniband/core/ucma.c +3 -3
index 29b21213ea75..acac9eafdbf6 100644
@@ -1321,10 +1321,10 @@ static ssize_t ucma_leave_multicast(struct
 ucma_file *file,
 		mc = ERR_PTR(-ENOENT);
 	else if (mc->ctx->file != file)
 		mc = ERR_PTR(-EINVAL);
-	else {
+	else if (!atomic_inc_not_zero(&mc->ctx->ref))
+		mc = ERR_PTR(-ENXIO);
+	else
 		idr_remove(&multicast_idr, mc->id);
-		atomic_inc(&mc->ctx->ref);
-	}
 	mutex_unlock(&mut);
 
Quoted 1 line

if (IS_ERR(mc)) {

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

A message that is not in the archive (sent off-list or not yet received): 1828884A29C6694DAF28B7E6B8A82373A9023323-P5GAC/[email protected]

#4 lore raw
Quoted 23 lines · Sean
Quoted 23 lines

Something like this:

CPU A CPU B
======================== ================================
ucma_destroy_id()
wait_for_completion()

                              .. anything
                                ucma_put_ctx()
                                  complete()
 .. continues ...
                              ucma_leave_multicast()
                               mutex_lock(mut)
                                 atomic_inc(ctx->ref)
                               mutex_unlock(mut)
 ucma_free_ctx()
  ucma_cleanup_multicast()
   mutex_lock(mut)
     kfree(mc)
                               rdma_leave_multicast(mc->ctx->cm_id,..

Fix it by latching the ref at 0. Once it goes to 0 mc and ctx cannot leave the mutex(mut) protection.

Quoted 6 lines
Quoted 4 lines

The other atomic_inc in ucma_get_ctx is OK because mutex(mut) protects it from racing with ucma_destroy_id.

This has been picked up. Thanks.

Signature · 2 lines
Doug Ledford <[email protected]>
              GPG KeyID: 0E572FDD