Commit d30fe32c authored by rpaquay's avatar rpaquay Committed by Commit bot

This looks like a clear case of "use-after-delete": Given DNS resolution

can take some time to complete, the re-use of a raw pointer stored as
member variable (Socket*) is likely to be the root cause of this crash.

This can happen is a socket is destroyed in between a call to "connect"
(or "send") and the DNS resolution callback is invoked.

Both the SocketConnectFunction and SocketSendFunction used to keep
a raw pointer to the Socket instance. A call to "destroy" at the
"right" time would free the socket instance, leaving both function
to access a released object.

The fix in this CL is to re-aquire the Socket instance using a
socket_id instead of re-using the Socket* instance. If the socket
has been destroyed, the socket_id is invalid, and the function fails
gracefully.

BUG=416741

Review URL: https://codereview.chromium.org/608083002

Cr-Commit-Position: refs/heads/master@{#297076}
parent 0d523306
...@@ -184,7 +184,8 @@ bool SocketDestroyFunction::Prepare() { ...@@ -184,7 +184,8 @@ bool SocketDestroyFunction::Prepare() {
void SocketDestroyFunction::Work() { RemoveSocket(socket_id_); } void SocketDestroyFunction::Work() { RemoveSocket(socket_id_); }
SocketConnectFunction::SocketConnectFunction() SocketConnectFunction::SocketConnectFunction()
: socket_id_(0), hostname_(), port_(0), socket_(NULL) {} : socket_id_(0), hostname_(), port_(0) {
}
SocketConnectFunction::~SocketConnectFunction() {} SocketConnectFunction::~SocketConnectFunction() {}
...@@ -196,18 +197,18 @@ bool SocketConnectFunction::Prepare() { ...@@ -196,18 +197,18 @@ bool SocketConnectFunction::Prepare() {
} }
void SocketConnectFunction::AsyncWorkStart() { void SocketConnectFunction::AsyncWorkStart() {
socket_ = GetSocket(socket_id_); Socket* socket = GetSocket(socket_id_);
if (!socket_) { if (!socket) {
error_ = kSocketNotFoundError; error_ = kSocketNotFoundError;
SetResult(new base::FundamentalValue(-1)); SetResult(new base::FundamentalValue(-1));
AsyncWorkCompleted(); AsyncWorkCompleted();
return; return;
} }
socket_->set_hostname(hostname_); socket->set_hostname(hostname_);
SocketPermissionRequest::OperationType operation_type; SocketPermissionRequest::OperationType operation_type;
switch (socket_->GetSocketType()) { switch (socket->GetSocketType()) {
case Socket::TYPE_TCP: case Socket::TYPE_TCP:
operation_type = SocketPermissionRequest::TCP_CONNECT; operation_type = SocketPermissionRequest::TCP_CONNECT;
break; break;
...@@ -242,9 +243,17 @@ void SocketConnectFunction::AfterDnsLookup(int lookup_result) { ...@@ -242,9 +243,17 @@ void SocketConnectFunction::AfterDnsLookup(int lookup_result) {
} }
void SocketConnectFunction::StartConnect() { void SocketConnectFunction::StartConnect() {
socket_->Connect(resolved_address_, Socket* socket = GetSocket(socket_id_);
port_, if (!socket) {
base::Bind(&SocketConnectFunction::OnConnect, this)); error_ = kSocketNotFoundError;
SetResult(new base::FundamentalValue(-1));
AsyncWorkCompleted();
return;
}
socket->Connect(resolved_address_,
port_,
base::Bind(&SocketConnectFunction::OnConnect, this));
} }
void SocketConnectFunction::OnConnect(int result) { void SocketConnectFunction::OnConnect(int result) {
...@@ -489,11 +498,8 @@ void SocketRecvFromFunction::OnCompleted(int bytes_read, ...@@ -489,11 +498,8 @@ void SocketRecvFromFunction::OnCompleted(int bytes_read,
} }
SocketSendToFunction::SocketSendToFunction() SocketSendToFunction::SocketSendToFunction()
: socket_id_(0), : socket_id_(0), io_buffer_(NULL), io_buffer_size_(0), port_(0) {
io_buffer_(NULL), }
io_buffer_size_(0),
port_(0),
socket_(NULL) {}
SocketSendToFunction::~SocketSendToFunction() {} SocketSendToFunction::~SocketSendToFunction() {}
...@@ -510,15 +516,15 @@ bool SocketSendToFunction::Prepare() { ...@@ -510,15 +516,15 @@ bool SocketSendToFunction::Prepare() {
} }
void SocketSendToFunction::AsyncWorkStart() { void SocketSendToFunction::AsyncWorkStart() {
socket_ = GetSocket(socket_id_); Socket* socket = GetSocket(socket_id_);
if (!socket_) { if (!socket) {
error_ = kSocketNotFoundError; error_ = kSocketNotFoundError;
SetResult(new base::FundamentalValue(-1)); SetResult(new base::FundamentalValue(-1));
AsyncWorkCompleted(); AsyncWorkCompleted();
return; return;
} }
if (socket_->GetSocketType() == Socket::TYPE_UDP) { if (socket->GetSocketType() == Socket::TYPE_UDP) {
SocketPermission::CheckParam param( SocketPermission::CheckParam param(
SocketPermissionRequest::UDP_SEND_TO, hostname_, port_); SocketPermissionRequest::UDP_SEND_TO, hostname_, port_);
if (!extension()->permissions_data()->CheckAPIPermissionWithParam( if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
...@@ -543,11 +549,19 @@ void SocketSendToFunction::AfterDnsLookup(int lookup_result) { ...@@ -543,11 +549,19 @@ void SocketSendToFunction::AfterDnsLookup(int lookup_result) {
} }
void SocketSendToFunction::StartSendTo() { void SocketSendToFunction::StartSendTo() {
socket_->SendTo(io_buffer_, Socket* socket = GetSocket(socket_id_);
io_buffer_size_, if (!socket) {
resolved_address_, error_ = kSocketNotFoundError;
port_, SetResult(new base::FundamentalValue(-1));
base::Bind(&SocketSendToFunction::OnCompleted, this)); AsyncWorkCompleted();
return;
}
socket->SendTo(io_buffer_,
io_buffer_size_,
resolved_address_,
port_,
base::Bind(&SocketSendToFunction::OnCompleted, this));
} }
void SocketSendToFunction::OnCompleted(int bytes_written) { void SocketSendToFunction::OnCompleted(int bytes_written) {
......
...@@ -204,7 +204,6 @@ class SocketConnectFunction : public SocketExtensionWithDnsLookupFunction { ...@@ -204,7 +204,6 @@ class SocketConnectFunction : public SocketExtensionWithDnsLookupFunction {
int socket_id_; int socket_id_;
std::string hostname_; std::string hostname_;
int port_; int port_;
Socket* socket_;
}; };
class SocketDisconnectFunction : public SocketAsyncApiFunction { class SocketDisconnectFunction : public SocketAsyncApiFunction {
...@@ -359,7 +358,6 @@ class SocketSendToFunction : public SocketExtensionWithDnsLookupFunction { ...@@ -359,7 +358,6 @@ class SocketSendToFunction : public SocketExtensionWithDnsLookupFunction {
size_t io_buffer_size_; size_t io_buffer_size_;
std::string hostname_; std::string hostname_;
int port_; int port_;
Socket* socket_;
}; };
class SocketSetKeepAliveFunction : public SocketAsyncApiFunction { class SocketSetKeepAliveFunction : public SocketAsyncApiFunction {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment