From: Radoslaw Zarzynski Date: Tue, 22 May 2018 13:50:44 +0000 (+0200) Subject: common: OpTracker doesn't visit TrackedOp when nref == 0. X-Git-Tag: v13.2.0~31^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=refs%2Fpull%2F22160%2Fhead;p=ceph.git common: OpTracker doesn't visit TrackedOp when nref == 0. The patch fixes a race condition that happens between `unregister_inflight_op` and `visit_ops_in_flight` of `OpTracker`. When a callable passed to the former one turns the plain reference it gets into `TrackedOpRef`, an almost-to-terminate `TrackedOp` (with `nref == 0`) can be resurrected (`nref++`). This will be reflected in extra call to `unregister_inflight_op` for same op leading to e.g. use-after-free. For more details see: https://tracker.ceph.com/issues/24037#note-5. The fix deals with the problem by ensuring there will be no call to the visitor for ops with zeroized `nref`. Fixes: http://tracker.ceph.com/issues/24037 Signed-off-by: Radoslaw Zarzynski (cherry picked from commit 574aeb8130926fab5632d9f7a6ac0b132c6a60b8) --- diff --git a/src/common/TrackedOp.cc b/src/common/TrackedOp.cc index feb3e9f7308..8d4e986190a 100644 --- a/src/common/TrackedOp.cc +++ b/src/common/TrackedOp.cc @@ -328,7 +328,7 @@ bool OpTracker::visit_ops_in_flight(utime_t* oldest_secs, assert(NULL != sdata); Mutex::Locker locker(sdata->ops_in_flight_lock_sharded); for (auto& op : sdata->ops_in_flight_sharded) { - if (!visit(op)) + if (op.nref > 0 && !visit(op)) break; } }