]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commit
osdc: Objecter::linger_by_cookie() for safe cast from uint64 wip-72771
authorCasey Bodley <cbodley@redhat.com>
Fri, 26 Sep 2025 21:25:53 +0000 (17:25 -0400)
committerCasey Bodley <cbodley@redhat.com>
Thu, 2 Oct 2025 13:10:40 +0000 (09:10 -0400)
commit50d62b1b2b6eac043a98500223a1e56174b50229
treeeb25544531c26809956b06c69b16e10e32b03b2b
parent42d0d5d2e2bb0038daaf35cae89615ff83ac6eec
osdc: Objecter::linger_by_cookie() for safe cast from uint64

a `linger_ops_set` was added for `Objecter::handle_watch_notify()`
as a safety check before casting `uint64_t cookie` to `LingerOp*`
and deferencing it

neorados also made use of this set through `Objecter::is_valid_watch()`
checks. however, this approach was still susceptible to use-after-free,
because the callers didn't preserve a LingerOp reference between this
check and its use - and the Objecter lock is dropped in between. in
addition, `neorados::RADOS::unwatch_()` was missing its check for
`is_valid_watch()`

librados did not make use of this `is_valid_watch()` at all, so was
casting cookies directly to LingerOp* and dereferencing. this results
in use-after-free for any cookies invalidated by `linger_cancel()` -
for example when called by `CB_DoWatchError`

replace `is_valid_watch()` with a `linger_by_cookie()` function that
* performs the validity check with `linger_ops_set`,
* safely reinterpret_casts the cookie to LingerOp*, and
* returns a reference to the caller via intrusive_ptr<LingerOp>

`librados::IoCtxImpl::watch_check()`, `unwatch()` and `aio_unwatch()`
now call `linger_by_cookie()`, so have to handle the null case by
returning `-ENOTCONN` (this matches neorados' existing behavior)

Fixes: https://tracker.ceph.com/issues/72771
Signed-off-by: Casey Bodley <cbodley@redhat.com>
src/librados/IoCtxImpl.cc
src/neorados/RADOS.cc
src/osdc/Objecter.cc
src/osdc/Objecter.h