]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
neorados: Validate pointers from watch cookies
authorAdam Emerson <aemerson@redhat.com>
Thu, 7 Sep 2023 21:35:40 +0000 (17:35 -0400)
committerAdam Emerson <aemerson@redhat.com>
Thu, 14 Sep 2023 21:48:00 +0000 (17:48 -0400)
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 <aemerson@redhat.com>
src/include/neorados/RADOS.hpp
src/neorados/RADOS.cc
src/osdc/Objecter.h

index 0bae16afbfe379d0d0d75536694b73ddeb0b4c82..1be69580db980ebc784085b94ea8fe2e7c8f2392 100644 (file)
@@ -493,9 +493,9 @@ public:
     return std::move(get_omap_vals_by_keys(keys, kv, ec));
   }
 
-  ReadOp& list_watchers(std::vector<struct ObjWatcher>* watchers,
+  ReadOp& list_watchers(std::vector<ObjWatcher>* watchers,
                        boost::system::error_code* ec = nullptr) &;
-  ReadOp&& list_watchers(std::vector<struct ObjWatcher>* watchers,
+  ReadOp&& list_watchers(std::vector<ObjWatcher>* watchers,
                         boost::system::error_code* ec = nullptr) && {
     return std::move(list_watchers(watchers, ec));
   }
@@ -1670,6 +1670,9 @@ public:
       }, consigned);
   }
 
+  tl::expected<ceph::timespan, boost::system::error_code>
+  check_watch(uint64_t cookie);
+
   using NotifySig = void(boost::system::error_code, ceph::buffer::list);
   using NotifyComp = boost::asio::any_completion_handler<NotifySig>;
   template<boost::asio::completion_token_for<NotifySig> CompletionToken>
@@ -1841,8 +1844,6 @@ private:
   void watch_(Object o, IOContext ioc,
              std::optional<std::chrono::seconds> timeout,
              WatchCB cb, WatchComp c);
-  tl::expected<ceph::timespan, boost::system::error_code>
-  watch_check_(uint64_t cookie);
   void notify_ack_(Object o, IOContext _ioc,
                   uint64_t notify_id,
                   uint64_t cookie,
index 3b51992d860371684d4ecf744ddd070d06fd1a24..0c7d0f7f8e0a5911a32c7597de73374e3a41a5d1 100644 (file)
@@ -1418,10 +1418,14 @@ void RADOS::notify_ack_(Object o,
                       nullptr, ioc->extra_op_flags, std::move(c));
 }
 
-tl::expected<ceph::timespan, bs::error_code> RADOS::watch_check_(uint64_t cookie)
+tl::expected<ceph::timespan, bs::error_code> RADOS::check_watch(uint64_t cookie)
 {
-  Objecter::LingerOp *linger_op = reinterpret_cast<Objecter::LingerOp*>(cookie);
-  return impl->objecter->linger_check(linger_op);
+  auto linger_op = reinterpret_cast<Objecter::LingerOp*>(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,
index 28f5ef13caeca804f14a91a8b3a05e5ba4ec34b3..c43763fe578abc60a13e373e07481549f05d936a 100644 (file)
@@ -2512,7 +2512,7 @@ public:
 
   std::map<uint64_t, LingerOp*> linger_ops;
   // we use this just to confirm a cookie is valid before dereferencing the ptr
-  std::set<LingerOp*> linger_ops_set;
+  std::unordered_set<LingerOp*> linger_ops_set;
 
   std::map<ceph_tid_t,PoolStatOp*> poolstat_ops;
   std::map<ceph_tid_t,StatfsOp*> statfs_ops;
@@ -2594,6 +2594,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<typename CT>
   auto linger_callback_flush(CT&& ct) {
     auto consigned = boost::asio::consign(