Home | History | Annotate | Download | only in ipc
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "ipc/ipc_channel_win.h"
      6 
      7 #include <windows.h>
      8 
      9 #include "base/auto_reset.h"
     10 #include "base/bind.h"
     11 #include "base/compiler_specific.h"
     12 #include "base/logging.h"
     13 #include "base/pickle.h"
     14 #include "base/process/process_handle.h"
     15 #include "base/rand_util.h"
     16 #include "base/strings/string_number_conversions.h"
     17 #include "base/strings/utf_string_conversions.h"
     18 #include "base/threading/thread_checker.h"
     19 #include "base/win/scoped_handle.h"
     20 #include "ipc/ipc_listener.h"
     21 #include "ipc/ipc_logging.h"
     22 #include "ipc/ipc_message_utils.h"
     23 
     24 namespace {
     25 
     26 enum DebugFlags {
     27   INIT_DONE = 1 << 0,
     28   CALLED_CONNECT = 1 << 1,
     29   PENDING_CONNECT = 1 << 2,
     30   CONNECT_COMPLETED = 1 << 3,
     31   PIPE_CONNECTED = 1 << 4,
     32   WRITE_MSG = 1 << 5,
     33   READ_MSG = 1 << 6,
     34   WRITE_COMPLETED = 1 << 7,
     35   READ_COMPLETED = 1 << 8,
     36   CLOSED = 1 << 9,
     37   WAIT_FOR_READ = 1 << 10,
     38   WAIT_FOR_WRITE = 1 << 11,
     39   WAIT_FOR_READ_COMPLETE = 1 << 12,
     40   WAIT_FOR_WRITE_COMPLETE = 1 << 13
     41 };
     42 
     43 }  // namespace
     44 
     45 namespace IPC {
     46 
     47 ChannelWin::State::State(ChannelWin* channel) : is_pending(false) {
     48   memset(&context.overlapped, 0, sizeof(context.overlapped));
     49   context.handler = channel;
     50 }
     51 
     52 ChannelWin::State::~State() {
     53   COMPILE_ASSERT(!offsetof(ChannelWin::State, context),
     54                  starts_with_io_context);
     55 }
     56 
     57 ChannelWin::ChannelWin(const IPC::ChannelHandle &channel_handle,
     58                        Mode mode, Listener* listener)
     59     : ChannelReader(listener),
     60       input_state_(this),
     61       output_state_(this),
     62       peer_pid_(base::kNullProcessId),
     63       waiting_connect_(mode & MODE_SERVER_FLAG),
     64       processing_incoming_(false),
     65       validate_client_(false),
     66       writing_(false),
     67       debug_flags_(0),
     68       write_error_(0),
     69       last_write_error_(0),
     70       write_size_(0),
     71       client_secret_(0),
     72       weak_factory_(this) {
     73   CreatePipe(channel_handle, mode);
     74 }
     75 
     76 ChannelWin::~ChannelWin() {
     77   Close();
     78 }
     79 
     80 void ChannelWin::Close() {
     81   if (thread_check_.get()) {
     82     DCHECK(thread_check_->CalledOnValidThread());
     83   }
     84   debug_flags_ |= CLOSED;
     85 
     86   if (input_state_.is_pending || output_state_.is_pending)
     87     CancelIo(pipe_.Get());
     88 
     89   // Closing the handle at this point prevents us from issuing more requests
     90   // form OnIOCompleted().
     91   if (pipe_.IsValid())
     92     pipe_.Close();
     93 
     94   if (input_state_.is_pending)
     95     debug_flags_ |= WAIT_FOR_READ;
     96 
     97   if (output_state_.is_pending)
     98     debug_flags_ |= WAIT_FOR_WRITE;
     99 
    100   // Make sure all IO has completed.
    101   base::Time start = base::Time::Now();
    102   while (input_state_.is_pending || output_state_.is_pending) {
    103     base::MessageLoopForIO::current()->WaitForIOCompletion(INFINITE, this);
    104   }
    105 
    106   while (!output_queue_.empty()) {
    107     Message* m = output_queue_.front();
    108     output_queue_.pop();
    109     delete m;
    110   }
    111 }
    112 
    113 bool ChannelWin::Send(Message* message) {
    114   DCHECK(thread_check_->CalledOnValidThread());
    115   DVLOG(2) << "sending message @" << message << " on channel @" << this
    116            << " with type " << message->type()
    117            << " (" << output_queue_.size() << " in queue)";
    118 
    119 #ifdef IPC_MESSAGE_LOG_ENABLED
    120   Logging::GetInstance()->OnSendMessage(message, "");
    121 #endif
    122 
    123   message->TraceMessageBegin();
    124   output_queue_.push(message);
    125   // ensure waiting to write
    126   if (!waiting_connect_) {
    127     if (!output_state_.is_pending) {
    128       if (!ProcessOutgoingMessages(NULL, 0))
    129         return false;
    130     }
    131   }
    132 
    133   return true;
    134 }
    135 
    136 base::ProcessId ChannelWin::GetPeerPID() const {
    137   return peer_pid_;
    138 }
    139 
    140 base::ProcessId ChannelWin::GetSelfPID() const {
    141   return GetCurrentProcessId();
    142 }
    143 
    144 // static
    145 bool ChannelWin::IsNamedServerInitialized(
    146     const std::string& channel_id) {
    147   if (WaitNamedPipe(PipeName(channel_id, NULL).c_str(), 1))
    148     return true;
    149   // If ERROR_SEM_TIMEOUT occurred, the pipe exists but is handling another
    150   // connection.
    151   return GetLastError() == ERROR_SEM_TIMEOUT;
    152 }
    153 
    154 ChannelWin::ReadState ChannelWin::ReadData(
    155     char* buffer,
    156     int buffer_len,
    157     int* /* bytes_read */) {
    158   if (!pipe_.IsValid())
    159     return READ_FAILED;
    160 
    161   debug_flags_ |= READ_MSG;
    162   DWORD bytes_read = 0;
    163   BOOL ok = ReadFile(pipe_.Get(), buffer, buffer_len,
    164                      &bytes_read, &input_state_.context.overlapped);
    165   if (!ok) {
    166     DWORD err = GetLastError();
    167     if (err == ERROR_IO_PENDING) {
    168       input_state_.is_pending = true;
    169       return READ_PENDING;
    170     }
    171     LOG(ERROR) << "pipe error: " << err;
    172     return READ_FAILED;
    173   }
    174 
    175   // We could return READ_SUCCEEDED here. But the way that this code is
    176   // structured we instead go back to the message loop. Our completion port
    177   // will be signalled even in the "synchronously completed" state.
    178   //
    179   // This allows us to potentially process some outgoing messages and
    180   // interleave other work on this thread when we're getting hammered with
    181   // input messages. Potentially, this could be tuned to be more efficient
    182   // with some testing.
    183   input_state_.is_pending = true;
    184   return READ_PENDING;
    185 }
    186 
    187 bool ChannelWin::WillDispatchInputMessage(Message* msg) {
    188   // Make sure we get a hello when client validation is required.
    189   if (validate_client_)
    190     return IsHelloMessage(*msg);
    191   return true;
    192 }
    193 
    194 void ChannelWin::HandleInternalMessage(const Message& msg) {
    195   DCHECK_EQ(msg.type(), static_cast<unsigned>(Channel::HELLO_MESSAGE_TYPE));
    196   // The hello message contains one parameter containing the PID.
    197   PickleIterator it(msg);
    198   int32 claimed_pid;
    199   bool failed = !it.ReadInt(&claimed_pid);
    200 
    201   if (!failed && validate_client_) {
    202     int32 secret;
    203     failed = it.ReadInt(&secret) ? (secret != client_secret_) : true;
    204   }
    205 
    206   if (failed) {
    207     NOTREACHED();
    208     Close();
    209     listener()->OnChannelError();
    210     return;
    211   }
    212 
    213   peer_pid_ = claimed_pid;
    214   // Validation completed.
    215   validate_client_ = false;
    216   listener()->OnChannelConnected(claimed_pid);
    217 }
    218 
    219 bool ChannelWin::DidEmptyInputBuffers() {
    220   // We don't need to do anything here.
    221   return true;
    222 }
    223 
    224 // static
    225 const base::string16 ChannelWin::PipeName(
    226     const std::string& channel_id, int32* secret) {
    227   std::string name("\\\\.\\pipe\\chrome.");
    228 
    229   // Prevent the shared secret from ending up in the pipe name.
    230   size_t index = channel_id.find_first_of('\\');
    231   if (index != std::string::npos) {
    232     if (secret)  // Retrieve the secret if asked for.
    233       base::StringToInt(channel_id.substr(index + 1), secret);
    234     return base::ASCIIToWide(name.append(channel_id.substr(0, index - 1)));
    235   }
    236 
    237   // This case is here to support predictable named pipes in tests.
    238   if (secret)
    239     *secret = 0;
    240   return base::ASCIIToWide(name.append(channel_id));
    241 }
    242 
    243 bool ChannelWin::CreatePipe(const IPC::ChannelHandle &channel_handle,
    244                             Mode mode) {
    245   DCHECK(!pipe_.IsValid());
    246   base::string16 pipe_name;
    247   // If we already have a valid pipe for channel just copy it.
    248   if (channel_handle.pipe.handle) {
    249     // TODO(rvargas) crbug.com/415294: ChannelHandle should either go away in
    250     // favor of two independent entities (name/file), or it should be a move-
    251     // only type with a base::File member. In any case, this code should not
    252     // call DuplicateHandle.
    253     DCHECK(channel_handle.name.empty());
    254     pipe_name = L"Not Available";  // Just used for LOG
    255     // Check that the given pipe confirms to the specified mode.  We can
    256     // only check for PIPE_TYPE_MESSAGE & PIPE_SERVER_END flags since the
    257     // other flags (PIPE_TYPE_BYTE, and PIPE_CLIENT_END) are defined as 0.
    258     DWORD flags = 0;
    259     GetNamedPipeInfo(channel_handle.pipe.handle, &flags, NULL, NULL, NULL);
    260     DCHECK(!(flags & PIPE_TYPE_MESSAGE));
    261     if (((mode & MODE_SERVER_FLAG) && !(flags & PIPE_SERVER_END)) ||
    262         ((mode & MODE_CLIENT_FLAG) && (flags & PIPE_SERVER_END))) {
    263       LOG(WARNING) << "Inconsistent open mode. Mode :" << mode;
    264       return false;
    265     }
    266     HANDLE local_handle;
    267     if (!DuplicateHandle(GetCurrentProcess(),
    268                          channel_handle.pipe.handle,
    269                          GetCurrentProcess(),
    270                          &local_handle,
    271                          0,
    272                          FALSE,
    273                          DUPLICATE_SAME_ACCESS)) {
    274       LOG(WARNING) << "DuplicateHandle failed. Error :" << GetLastError();
    275       return false;
    276     }
    277     pipe_.Set(local_handle);
    278   } else if (mode & MODE_SERVER_FLAG) {
    279     DCHECK(!channel_handle.pipe.handle);
    280     const DWORD open_mode = PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED |
    281                             FILE_FLAG_FIRST_PIPE_INSTANCE;
    282     pipe_name = PipeName(channel_handle.name, &client_secret_);
    283     validate_client_ = !!client_secret_;
    284     pipe_.Set(CreateNamedPipeW(pipe_name.c_str(),
    285                                open_mode,
    286                                PIPE_TYPE_BYTE | PIPE_READMODE_BYTE,
    287                                1,
    288                                Channel::kReadBufferSize,
    289                                Channel::kReadBufferSize,
    290                                5000,
    291                                NULL));
    292   } else if (mode & MODE_CLIENT_FLAG) {
    293     DCHECK(!channel_handle.pipe.handle);
    294     pipe_name = PipeName(channel_handle.name, &client_secret_);
    295     pipe_.Set(CreateFileW(pipe_name.c_str(),
    296                           GENERIC_READ | GENERIC_WRITE,
    297                           0,
    298                           NULL,
    299                           OPEN_EXISTING,
    300                           SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION |
    301                               FILE_FLAG_OVERLAPPED,
    302                           NULL));
    303   } else {
    304     NOTREACHED();
    305   }
    306 
    307   if (!pipe_.IsValid()) {
    308     // If this process is being closed, the pipe may be gone already.
    309     PLOG(WARNING) << "Unable to create pipe \"" << pipe_name << "\" in "
    310                   << (mode & MODE_SERVER_FLAG ? "server" : "client") << " mode";
    311     return false;
    312   }
    313 
    314   // Create the Hello message to be sent when Connect is called
    315   scoped_ptr<Message> m(new Message(MSG_ROUTING_NONE,
    316                                     HELLO_MESSAGE_TYPE,
    317                                     IPC::Message::PRIORITY_NORMAL));
    318 
    319   // Don't send the secret to the untrusted process, and don't send a secret
    320   // if the value is zero (for IPC backwards compatability).
    321   int32 secret = validate_client_ ? 0 : client_secret_;
    322   if (!m->WriteInt(GetCurrentProcessId()) ||
    323       (secret && !m->WriteUInt32(secret))) {
    324     pipe_.Close();
    325     return false;
    326   }
    327 
    328   debug_flags_ |= INIT_DONE;
    329 
    330   output_queue_.push(m.release());
    331   return true;
    332 }
    333 
    334 bool ChannelWin::Connect() {
    335   DLOG_IF(WARNING, thread_check_.get()) << "Connect called more than once";
    336 
    337   if (!thread_check_.get())
    338     thread_check_.reset(new base::ThreadChecker());
    339 
    340   if (!pipe_.IsValid())
    341     return false;
    342 
    343   base::MessageLoopForIO::current()->RegisterIOHandler(pipe_.Get(), this);
    344 
    345   // Check to see if there is a client connected to our pipe...
    346   if (waiting_connect_)
    347     ProcessConnection();
    348 
    349   if (!input_state_.is_pending) {
    350     // Complete setup asynchronously. By not setting input_state_.is_pending
    351     // to true, we indicate to OnIOCompleted that this is the special
    352     // initialization signal.
    353     base::MessageLoopForIO::current()->PostTask(
    354         FROM_HERE,
    355         base::Bind(&ChannelWin::OnIOCompleted,
    356                    weak_factory_.GetWeakPtr(),
    357                    &input_state_.context,
    358                    0,
    359                    0));
    360   }
    361 
    362   if (!waiting_connect_)
    363     ProcessOutgoingMessages(NULL, 0);
    364   return true;
    365 }
    366 
    367 bool ChannelWin::ProcessConnection() {
    368   DCHECK(thread_check_->CalledOnValidThread());
    369   if (input_state_.is_pending)
    370     input_state_.is_pending = false;
    371 
    372   // Do we have a client connected to our pipe?
    373   if (!pipe_.IsValid())
    374     return false;
    375 
    376   BOOL ok = ConnectNamedPipe(pipe_.Get(), &input_state_.context.overlapped);
    377   debug_flags_ |= CALLED_CONNECT;
    378 
    379   DWORD err = GetLastError();
    380   if (ok) {
    381     // Uhm, the API documentation says that this function should never
    382     // return success when used in overlapped mode.
    383     NOTREACHED();
    384     return false;
    385   }
    386 
    387   switch (err) {
    388   case ERROR_IO_PENDING:
    389     input_state_.is_pending = true;
    390     debug_flags_ |= PENDING_CONNECT;
    391     break;
    392   case ERROR_PIPE_CONNECTED:
    393     debug_flags_ |= PIPE_CONNECTED;
    394     waiting_connect_ = false;
    395     break;
    396   case ERROR_NO_DATA:
    397     // The pipe is being closed.
    398     return false;
    399   default:
    400     NOTREACHED();
    401     return false;
    402   }
    403 
    404   return true;
    405 }
    406 
    407 bool ChannelWin::ProcessOutgoingMessages(
    408     base::MessageLoopForIO::IOContext* context,
    409     DWORD bytes_written) {
    410   DCHECK(!waiting_connect_);  // Why are we trying to send messages if there's
    411                               // no connection?
    412   DCHECK(thread_check_->CalledOnValidThread());
    413 
    414   if (output_state_.is_pending) {
    415     DCHECK(context);
    416     output_state_.is_pending = false;
    417     if (!context || bytes_written == 0) {
    418       DWORD err = GetLastError();
    419       LOG(ERROR) << "pipe error: " << err;
    420       return false;
    421     }
    422     // Message was sent.
    423     CHECK(!output_queue_.empty());
    424     Message* m = output_queue_.front();
    425     output_queue_.pop();
    426     delete m;
    427   }
    428 
    429   if (output_queue_.empty())
    430     return true;
    431 
    432   if (!pipe_.IsValid())
    433     return false;
    434 
    435   // Write to pipe...
    436   Message* m = output_queue_.front();
    437   DCHECK(m->size() <= INT_MAX);
    438   debug_flags_ |= WRITE_MSG;
    439   CHECK(!writing_);
    440   writing_ = true;
    441   write_size_ = static_cast<uint32>(m->size());
    442   write_error_ = 0;
    443   BOOL ok = WriteFile(pipe_.Get(),
    444                       m->data(),
    445                       write_size_,
    446                       NULL,
    447                       &output_state_.context.overlapped);
    448   if (!ok) {
    449     write_error_ = GetLastError();
    450     if (write_error_ == ERROR_IO_PENDING) {
    451       output_state_.is_pending = true;
    452 
    453       DVLOG(2) << "sent pending message @" << m << " on channel @" << this
    454                << " with type " << m->type();
    455 
    456       return true;
    457     }
    458     writing_ = false;
    459     last_write_error_ = write_error_;
    460     LOG(ERROR) << "pipe error: " << write_error_;
    461     return false;
    462   }
    463 
    464   DVLOG(2) << "sent message @" << m << " on channel @" << this
    465            << " with type " << m->type();
    466 
    467   output_state_.is_pending = true;
    468   return true;
    469 }
    470 
    471 void ChannelWin::OnIOCompleted(
    472     base::MessageLoopForIO::IOContext* context,
    473     DWORD bytes_transfered,
    474     DWORD error) {
    475   bool ok = true;
    476   DCHECK(thread_check_->CalledOnValidThread());
    477   if (context == &input_state_.context) {
    478     if (waiting_connect_) {
    479       debug_flags_ |= CONNECT_COMPLETED;
    480       if (!ProcessConnection())
    481         return;
    482       // We may have some messages queued up to send...
    483       if (!output_queue_.empty() && !output_state_.is_pending)
    484         ProcessOutgoingMessages(NULL, 0);
    485       if (input_state_.is_pending)
    486         return;
    487       // else, fall-through and look for incoming messages...
    488     }
    489 
    490     // We don't support recursion through OnMessageReceived yet!
    491     DCHECK(!processing_incoming_);
    492     base::AutoReset<bool> auto_reset_processing_incoming(
    493         &processing_incoming_, true);
    494 
    495     // Process the new data.
    496     if (input_state_.is_pending) {
    497       // This is the normal case for everything except the initialization step.
    498       debug_flags_ |= READ_COMPLETED;
    499       if (debug_flags_ & WAIT_FOR_READ) {
    500         CHECK(!(debug_flags_ & WAIT_FOR_READ_COMPLETE));
    501         debug_flags_ |= WAIT_FOR_READ_COMPLETE;
    502       }
    503       input_state_.is_pending = false;
    504       if (!bytes_transfered)
    505         ok = false;
    506       else if (pipe_.IsValid())
    507         ok = AsyncReadComplete(bytes_transfered);
    508     } else {
    509       DCHECK(!bytes_transfered);
    510     }
    511 
    512     // Request more data.
    513     if (ok)
    514       ok = ProcessIncomingMessages();
    515   } else {
    516     DCHECK(context == &output_state_.context);
    517     CHECK(writing_);
    518     CHECK(output_state_.is_pending);
    519     writing_ = false;
    520     debug_flags_ |= WRITE_COMPLETED;
    521     if (debug_flags_ & WAIT_FOR_WRITE) {
    522       CHECK(!(debug_flags_ & WAIT_FOR_WRITE_COMPLETE));
    523       debug_flags_ |= WAIT_FOR_WRITE_COMPLETE;
    524     }
    525     ok = ProcessOutgoingMessages(context, bytes_transfered);
    526   }
    527   if (!ok && pipe_.IsValid()) {
    528     // We don't want to re-enter Close().
    529     Close();
    530     listener()->OnChannelError();
    531   }
    532 }
    533 
    534 //------------------------------------------------------------------------------
    535 // Channel's methods
    536 
    537 // static
    538 scoped_ptr<Channel> Channel::Create(
    539     const IPC::ChannelHandle &channel_handle, Mode mode, Listener* listener) {
    540   return scoped_ptr<Channel>(
    541       new ChannelWin(channel_handle, mode, listener));
    542 }
    543 
    544 // static
    545 bool Channel::IsNamedServerInitialized(const std::string& channel_id) {
    546   return ChannelWin::IsNamedServerInitialized(channel_id);
    547 }
    548 
    549 // static
    550 std::string Channel::GenerateVerifiedChannelID(const std::string& prefix) {
    551   // Windows pipes can be enumerated by low-privileged processes. So, we
    552   // append a strong random value after the \ character. This value is not
    553   // included in the pipe name, but sent as part of the client hello, to
    554   // hijacking the pipe name to spoof the client.
    555 
    556   std::string id = prefix;
    557   if (!id.empty())
    558     id.append(".");
    559 
    560   int secret;
    561   do {  // Guarantee we get a non-zero value.
    562     secret = base::RandInt(0, std::numeric_limits<int>::max());
    563   } while (secret == 0);
    564 
    565   id.append(GenerateUniqueRandomChannelID());
    566   return id.append(base::StringPrintf("\\%d", secret));
    567 }
    568 
    569 }  // namespace IPC
    570