From: Jason Dillaman Date: Tue, 3 May 2016 11:41:30 +0000 (-0400) Subject: librbd: possible race condition leads to use-after-free X-Git-Tag: v11.0.0~737^2 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=d9421a25b582e41550526714b71fb55f05abb1de;p=ceph-ci.git librbd: possible race condition leads to use-after-free The invoke async operation state machine can complete before the owner lock is released. Use a stack reference to prevent use-after-free. Fixes: http://tracker.ceph.com/issues/15690 Signed-off-by: Jason Dillaman --- diff --git a/src/librbd/Operations.cc b/src/librbd/Operations.cc index 89eb63637e0..5c8b3d222ba 100644 --- a/src/librbd/Operations.cc +++ b/src/librbd/Operations.cc @@ -152,12 +152,14 @@ struct C_InvokeAsyncRequest : public Context { } void send_acquire_exclusive_lock() { - image_ctx.owner_lock.get_read(); + // context can complete before owner_lock is unlocked + RWLock &owner_lock(image_ctx.owner_lock); + owner_lock.get_read(); image_ctx.snap_lock.get_read(); if (image_ctx.read_only || (!permit_snapshot && image_ctx.snap_id != CEPH_NOSNAP)) { image_ctx.snap_lock.put_read(); - image_ctx.owner_lock.put_read(); + owner_lock.put_read(); complete(-EROFS); return; } @@ -165,10 +167,10 @@ struct C_InvokeAsyncRequest : public Context { if (image_ctx.exclusive_lock == nullptr) { send_local_request(); - image_ctx.owner_lock.put_read(); + owner_lock.put_read(); return; } else if (image_ctx.image_watcher == nullptr) { - image_ctx.owner_lock.put_read(); + owner_lock.put_read(); complete(-EROFS); return; } @@ -176,7 +178,7 @@ struct C_InvokeAsyncRequest : public Context { if (image_ctx.exclusive_lock->is_lock_owner() && image_ctx.exclusive_lock->accept_requests()) { send_local_request(); - image_ctx.owner_lock.put_read(); + owner_lock.put_read(); return; } @@ -188,7 +190,7 @@ struct C_InvokeAsyncRequest : public Context { &C_InvokeAsyncRequest::handle_acquire_exclusive_lock>( this); image_ctx.exclusive_lock->try_lock(ctx); - image_ctx.owner_lock.put_read(); + owner_lock.put_read(); } void handle_acquire_exclusive_lock(int r) { @@ -200,15 +202,17 @@ struct C_InvokeAsyncRequest : public Context { return; } - image_ctx.owner_lock.get_read(); + // context can complete before owner_lock is unlocked + RWLock &owner_lock(image_ctx.owner_lock); + owner_lock.get_read(); if (image_ctx.exclusive_lock->is_lock_owner()) { send_local_request(); - image_ctx.owner_lock.put_read(); + owner_lock.put_read(); return; } send_remote_request(); - image_ctx.owner_lock.put_read(); + owner_lock.put_read(); } void send_remote_request() {