Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(285)

Unified Diff: remoting/host/security_key/security_key_auth_handler_linux.cc

Issue 2167853004: Removing 'AllowScopedIO' exception from SecurityKeyAuthHandlerLinux (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@temp_dir
Patch Set: More fixes! Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: remoting/host/security_key/security_key_auth_handler_linux.cc
diff --git a/remoting/host/security_key/security_key_auth_handler_linux.cc b/remoting/host/security_key/security_key_auth_handler_linux.cc
index 346a2febb396c3ed14d25a80041e02610ca61be1..b938d0f5522bf3ff301d56578f13bdac5d971f25 100644
--- a/remoting/host/security_key/security_key_auth_handler_linux.cc
+++ b/remoting/host/security_key/security_key_auth_handler_linux.cc
@@ -4,18 +4,29 @@
#include "remoting/host/security_key/security_key_auth_handler.h"
-#include <stdint.h>
#include <unistd.h>
+#include <cstdint>
#include <memory>
#include "base/bind.h"
+#include "base/callback.h"
#include "base/files/file_util.h"
#include "base/lazy_instance.h"
+#include "base/location.h"
#include "base/logging.h"
-#include "base/stl_util.h"
+#include "base/memory/ptr_util.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/single_thread_task_runner.h"
+#include "base/synchronization/lock.h"
+// TODO: DEBUG DEBUG DEBUG -> REMOVE LOGGING
+#include "base/threading/platform_thread.h"
+#include "base/threading/thread.h"
+// END DEBUG DEBUG DEBUG
#include "base/threading/thread_checker.h"
#include "base/threading/thread_restrictions.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "net/base/completion_callback.h"
#include "net/base/net_errors.h"
@@ -53,11 +64,13 @@ namespace remoting {
class SecurityKeyAuthHandlerLinux : public SecurityKeyAuthHandler {
public:
- SecurityKeyAuthHandlerLinux();
+ explicit SecurityKeyAuthHandlerLinux(
+ scoped_refptr<base::SingleThreadTaskRunner> file_task_runner);
~SecurityKeyAuthHandlerLinux() override;
private:
- typedef std::map<int, SecurityKeySocket*> ActiveSockets;
+ // The actual implementation resides in Core class.
+ class Core;
// SecurityKeyAuthHandler interface.
void CreateSecurityKeyConnection() override;
@@ -69,6 +82,54 @@ class SecurityKeyAuthHandlerLinux : public SecurityKeyAuthHandler {
size_t GetActiveConnectionCountForTest() const override;
void SetRequestTimeoutForTest(base::TimeDelta timeout) override;
+ // Ensures SecurityKeyAuthHandlerLinux methods are called on the same thread.
+ base::ThreadChecker thread_checker_;
+
+ // Used to pass security key extension messages to the client.
+ SendMessageCallback send_message_callback_;
+
+ // Timeout used for a request.
+ base::TimeDelta request_timeout_;
+
+ // Used by |core_| to perform File IO via Unix Domain Sockets.
+ scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_;
+
+ // Responsible for handling security key requests on |file_task_runner_|.
+ std::unique_ptr<Core> core_;
+
+ DISALLOW_COPY_AND_ASSIGN(SecurityKeyAuthHandlerLinux);
+};
+
+class SecurityKeyAuthHandlerLinux::Core {
+ public:
+ Core(const SendMessageCallback& send_message_callback,
+ base::TimeDelta timeout);
+ ~Core();
+
+ // Creates the accept socket, binds to it, and begins accepting listeners.
+ // Must be called from the file IO task runner.
+ void StartListening();
+
+ // Returns whether |security_key_connection_id| corresponds to an active
+ // connection. Can be called from any thread.
+ bool IsValidConnectionId(int security_key_connection_id) const;
+
+ // Passes |response| to the socket associated with
+ // |security_key_connection_id|. Must be called from the file IO task runner.
+ void SendClientResponse(int security_key_connection_id,
+ const std::string& response);
+
+ // Sends an SSH error code to the socket assocated with
+ // |security_key_connection_id| and closes it. Must be called from the file
+ // IO task runner.
+ void SendErrorAndCloseConnection(int security_key_connection_id);
+
+ // Returns the number of active connections. Can be called from any thread.
+ size_t GetActiveConnectionCountForTest() const;
+
+ private:
+ typedef std::map<int, std::unique_ptr<SecurityKeySocket>> ActiveSockets;
+
// Starts listening for connection.
void DoAccept();
@@ -101,22 +162,32 @@ class SecurityKeyAuthHandlerLinux : public SecurityKeyAuthHandler {
SendMessageCallback send_message_callback_;
// The last assigned security key connection id.
- int last_connection_id_;
+ int last_connection_id_ = 0;
// Sockets by connection id used to process gnubbyd requests.
ActiveSockets active_sockets_;
+ // Protects access to |active_sockets_|. Marked as mutable so this lock can
+ // be acquired inside methods marked 'const'.
+ mutable base::Lock active_sockets_lock_;
+
// Timeout used for a request.
base::TimeDelta request_timeout_;
- DISALLOW_COPY_AND_ASSIGN(SecurityKeyAuthHandlerLinux);
+ // Used to run |send_message_callback_| on the main thread.
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+
+ base::WeakPtrFactory<Core> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(Core);
};
std::unique_ptr<SecurityKeyAuthHandler> SecurityKeyAuthHandler::Create(
ClientSessionDetails* client_session_details,
- const SendMessageCallback& send_message_callback) {
+ const SendMessageCallback& send_message_callback,
+ scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) {
std::unique_ptr<SecurityKeyAuthHandler> auth_handler(
- new SecurityKeyAuthHandlerLinux());
+ new SecurityKeyAuthHandlerLinux(file_task_runner));
auth_handler->SetSendMessageCallback(send_message_callback);
return auth_handler;
}
@@ -126,54 +197,160 @@ void SecurityKeyAuthHandler::SetSecurityKeySocketName(
g_security_key_socket_name.Get() = security_key_socket_name;
}
-SecurityKeyAuthHandlerLinux::SecurityKeyAuthHandlerLinux()
- : last_connection_id_(0),
- request_timeout_(
- base::TimeDelta::FromSeconds(kDefaultRequestTimeoutSeconds)) {}
+SecurityKeyAuthHandlerLinux::SecurityKeyAuthHandlerLinux(
+ scoped_refptr<base::SingleThreadTaskRunner> file_task_runner)
+ : request_timeout_(
+ base::TimeDelta::FromSeconds(kDefaultRequestTimeoutSeconds)),
+ file_task_runner_(file_task_runner) {
+ LOG(INFO) << "** SecurityKeyAuthHandlerLinux() called on: "
+ << base::PlatformThread::GetName();
+}
SecurityKeyAuthHandlerLinux::~SecurityKeyAuthHandlerLinux() {
- STLDeleteValues(&active_sockets_);
+ if (core_) {
+ file_task_runner_->DeleteSoon(FROM_HERE, core_.release());
+ }
}
void SecurityKeyAuthHandlerLinux::CreateSecurityKeyConnection() {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(!g_security_key_socket_name.Get().empty());
+ DCHECK(!core_);
+ LOG(INFO) << "** CreateSecurityKeyConnection() called on: "
+ << base::PlatformThread::GetName();
+
+ core_.reset(new SecurityKeyAuthHandlerLinux::Core(send_message_callback_,
+ request_timeout_));
+
+ // base::Unretained is safe to use as |core_| is released in the D'tor on
+ // this thread and destroyed on |file_task_runner_|.
+ file_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&SecurityKeyAuthHandlerLinux::Core::StartListening,
+ base::Unretained(core_.get())));
+}
- {
- // DeleteFile() is a blocking operation, but so is creation of the unix
- // socket below. Consider moving this class to a different thread if this
- // causes any problems. See crbug.com/509807.
- // TODO(joedow): Since this code now runs as a host extension, we should
- // perform our IO on a separate thread: crbug.com/591739
- base::ThreadRestrictions::ScopedAllowIO allow_io;
-
- // If the file already exists, a socket in use error is returned.
- base::DeleteFile(g_security_key_socket_name.Get(), false);
+bool SecurityKeyAuthHandlerLinux::IsValidConnectionId(
+ int security_key_connection_id) const {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return core_ && core_->IsValidConnectionId(security_key_connection_id);
+}
+
+void SecurityKeyAuthHandlerLinux::SendClientResponse(
+ int security_key_connection_id,
+ const std::string& response) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(core_);
+
+ if (!IsValidConnectionId(security_key_connection_id)) {
+ LOG(WARNING) << "Unknown gnubby-auth data connection: '"
+ << security_key_connection_id << "'";
+ return;
}
- HOST_LOG << "Listening for security key requests on "
- << g_security_key_socket_name.Get().value();
+ // base::Unretained is safe to use as |core_| is released in the D'tor on
+ // this thread and destroyed on |file_task_runner_|.
+ file_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&SecurityKeyAuthHandlerLinux::Core::SendClientResponse,
+ base::Unretained(core_.get()), security_key_connection_id,
+ base::ConstRef(response)));
+}
+
+void SecurityKeyAuthHandlerLinux::SendErrorAndCloseConnection(
+ int security_key_connection_id) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(core_);
+
+ if (!IsValidConnectionId(security_key_connection_id)) {
+ LOG(WARNING) << "Unknown gnubby-auth data connection: '"
+ << security_key_connection_id << "'";
+ return;
+ }
+
+ // base::Unretained is safe to use as |core_| is released in the D'tor on
+ // this thread and destroyed on |file_task_runner_|.
+ file_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &SecurityKeyAuthHandlerLinux::Core::SendErrorAndCloseConnection,
+ base::Unretained(core_.get()), security_key_connection_id));
+}
+
+void SecurityKeyAuthHandlerLinux::SetSendMessageCallback(
+ const SendMessageCallback& callback) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(!core_) << "Core object already created, callback already set.";
+ send_message_callback_ = callback;
+}
+
+size_t SecurityKeyAuthHandlerLinux::GetActiveConnectionCountForTest() const {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return core_ ? core_->GetActiveConnectionCountForTest() : 0;
+}
+
+void SecurityKeyAuthHandlerLinux::SetRequestTimeoutForTest(
+ base::TimeDelta timeout) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(!core_) << "Core object already created, timeout already set.";
+ request_timeout_ = timeout;
+}
+
+SecurityKeyAuthHandlerLinux::Core::Core(
+ const SendMessageCallback& send_message_callback,
+ base::TimeDelta timeout)
+ : send_message_callback_(send_message_callback),
+ request_timeout_(timeout),
+ weak_factory_(this) {
+ LOG(INFO) << "** Core() called on: " << base::PlatformThread::GetName();
+ thread_checker_.DetachFromThread();
+ main_task_runner_ = base::ThreadTaskRunnerHandle::Get();
+}
+
+SecurityKeyAuthHandlerLinux::Core::~Core() {
+ LOG(INFO) << "** ~Core() called on: " << base::PlatformThread::GetName();
+}
+
+void SecurityKeyAuthHandlerLinux::Core::StartListening() {
+ LOG(INFO) << "** Core::StartListening() called on: "
+ << base::PlatformThread::GetName();
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(!auth_socket_);
+
+ // If the file already exists, a socket in use error is returned.
+ base::DeleteFile(g_security_key_socket_name.Get(), false);
auth_socket_.reset(
new net::UnixDomainServerSocket(base::Bind(MatchUid), false));
+
int rv = auth_socket_->BindAndListen(g_security_key_socket_name.Get().value(),
/*backlog=*/1);
if (rv != net::OK) {
LOG(ERROR) << "Failed to open socket for auth requests: '" << rv << "'";
return;
}
+
+ HOST_LOG << "Listening for security key requests on "
+ << g_security_key_socket_name.Get().value();
+
DoAccept();
}
-bool SecurityKeyAuthHandlerLinux::IsValidConnectionId(
+bool SecurityKeyAuthHandlerLinux::Core::IsValidConnectionId(
int security_key_connection_id) const {
+ LOG(INFO) << "** Core::IsValidConnectionId() called on: "
+ << base::PlatformThread::GetName();
+ base::AutoLock auto_lock(active_sockets_lock_);
return GetSocketForConnectionId(security_key_connection_id) !=
active_sockets_.end();
}
-void SecurityKeyAuthHandlerLinux::SendClientResponse(
+void SecurityKeyAuthHandlerLinux::Core::SendClientResponse(
int security_key_connection_id,
const std::string& response) {
+ LOG(INFO) << "** Core::SendClientResponse() called on: "
+ << base::PlatformThread::GetName();
+ DCHECK(thread_checker_.CalledOnValidThread());
+
ActiveSockets::const_iterator iter =
GetSocketForConnectionId(security_key_connection_id);
if (iter != active_sockets_.end()) {
@@ -184,8 +361,12 @@ void SecurityKeyAuthHandlerLinux::SendClientResponse(
}
}
-void SecurityKeyAuthHandlerLinux::SendErrorAndCloseConnection(
+void SecurityKeyAuthHandlerLinux::Core::SendErrorAndCloseConnection(
int security_key_connection_id) {
+ LOG(INFO) << "** Core::SendErrorAndCloseConnection() called on: "
+ << base::PlatformThread::GetName();
+ DCHECK(thread_checker_.CalledOnValidThread());
+
ActiveSockets::const_iterator iter =
GetSocketForConnectionId(security_key_connection_id);
if (iter != active_sockets_.end()) {
@@ -197,29 +378,29 @@ void SecurityKeyAuthHandlerLinux::SendErrorAndCloseConnection(
}
}
-void SecurityKeyAuthHandlerLinux::SetSendMessageCallback(
- const SendMessageCallback& callback) {
- send_message_callback_ = callback;
-}
-
-size_t SecurityKeyAuthHandlerLinux::GetActiveConnectionCountForTest() const {
+size_t SecurityKeyAuthHandlerLinux::Core::GetActiveConnectionCountForTest()
+ const {
+ base::AutoLock auto_lock(active_sockets_lock_);
return active_sockets_.size();
-}
+};
-void SecurityKeyAuthHandlerLinux::SetRequestTimeoutForTest(
- base::TimeDelta timeout) {
- request_timeout_ = timeout;
-}
+void SecurityKeyAuthHandlerLinux::Core::DoAccept() {
+ LOG(INFO) << "** Core::DoAccept() called on: "
+ << base::PlatformThread::GetName();
+ DCHECK(thread_checker_.CalledOnValidThread());
-void SecurityKeyAuthHandlerLinux::DoAccept() {
int result = auth_socket_->Accept(
- &accept_socket_, base::Bind(&SecurityKeyAuthHandlerLinux::OnAccepted,
- base::Unretained(this)));
- if (result != net::ERR_IO_PENDING)
+ &accept_socket_,
+ base::Bind(&SecurityKeyAuthHandlerLinux::Core::OnAccepted,
+ weak_factory_.GetWeakPtr()));
+ if (result != net::ERR_IO_PENDING) {
OnAccepted(result);
+ }
}
-void SecurityKeyAuthHandlerLinux::OnAccepted(int result) {
+void SecurityKeyAuthHandlerLinux::Core::OnAccepted(int result) {
+ LOG(INFO) << "** Core::OnAccepted() called on: "
+ << base::PlatformThread::GetName();
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK_NE(net::ERR_IO_PENDING, result);
@@ -231,19 +412,24 @@ void SecurityKeyAuthHandlerLinux::OnAccepted(int result) {
int security_key_connection_id = ++last_connection_id_;
SecurityKeySocket* socket = new SecurityKeySocket(
std::move(accept_socket_), request_timeout_,
- base::Bind(&SecurityKeyAuthHandlerLinux::RequestTimedOut,
- base::Unretained(this), security_key_connection_id));
- active_sockets_[security_key_connection_id] = socket;
+ base::Bind(&SecurityKeyAuthHandlerLinux::Core::RequestTimedOut,
+ weak_factory_.GetWeakPtr(), security_key_connection_id));
+ {
+ base::AutoLock auto_lock(active_sockets_lock_);
+ active_sockets_[security_key_connection_id] = base::WrapUnique(socket);
+ }
socket->StartReadingRequest(
- base::Bind(&SecurityKeyAuthHandlerLinux::OnReadComplete,
- base::Unretained(this), security_key_connection_id));
+ base::Bind(&SecurityKeyAuthHandlerLinux::Core::OnReadComplete,
+ weak_factory_.GetWeakPtr(), security_key_connection_id));
// Continue accepting new connections.
DoAccept();
}
-void SecurityKeyAuthHandlerLinux::OnReadComplete(
+void SecurityKeyAuthHandlerLinux::Core::OnReadComplete(
int security_key_connection_id) {
+ LOG(INFO) << "** Core::OnReadComplete() called on: "
+ << base::PlatformThread::GetName();
DCHECK(thread_checker_.CalledOnValidThread());
ActiveSockets::const_iterator iter =
@@ -256,33 +442,43 @@ void SecurityKeyAuthHandlerLinux::OnReadComplete(
}
HOST_LOG << "Received security key request: " << GetCommandCode(request_data);
- send_message_callback_.Run(security_key_connection_id, request_data);
+ main_task_runner_->PostTask(
+ FROM_HERE, base::Bind(send_message_callback_, security_key_connection_id,
+ request_data));
iter->second->StartReadingRequest(
- base::Bind(&SecurityKeyAuthHandlerLinux::OnReadComplete,
- base::Unretained(this), security_key_connection_id));
+ base::Bind(&SecurityKeyAuthHandlerLinux::Core::OnReadComplete,
+ weak_factory_.GetWeakPtr(), security_key_connection_id));
}
-SecurityKeyAuthHandlerLinux::ActiveSockets::const_iterator
-SecurityKeyAuthHandlerLinux::GetSocketForConnectionId(
+SecurityKeyAuthHandlerLinux::Core::ActiveSockets::const_iterator
+SecurityKeyAuthHandlerLinux::Core::GetSocketForConnectionId(
int security_key_connection_id) const {
return active_sockets_.find(security_key_connection_id);
}
-void SecurityKeyAuthHandlerLinux::SendErrorAndCloseActiveSocket(
+void SecurityKeyAuthHandlerLinux::Core::SendErrorAndCloseActiveSocket(
const ActiveSockets::const_iterator& iter) {
+ LOG(INFO) << "** Core::SendErrorAndCloseActiveSocket() called on: "
+ << base::PlatformThread::GetName();
+ DCHECK(thread_checker_.CalledOnValidThread());
+
iter->second->SendSshError();
- delete iter->second;
- active_sockets_.erase(iter);
+ {
+ base::AutoLock auto_lock(active_sockets_lock_);
+ active_sockets_.erase(iter);
+ }
}
-void SecurityKeyAuthHandlerLinux::RequestTimedOut(
+void SecurityKeyAuthHandlerLinux::Core::RequestTimedOut(
int security_key_connection_id) {
+ DCHECK(thread_checker_.CalledOnValidThread());
HOST_LOG << "SecurityKey request timed out";
ActiveSockets::const_iterator iter =
- active_sockets_.find(security_key_connection_id);
- if (iter != active_sockets_.end())
+ GetSocketForConnectionId(security_key_connection_id);
+ if (iter != active_sockets_.end()) {
SendErrorAndCloseActiveSocket(iter);
+ }
}
} // namespace remoting

Powered by Google App Engine
This is Rietveld 408576698