From: Adam Emerson Date: Thu, 7 Sep 2023 21:35:40 +0000 (-0400) Subject: neorados: Validate pointers from watch cookies X-Git-Tag: v19.3.0~349^2~6 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=7dc969e489f0262c1655e78f0bc3df0871e9e300;p=ceph.git neorados: Validate pointers from watch cookies Since Objecter has a set used to validate pointers converted from watch cookies before dereferencing them, expose a function to do so. Also make the set a `std::unordered_set` since we use it for only this purpose. Signed-off-by: Adam Emerson --- diff --git a/src/include/neorados/RADOS.hpp b/src/include/neorados/RADOS.hpp index ab95bdb17993..dbc4aff3c5ac 100644 --- a/src/include/neorados/RADOS.hpp +++ b/src/include/neorados/RADOS.hpp @@ -494,9 +494,9 @@ public: return std::move(get_omap_vals_by_keys(keys, kv, ec)); } - ReadOp& list_watchers(std::vector* watchers, + ReadOp& list_watchers(std::vector* watchers, boost::system::error_code* ec = nullptr) &; - ReadOp&& list_watchers(std::vector* watchers, + ReadOp&& list_watchers(std::vector* watchers, boost::system::error_code* ec = nullptr) && { return std::move(list_watchers(watchers, ec)); } @@ -1663,6 +1663,9 @@ public: }, consigned); } + tl::expected + check_watch(uint64_t cookie); + using NotifySig = void(boost::system::error_code, ceph::buffer::list); using NotifyComp = boost::asio::any_completion_handler; template CompletionToken> @@ -1832,8 +1835,6 @@ private: void watch_(Object o, IOContext ioc, std::optional timeout, WatchCB cb, WatchComp c); - tl::expected - watch_check_(uint64_t cookie); void notify_ack_(Object o, IOContext _ioc, uint64_t notify_id, uint64_t cookie, diff --git a/src/neorados/RADOS.cc b/src/neorados/RADOS.cc index 9a71b1269a16..9b743f6e9862 100644 --- a/src/neorados/RADOS.cc +++ b/src/neorados/RADOS.cc @@ -1375,10 +1375,14 @@ void RADOS::notify_ack_(Object o, IOContext _ioc, nullptr, ioc->extra_op_flags, std::move(c)); } -tl::expected RADOS::watch_check_(uint64_t cookie) +tl::expected RADOS::check_watch(uint64_t cookie) { - Objecter::LingerOp *linger_op = reinterpret_cast(cookie); - return impl->objecter->linger_check(linger_op); + auto linger_op = reinterpret_cast(cookie); + if (impl->objecter->is_valid_watch(linger_op)) { + return impl->objecter->linger_check(linger_op); + } else { + return tl::unexpected(bs::error_code(ENOTCONN, bs::generic_category())); + } } void RADOS::unwatch_(uint64_t cookie, IOContext _ioc, diff --git a/src/osdc/Objecter.h b/src/osdc/Objecter.h index 201b7b62d08f..6daf57b928d3 100644 --- a/src/osdc/Objecter.h +++ b/src/osdc/Objecter.h @@ -2532,7 +2532,7 @@ public: std::map linger_ops; // we use this just to confirm a cookie is valid before dereferencing the ptr - std::set linger_ops_set; + std::unordered_set linger_ops_set; std::map poolstat_ops; std::map statfs_ops; @@ -2614,6 +2614,12 @@ public: friend class CB_Objecter_GetVersion; friend class CB_DoWatchError; public: + + bool is_valid_watch(LingerOp* op) { + std::shared_lock l(rwlock); + return linger_ops_set.contains(op); + } + template auto linger_callback_flush(CT&& ct) { auto consigned = boost::asio::consign(