You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kudu.apache.org by to...@apache.org on 2016/04/21 23:16:03 UTC

incubator-kudu git commit: Fix use-after free in accessing InboundCall's MethodInfo

Repository: incubator-kudu
Updated Branches:
  refs/heads/master bde7294fc -> b6bab2092


Fix use-after free in accessing InboundCall's MethodInfo

This fixes a regression from 38e16b71b881ad1f276da918cae8977a383906a5 in which
a call is being responded to after the underlying service has shut down. In
this case, the call was holding on to a raw pointer to the RpcMethodInfo
object, and that object was being destroyed when the service stopped.

The fix here is to make it reference-counted. This has a slight penalty of some
extra atomic refcount operations, but any other fix would likely be much more
complex.

No new test since client-test was already failing nearly 50% in ASAN/TSAN
builds.

Change-Id: I30304fe6bd2074578e5cfc09ee18ef616d43e687
Reviewed-on: http://gerrit.cloudera.org:8080/2833
Tested-by: Kudu Jenkins
Reviewed-by: Adar Dembo <ad...@cloudera.com>


Project: http://git-wip-us.apache.org/repos/asf/incubator-kudu/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-kudu/commit/b6bab209
Tree: http://git-wip-us.apache.org/repos/asf/incubator-kudu/tree/b6bab209
Diff: http://git-wip-us.apache.org/repos/asf/incubator-kudu/diff/b6bab209

Branch: refs/heads/master
Commit: b6bab20922def643c9b57edef7313ea940dda068
Parents: bde7294
Author: Todd Lipcon <to...@apache.org>
Authored: Thu Apr 21 11:10:57 2016 -0700
Committer: Todd Lipcon <to...@apache.org>
Committed: Thu Apr 21 21:10:25 2016 +0000

----------------------------------------------------------------------
 src/kudu/rpc/inbound_call.h     | 9 +++++----
 src/kudu/rpc/protoc-gen-krpc.cc | 2 +-
 src/kudu/rpc/service_if.h       | 4 ++--
 3 files changed, 8 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kudu/blob/b6bab209/src/kudu/rpc/inbound_call.h
----------------------------------------------------------------------
diff --git a/src/kudu/rpc/inbound_call.h b/src/kudu/rpc/inbound_call.h
index cc35383..7796ef9 100644
--- a/src/kudu/rpc/inbound_call.h
+++ b/src/kudu/rpc/inbound_call.h
@@ -26,6 +26,7 @@
 #include "kudu/gutil/macros.h"
 #include "kudu/gutil/ref_counted.h"
 #include "kudu/rpc/remote_method.h"
+#include "kudu/rpc/service_if.h"
 #include "kudu/rpc/rpc_header.pb.h"
 #include "kudu/rpc/transfer.h"
 #include "kudu/util/faststring.h"
@@ -147,15 +148,15 @@ class InboundCall {
 
   // Associate this call with a particular method that will be invoked
   // by the service.
-  void set_method_info(RpcMethodInfo* info) {
-    method_info_ = info;
+  void set_method_info(scoped_refptr<RpcMethodInfo> info) {
+    method_info_ = std::move(info);
   }
 
   // Return the method associated with this call. This is set just before
   // the call is enqueued onto the service queue, and therefore may be
   // 'nullptr' for much of the lifecycle of a call.
   RpcMethodInfo* method_info() {
-    return method_info_;
+    return method_info_.get();
   }
 
   // When this InboundCall was received (instantiated).
@@ -242,7 +243,7 @@ class InboundCall {
   // After the method has been looked up within the service, this is filled in
   // to point to the information about this method. Acts as a pointer back to
   // per-method info such as tracing.
-  RpcMethodInfo* method_info_;
+  scoped_refptr<RpcMethodInfo> method_info_;
 
   DISALLOW_COPY_AND_ASSIGN(InboundCall);
 };

http://git-wip-us.apache.org/repos/asf/incubator-kudu/blob/b6bab209/src/kudu/rpc/protoc-gen-krpc.cc
----------------------------------------------------------------------
diff --git a/src/kudu/rpc/protoc-gen-krpc.cc b/src/kudu/rpc/protoc-gen-krpc.cc
index 0f8c014..fe05e90 100644
--- a/src/kudu/rpc/protoc-gen-krpc.cc
+++ b/src/kudu/rpc/protoc-gen-krpc.cc
@@ -451,7 +451,7 @@ class CodeGenerator : public ::google::protobuf::compiler::CodeGenerator {
 
         Print(printer, *subs,
               "  {\n"
-              "    unique_ptr<RpcMethodInfo> mi(new RpcMethodInfo());\n"
+              "    scoped_refptr<RpcMethodInfo> mi(new RpcMethodInfo());\n"
               "    mi->req_prototype.reset(new $request$());\n"
               "    mi->resp_prototype.reset(new $response$());\n"
               "    mi->handler_latency_histogram =\n"

http://git-wip-us.apache.org/repos/asf/incubator-kudu/blob/b6bab209/src/kudu/rpc/service_if.h
----------------------------------------------------------------------
diff --git a/src/kudu/rpc/service_if.h b/src/kudu/rpc/service_if.h
index 85d012f..582eab1 100644
--- a/src/kudu/rpc/service_if.h
+++ b/src/kudu/rpc/service_if.h
@@ -45,7 +45,7 @@ class RpcContext;
 // method that they implement. The generic server code implemented
 // by GeneratedServiceIf look up the RpcMethodInfo in order to handle
 // each RPC.
-struct RpcMethodInfo {
+struct RpcMethodInfo : public RefCountedThreadSafe<RpcMethodInfo> {
   // Prototype protobufs for requests and responses.
   // These are empty protobufs which are cloned in order to provide an
   // instance for each request.
@@ -104,7 +104,7 @@ class GeneratedServiceIf : public ServiceIf {
   // call. Methods are inserted by the constructor of the generated subclass.
   // After construction, this map is accessed by multiple threads and therefore
   // must not be modified.
-  std::unordered_map<std::string, std::unique_ptr<RpcMethodInfo>> methods_by_name_;
+  std::unordered_map<std::string, scoped_refptr<RpcMethodInfo>> methods_by_name_;
 };
 
 } // namespace rpc