| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ipc/ipc_channel_posix.h" | 5 #include "ipc/ipc_channel_posix.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #include <stddef.h> | 9 #include <stddef.h> |
| 10 #include <sys/types.h> | 10 #include <sys/types.h> |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 base::AutoLock locked(lock_); | 95 base::AutoLock locked(lock_); |
| 96 | 96 |
| 97 ChannelToFDMap::const_iterator i = map_.find(channel_id); | 97 ChannelToFDMap::const_iterator i = map_.find(channel_id); |
| 98 if (i == map_.end()) | 98 if (i == map_.end()) |
| 99 return -1; | 99 return -1; |
| 100 return i->second; | 100 return i->second; |
| 101 } | 101 } |
| 102 | 102 |
| 103 // Remove the mapping for the given channel id. No error is signaled if the | 103 // Remove the mapping for the given channel id. No error is signaled if the |
| 104 // channel_id doesn't exist | 104 // channel_id doesn't exist |
| 105 void RemoveAndClose(const std::string& channel_id) { | 105 void Remove(const std::string& channel_id) { |
| 106 base::AutoLock locked(lock_); | 106 base::AutoLock locked(lock_); |
| 107 | 107 map_.erase(channel_id); |
| 108 ChannelToFDMap::iterator i = map_.find(channel_id); | |
| 109 if (i != map_.end()) { | |
| 110 if (HANDLE_EINTR(close(i->second)) < 0) | |
| 111 PLOG(ERROR) << "close " << channel_id; | |
| 112 map_.erase(i); | |
| 113 } | |
| 114 } | 108 } |
| 115 | 109 |
| 116 // Insert a mapping from @channel_id to @fd. It's a fatal error to insert a | 110 // Insert a mapping from @channel_id to @fd. It's a fatal error to insert a |
| 117 // mapping if one already exists for the given channel_id | 111 // mapping if one already exists for the given channel_id |
| 118 void Insert(const std::string& channel_id, int fd) { | 112 void Insert(const std::string& channel_id, int fd) { |
| 119 base::AutoLock locked(lock_); | 113 base::AutoLock locked(lock_); |
| 120 DCHECK_NE(-1, fd); | 114 DCHECK_NE(-1, fd); |
| 121 | 115 |
| 122 ChannelToFDMap::const_iterator i = map_.find(channel_id); | 116 ChannelToFDMap::const_iterator i = map_.find(channel_id); |
| 123 CHECK(i == map_.end()) << "Creating second IPC server (fd " << fd << ") " | 117 CHECK(i == map_.end()) << "Creating second IPC server (fd " << fd << ") " |
| (...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 396 LOG(ERROR) << "Bad mode: " << mode_; | 390 LOG(ERROR) << "Bad mode: " << mode_; |
| 397 return false; | 391 return false; |
| 398 } | 392 } |
| 399 } else { | 393 } else { |
| 400 local_pipe = PipeMap::GetInstance()->Lookup(pipe_name_); | 394 local_pipe = PipeMap::GetInstance()->Lookup(pipe_name_); |
| 401 if (mode_ & MODE_CLIENT_FLAG) { | 395 if (mode_ & MODE_CLIENT_FLAG) { |
| 402 if (local_pipe != -1) { | 396 if (local_pipe != -1) { |
| 403 // Case 3 from comment above. | 397 // Case 3 from comment above. |
| 404 // We only allow one connection. | 398 // We only allow one connection. |
| 405 local_pipe = HANDLE_EINTR(dup(local_pipe)); | 399 local_pipe = HANDLE_EINTR(dup(local_pipe)); |
| 406 PipeMap::GetInstance()->RemoveAndClose(pipe_name_); | 400 PipeMap::GetInstance()->Remove(pipe_name_); |
| 407 } else { | 401 } else { |
| 408 // Case 4a from comment above. | 402 // Case 4a from comment above. |
| 409 // Guard against inappropriate reuse of the initial IPC channel. If | 403 // Guard against inappropriate reuse of the initial IPC channel. If |
| 410 // an IPC channel closes and someone attempts to reuse it by name, the | 404 // an IPC channel closes and someone attempts to reuse it by name, the |
| 411 // initial channel must not be recycled here. http://crbug.com/26754. | 405 // initial channel must not be recycled here. http://crbug.com/26754. |
| 412 static bool used_initial_channel = false; | 406 static bool used_initial_channel = false; |
| 413 if (used_initial_channel) { | 407 if (used_initial_channel) { |
| 414 LOG(FATAL) << "Denying attempt to reuse initial IPC channel for " | 408 LOG(FATAL) << "Denying attempt to reuse initial IPC channel for " |
| 415 << pipe_name_; | 409 << pipe_name_; |
| 416 return false; | 410 return false; |
| 417 } | 411 } |
| 418 used_initial_channel = true; | 412 used_initial_channel = true; |
| 419 | 413 |
| 420 local_pipe = | 414 local_pipe = |
| 421 base::GlobalDescriptors::GetInstance()->Get(kPrimaryIPCChannel); | 415 base::GlobalDescriptors::GetInstance()->Get(kPrimaryIPCChannel); |
| 422 } | 416 } |
| 423 } else if (mode_ & MODE_SERVER_FLAG) { | 417 } else if (mode_ & MODE_SERVER_FLAG) { |
| 424 // Case 4b from comment above. | 418 // Case 4b from comment above. |
| 425 if (local_pipe != -1) { | 419 if (local_pipe != -1) { |
| 426 LOG(ERROR) << "Server already exists for " << pipe_name_; | 420 LOG(ERROR) << "Server already exists for " << pipe_name_; |
| 427 return false; | 421 return false; |
| 428 } | 422 } |
| 423 base::AutoLock lock(client_pipe_lock_); |
| 429 if (!SocketPair(&local_pipe, &client_pipe_)) | 424 if (!SocketPair(&local_pipe, &client_pipe_)) |
| 430 return false; | 425 return false; |
| 431 PipeMap::GetInstance()->Insert(pipe_name_, client_pipe_); | 426 PipeMap::GetInstance()->Insert(pipe_name_, client_pipe_); |
| 432 } else { | 427 } else { |
| 433 LOG(ERROR) << "Bad mode: " << mode_; | 428 LOG(ERROR) << "Bad mode: " << mode_; |
| 434 return false; | 429 return false; |
| 435 } | 430 } |
| 436 } | 431 } |
| 437 | 432 |
| 438 #if defined(IPC_USES_READWRITE) | 433 #if defined(IPC_USES_READWRITE) |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 522 PLOG(ERROR) << "pipe error (" << pipe_ << ")"; | 517 PLOG(ERROR) << "pipe error (" << pipe_ << ")"; |
| 523 return false; | 518 return false; |
| 524 } | 519 } |
| 525 } else if (bytes_read == 0) { | 520 } else if (bytes_read == 0) { |
| 526 // The pipe has closed... | 521 // The pipe has closed... |
| 527 return false; | 522 return false; |
| 528 } | 523 } |
| 529 } | 524 } |
| 530 DCHECK(bytes_read); | 525 DCHECK(bytes_read); |
| 531 | 526 |
| 532 if (client_pipe_ != -1) { | 527 CloseClientFileDescriptor(); |
| 533 PipeMap::GetInstance()->RemoveAndClose(pipe_name_); | |
| 534 client_pipe_ = -1; | |
| 535 } | |
| 536 | 528 |
| 537 // a pointer to an array of |num_wire_fds| file descriptors from the read | 529 // a pointer to an array of |num_wire_fds| file descriptors from the read |
| 538 const int* wire_fds = NULL; | 530 const int* wire_fds = NULL; |
| 539 unsigned num_wire_fds = 0; | 531 unsigned num_wire_fds = 0; |
| 540 | 532 |
| 541 // walk the list of control messages and, if we find an array of file | 533 // walk the list of control messages and, if we find an array of file |
| 542 // descriptors, save a pointer to the array | 534 // descriptors, save a pointer to the array |
| 543 | 535 |
| 544 // This next if statement is to work around an OSX issue where | 536 // This next if statement is to work around an OSX issue where |
| 545 // CMSG_FIRSTHDR will return non-NULL in the case that controllen == 0. | 537 // CMSG_FIRSTHDR will return non-NULL in the case that controllen == 0. |
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 909 #endif // IPC_MESSAGE_LOG_ENABLED | 901 #endif // IPC_MESSAGE_LOG_ENABLED |
| 910 | 902 |
| 911 output_queue_.push(message); | 903 output_queue_.push(message); |
| 912 if (!is_blocked_on_write_ && !waiting_connect_) { | 904 if (!is_blocked_on_write_ && !waiting_connect_) { |
| 913 return ProcessOutgoingMessages(); | 905 return ProcessOutgoingMessages(); |
| 914 } | 906 } |
| 915 | 907 |
| 916 return true; | 908 return true; |
| 917 } | 909 } |
| 918 | 910 |
| 919 int Channel::ChannelImpl::GetClientFileDescriptor() const { | 911 int Channel::ChannelImpl::GetClientFileDescriptor() { |
| 912 base::AutoLock lock(client_pipe_lock_); |
| 920 return client_pipe_; | 913 return client_pipe_; |
| 921 } | 914 } |
| 922 | 915 |
| 916 int Channel::ChannelImpl::TakeClientFileDescriptor() { |
| 917 base::AutoLock lock(client_pipe_lock_); |
| 918 int fd = client_pipe_; |
| 919 if (client_pipe_ != -1) { |
| 920 PipeMap::GetInstance()->Remove(pipe_name_); |
| 921 client_pipe_ = -1; |
| 922 } |
| 923 return fd; |
| 924 } |
| 925 |
| 926 void Channel::ChannelImpl::CloseClientFileDescriptor() { |
| 927 base::AutoLock lock(client_pipe_lock_); |
| 928 if (client_pipe_ != -1) { |
| 929 PipeMap::GetInstance()->Remove(pipe_name_); |
| 930 if (HANDLE_EINTR(close(client_pipe_)) < 0) |
| 931 PLOG(ERROR) << "close " << pipe_name_; |
| 932 client_pipe_ = -1; |
| 933 } |
| 934 } |
| 935 |
| 923 bool Channel::ChannelImpl::AcceptsConnections() const { | 936 bool Channel::ChannelImpl::AcceptsConnections() const { |
| 924 return server_listen_pipe_ != -1; | 937 return server_listen_pipe_ != -1; |
| 925 } | 938 } |
| 926 | 939 |
| 927 bool Channel::ChannelImpl::HasAcceptedConnection() const { | 940 bool Channel::ChannelImpl::HasAcceptedConnection() const { |
| 928 return AcceptsConnections() && pipe_ != -1; | 941 return AcceptsConnections() && pipe_ != -1; |
| 929 } | 942 } |
| 930 | 943 |
| 931 bool Channel::ChannelImpl::GetClientEuid(uid_t* client_euid) const { | 944 bool Channel::ChannelImpl::GetClientEuid(uid_t* client_euid) const { |
| 932 DCHECK(HasAcceptedConnection()); | 945 DCHECK(HasAcceptedConnection()); |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1166 must_unlink_ = false; | 1179 must_unlink_ = false; |
| 1167 } | 1180 } |
| 1168 if (server_listen_pipe_ != -1) { | 1181 if (server_listen_pipe_ != -1) { |
| 1169 if (HANDLE_EINTR(close(server_listen_pipe_)) < 0) | 1182 if (HANDLE_EINTR(close(server_listen_pipe_)) < 0) |
| 1170 PLOG(ERROR) << "close " << server_listen_pipe_; | 1183 PLOG(ERROR) << "close " << server_listen_pipe_; |
| 1171 server_listen_pipe_ = -1; | 1184 server_listen_pipe_ = -1; |
| 1172 // Unregister libevent for the listening socket and close it. | 1185 // Unregister libevent for the listening socket and close it. |
| 1173 server_listen_connection_watcher_.StopWatchingFileDescriptor(); | 1186 server_listen_connection_watcher_.StopWatchingFileDescriptor(); |
| 1174 } | 1187 } |
| 1175 | 1188 |
| 1176 if (client_pipe_ != -1) { | 1189 CloseClientFileDescriptor(); |
| 1177 PipeMap::GetInstance()->RemoveAndClose(pipe_name_); | |
| 1178 client_pipe_ = -1; | |
| 1179 } | |
| 1180 } | 1190 } |
| 1181 | 1191 |
| 1182 //------------------------------------------------------------------------------ | 1192 //------------------------------------------------------------------------------ |
| 1183 // Channel's methods simply call through to ChannelImpl. | 1193 // Channel's methods simply call through to ChannelImpl. |
| 1184 Channel::Channel(const IPC::ChannelHandle& channel_handle, Mode mode, | 1194 Channel::Channel(const IPC::ChannelHandle& channel_handle, Mode mode, |
| 1185 Listener* listener) | 1195 Listener* listener) |
| 1186 : channel_impl_(new ChannelImpl(channel_handle, mode, listener)) { | 1196 : channel_impl_(new ChannelImpl(channel_handle, mode, listener)) { |
| 1187 } | 1197 } |
| 1188 | 1198 |
| 1189 Channel::~Channel() { | 1199 Channel::~Channel() { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1203 } | 1213 } |
| 1204 | 1214 |
| 1205 bool Channel::Send(Message* message) { | 1215 bool Channel::Send(Message* message) { |
| 1206 return channel_impl_->Send(message); | 1216 return channel_impl_->Send(message); |
| 1207 } | 1217 } |
| 1208 | 1218 |
| 1209 int Channel::GetClientFileDescriptor() const { | 1219 int Channel::GetClientFileDescriptor() const { |
| 1210 return channel_impl_->GetClientFileDescriptor(); | 1220 return channel_impl_->GetClientFileDescriptor(); |
| 1211 } | 1221 } |
| 1212 | 1222 |
| 1223 int Channel::TakeClientFileDescriptor() { |
| 1224 return channel_impl_->TakeClientFileDescriptor(); |
| 1225 } |
| 1226 |
| 1213 bool Channel::AcceptsConnections() const { | 1227 bool Channel::AcceptsConnections() const { |
| 1214 return channel_impl_->AcceptsConnections(); | 1228 return channel_impl_->AcceptsConnections(); |
| 1215 } | 1229 } |
| 1216 | 1230 |
| 1217 bool Channel::HasAcceptedConnection() const { | 1231 bool Channel::HasAcceptedConnection() const { |
| 1218 return channel_impl_->HasAcceptedConnection(); | 1232 return channel_impl_->HasAcceptedConnection(); |
| 1219 } | 1233 } |
| 1220 | 1234 |
| 1221 bool Channel::GetClientEuid(uid_t* client_euid) const { | 1235 bool Channel::GetClientEuid(uid_t* client_euid) const { |
| 1222 return channel_impl_->GetClientEuid(client_euid); | 1236 return channel_impl_->GetClientEuid(client_euid); |
| 1223 } | 1237 } |
| 1224 | 1238 |
| 1225 void Channel::ResetToAcceptingConnectionState() { | 1239 void Channel::ResetToAcceptingConnectionState() { |
| 1226 channel_impl_->ResetToAcceptingConnectionState(); | 1240 channel_impl_->ResetToAcceptingConnectionState(); |
| 1227 } | 1241 } |
| 1228 | 1242 |
| 1229 // static | 1243 // static |
| 1230 bool Channel::IsNamedServerInitialized(const std::string& channel_id) { | 1244 bool Channel::IsNamedServerInitialized(const std::string& channel_id) { |
| 1231 return ChannelImpl::IsNamedServerInitialized(channel_id); | 1245 return ChannelImpl::IsNamedServerInitialized(channel_id); |
| 1232 } | 1246 } |
| 1233 | 1247 |
| 1234 #if defined(OS_LINUX) | 1248 #if defined(OS_LINUX) |
| 1235 // static | 1249 // static |
| 1236 void Channel::SetGlobalPid(int pid) { | 1250 void Channel::SetGlobalPid(int pid) { |
| 1237 ChannelImpl::SetGlobalPid(pid); | 1251 ChannelImpl::SetGlobalPid(pid); |
| 1238 } | 1252 } |
| 1239 #endif // OS_LINUX | 1253 #endif // OS_LINUX |
| 1240 | 1254 |
| 1241 } // namespace IPC | 1255 } // namespace IPC |
| OLD | NEW |