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 <stdio.h> 6#include <string> 7#include <sstream> 8 9#include "base/message_loop/message_loop.h" 10#include "base/threading/platform_thread.h" 11#include "ipc/ipc_test_base.h" 12#include "testing/gtest/include/gtest/gtest.h" 13 14// IPC messages for testing ---------------------------------------------------- 15 16#define IPC_MESSAGE_IMPL 17#include "ipc/ipc_message_macros.h" 18 19#define IPC_MESSAGE_START TestMsgStart 20 21// Generic message class that is an int followed by a wstring. 22IPC_MESSAGE_CONTROL2(MsgClassIS, int, std::wstring) 23 24// Generic message class that is a wstring followed by an int. 25IPC_MESSAGE_CONTROL2(MsgClassSI, std::wstring, int) 26 27// Message to create a mutex in the IPC server, using the received name. 28IPC_MESSAGE_CONTROL2(MsgDoMutex, std::wstring, int) 29 30// Used to generate an ID for a message that should not exist. 31IPC_MESSAGE_CONTROL0(MsgUnhandled) 32 33// ----------------------------------------------------------------------------- 34 35namespace { 36 37TEST(IPCMessageIntegrity, ReadBeyondBufferStr) { 38 //This was BUG 984408. 39 uint32 v1 = kuint32max - 1; 40 int v2 = 666; 41 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL); 42 EXPECT_TRUE(m.WriteInt(v1)); 43 EXPECT_TRUE(m.WriteInt(v2)); 44 45 PickleIterator iter(m); 46 std::string vs; 47 EXPECT_FALSE(m.ReadString(&iter, &vs)); 48} 49 50TEST(IPCMessageIntegrity, ReadBeyondBufferWStr) { 51 //This was BUG 984408. 52 uint32 v1 = kuint32max - 1; 53 int v2 = 777; 54 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL); 55 EXPECT_TRUE(m.WriteInt(v1)); 56 EXPECT_TRUE(m.WriteInt(v2)); 57 58 PickleIterator iter(m); 59 std::wstring vs; 60 EXPECT_FALSE(m.ReadWString(&iter, &vs)); 61} 62 63TEST(IPCMessageIntegrity, ReadBytesBadIterator) { 64 // This was BUG 1035467. 65 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL); 66 EXPECT_TRUE(m.WriteInt(1)); 67 EXPECT_TRUE(m.WriteInt(2)); 68 69 PickleIterator iter(m); 70 const char* data = NULL; 71 EXPECT_TRUE(m.ReadBytes(&iter, &data, sizeof(int))); 72} 73 74TEST(IPCMessageIntegrity, ReadVectorNegativeSize) { 75 // A slight variation of BUG 984408. Note that the pickling of vector<char> 76 // has a specialized template which is not vulnerable to this bug. So here 77 // try to hit the non-specialized case vector<P>. 78 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL); 79 EXPECT_TRUE(m.WriteInt(-1)); // This is the count of elements. 80 EXPECT_TRUE(m.WriteInt(1)); 81 EXPECT_TRUE(m.WriteInt(2)); 82 EXPECT_TRUE(m.WriteInt(3)); 83 84 std::vector<double> vec; 85 PickleIterator iter(m); 86 EXPECT_FALSE(ReadParam(&m, &iter, &vec)); 87} 88 89TEST(IPCMessageIntegrity, ReadVectorTooLarge1) { 90 // This was BUG 1006367. This is the large but positive length case. Again 91 // we try to hit the non-specialized case vector<P>. 92 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL); 93 EXPECT_TRUE(m.WriteInt(0x21000003)); // This is the count of elements. 94 EXPECT_TRUE(m.WriteInt64(1)); 95 EXPECT_TRUE(m.WriteInt64(2)); 96 97 std::vector<int64> vec; 98 PickleIterator iter(m); 99 EXPECT_FALSE(ReadParam(&m, &iter, &vec)); 100} 101 102TEST(IPCMessageIntegrity, ReadVectorTooLarge2) { 103 // This was BUG 1006367. This is the large but positive with an additional 104 // integer overflow when computing the actual byte size. Again we try to hit 105 // the non-specialized case vector<P>. 106 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL); 107 EXPECT_TRUE(m.WriteInt(0x71000000)); // This is the count of elements. 108 EXPECT_TRUE(m.WriteInt64(1)); 109 EXPECT_TRUE(m.WriteInt64(2)); 110 111 std::vector<int64> vec; 112 PickleIterator iter(m); 113 EXPECT_FALSE(ReadParam(&m, &iter, &vec)); 114} 115 116class SimpleListener : public IPC::Listener { 117 public: 118 SimpleListener() : other_(NULL) { 119 } 120 void Init(IPC::Sender* s) { 121 other_ = s; 122 } 123 protected: 124 IPC::Sender* other_; 125}; 126 127enum { 128 FUZZER_ROUTING_ID = 5 129}; 130 131// The fuzzer server class. It runs in a child process and expects 132// only two IPC calls; after that it exits the message loop which 133// terminates the child process. 134class FuzzerServerListener : public SimpleListener { 135 public: 136 FuzzerServerListener() : message_count_(2), pending_messages_(0) { 137 } 138 virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE { 139 if (msg.routing_id() == MSG_ROUTING_CONTROL) { 140 ++pending_messages_; 141 IPC_BEGIN_MESSAGE_MAP(FuzzerServerListener, msg) 142 IPC_MESSAGE_HANDLER(MsgClassIS, OnMsgClassISMessage) 143 IPC_MESSAGE_HANDLER(MsgClassSI, OnMsgClassSIMessage) 144 IPC_END_MESSAGE_MAP() 145 if (pending_messages_) { 146 // Probably a problem de-serializing the message. 147 ReplyMsgNotHandled(msg.type()); 148 } 149 } 150 return true; 151 } 152 153 private: 154 void OnMsgClassISMessage(int value, const std::wstring& text) { 155 UseData(MsgClassIS::ID, value, text); 156 RoundtripAckReply(FUZZER_ROUTING_ID, MsgClassIS::ID, value); 157 Cleanup(); 158 } 159 160 void OnMsgClassSIMessage(const std::wstring& text, int value) { 161 UseData(MsgClassSI::ID, value, text); 162 RoundtripAckReply(FUZZER_ROUTING_ID, MsgClassSI::ID, value); 163 Cleanup(); 164 } 165 166 bool RoundtripAckReply(int routing, uint32 type_id, int reply) { 167 IPC::Message* message = new IPC::Message(routing, type_id, 168 IPC::Message::PRIORITY_NORMAL); 169 message->WriteInt(reply + 1); 170 message->WriteInt(reply); 171 return other_->Send(message); 172 } 173 174 void Cleanup() { 175 --message_count_; 176 --pending_messages_; 177 if (0 == message_count_) 178 base::MessageLoop::current()->Quit(); 179 } 180 181 void ReplyMsgNotHandled(uint32 type_id) { 182 RoundtripAckReply(FUZZER_ROUTING_ID, MsgUnhandled::ID, type_id); 183 Cleanup(); 184 } 185 186 void UseData(int caller, int value, const std::wstring& text) { 187 std::wostringstream wos; 188 wos << L"IPC fuzzer:" << caller << " [" << value << L" " << text << L"]\n"; 189 std::wstring output = wos.str(); 190 LOG(WARNING) << output.c_str(); 191 }; 192 193 int message_count_; 194 int pending_messages_; 195}; 196 197class FuzzerClientListener : public SimpleListener { 198 public: 199 FuzzerClientListener() : last_msg_(NULL) { 200 } 201 202 virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE { 203 last_msg_ = new IPC::Message(msg); 204 base::MessageLoop::current()->Quit(); 205 return true; 206 } 207 208 bool ExpectMessage(int value, uint32 type_id) { 209 if (!MsgHandlerInternal(type_id)) 210 return false; 211 int msg_value1 = 0; 212 int msg_value2 = 0; 213 PickleIterator iter(*last_msg_); 214 if (!last_msg_->ReadInt(&iter, &msg_value1)) 215 return false; 216 if (!last_msg_->ReadInt(&iter, &msg_value2)) 217 return false; 218 if ((msg_value2 + 1) != msg_value1) 219 return false; 220 if (msg_value2 != value) 221 return false; 222 223 delete last_msg_; 224 last_msg_ = NULL; 225 return true; 226 } 227 228 bool ExpectMsgNotHandled(uint32 type_id) { 229 return ExpectMessage(type_id, MsgUnhandled::ID); 230 } 231 232 private: 233 bool MsgHandlerInternal(uint32 type_id) { 234 base::MessageLoop::current()->Run(); 235 if (NULL == last_msg_) 236 return false; 237 if (FUZZER_ROUTING_ID != last_msg_->routing_id()) 238 return false; 239 return (type_id == last_msg_->type()); 240 }; 241 242 IPC::Message* last_msg_; 243}; 244 245// Runs the fuzzing server child mode. Returns when the preset number of 246// messages have been received. 247MULTIPROCESS_IPC_TEST_CLIENT_MAIN(FuzzServerClient) { 248 base::MessageLoopForIO main_message_loop; 249 FuzzerServerListener listener; 250 IPC::Channel channel(IPCTestBase::GetChannelName("FuzzServerClient"), 251 IPC::Channel::MODE_CLIENT, 252 &listener); 253 CHECK(channel.Connect()); 254 listener.Init(&channel); 255 base::MessageLoop::current()->Run(); 256 return 0; 257} 258 259class IPCFuzzingTest : public IPCTestBase { 260}; 261 262// This test makes sure that the FuzzerClientListener and FuzzerServerListener 263// are working properly by generating two well formed IPC calls. 264TEST_F(IPCFuzzingTest, SanityTest) { 265 Init("FuzzServerClient"); 266 267 FuzzerClientListener listener; 268 CreateChannel(&listener); 269 listener.Init(channel()); 270 ASSERT_TRUE(ConnectChannel()); 271 ASSERT_TRUE(StartClient()); 272 273 IPC::Message* msg = NULL; 274 int value = 43; 275 msg = new MsgClassIS(value, L"expect 43"); 276 sender()->Send(msg); 277 EXPECT_TRUE(listener.ExpectMessage(value, MsgClassIS::ID)); 278 279 msg = new MsgClassSI(L"expect 44", ++value); 280 sender()->Send(msg); 281 EXPECT_TRUE(listener.ExpectMessage(value, MsgClassSI::ID)); 282 283 EXPECT_TRUE(WaitForClientShutdown()); 284 DestroyChannel(); 285} 286 287// This test uses a payload that is smaller than expected. This generates an 288// error while unpacking the IPC buffer which in debug trigger an assertion and 289// in release is ignored (!). Right after we generate another valid IPC to make 290// sure framing is working properly. 291#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON) 292TEST_F(IPCFuzzingTest, MsgBadPayloadShort) { 293 Init("FuzzServerClient"); 294 295 FuzzerClientListener listener; 296 CreateChannel(&listener); 297 listener.Init(channel()); 298 ASSERT_TRUE(ConnectChannel()); 299 ASSERT_TRUE(StartClient()); 300 301 IPC::Message* msg = new IPC::Message(MSG_ROUTING_CONTROL, MsgClassIS::ID, 302 IPC::Message::PRIORITY_NORMAL); 303 msg->WriteInt(666); 304 sender()->Send(msg); 305 EXPECT_TRUE(listener.ExpectMsgNotHandled(MsgClassIS::ID)); 306 307 msg = new MsgClassSI(L"expect one", 1); 308 sender()->Send(msg); 309 EXPECT_TRUE(listener.ExpectMessage(1, MsgClassSI::ID)); 310 311 EXPECT_TRUE(WaitForClientShutdown()); 312 DestroyChannel(); 313} 314#endif 315 316// This test uses a payload that has too many arguments, but so the payload size 317// is big enough so the unpacking routine does not generate an error as in the 318// case of MsgBadPayloadShort test. This test does not pinpoint a flaw (per se) 319// as by design we don't carry type information on the IPC message. 320TEST_F(IPCFuzzingTest, MsgBadPayloadArgs) { 321 Init("FuzzServerClient"); 322 323 FuzzerClientListener listener; 324 CreateChannel(&listener); 325 listener.Init(channel()); 326 ASSERT_TRUE(ConnectChannel()); 327 ASSERT_TRUE(StartClient()); 328 329 IPC::Message* msg = new IPC::Message(MSG_ROUTING_CONTROL, MsgClassSI::ID, 330 IPC::Message::PRIORITY_NORMAL); 331 msg->WriteWString(L"d"); 332 msg->WriteInt(0); 333 msg->WriteInt(0x65); // Extra argument. 334 335 sender()->Send(msg); 336 EXPECT_TRUE(listener.ExpectMessage(0, MsgClassSI::ID)); 337 338 // Now send a well formed message to make sure the receiver wasn't 339 // thrown out of sync by the extra argument. 340 msg = new MsgClassIS(3, L"expect three"); 341 sender()->Send(msg); 342 EXPECT_TRUE(listener.ExpectMessage(3, MsgClassIS::ID)); 343 344 EXPECT_TRUE(WaitForClientShutdown()); 345 DestroyChannel(); 346} 347 348// This class is for testing the IPC_BEGIN_MESSAGE_MAP_EX macros. 349class ServerMacroExTest { 350 public: 351 ServerMacroExTest() : unhandled_msgs_(0) { 352 } 353 354 virtual ~ServerMacroExTest() { 355 } 356 357 virtual bool OnMessageReceived(const IPC::Message& msg) { 358 bool msg_is_ok = false; 359 IPC_BEGIN_MESSAGE_MAP_EX(ServerMacroExTest, msg, msg_is_ok) 360 IPC_MESSAGE_HANDLER(MsgClassIS, OnMsgClassISMessage) 361 IPC_MESSAGE_HANDLER(MsgClassSI, OnMsgClassSIMessage) 362 IPC_MESSAGE_UNHANDLED(++unhandled_msgs_) 363 IPC_END_MESSAGE_MAP_EX() 364 return msg_is_ok; 365 } 366 367 int unhandled_msgs() const { 368 return unhandled_msgs_; 369 } 370 371 private: 372 void OnMsgClassISMessage(int value, const std::wstring& text) { 373 } 374 void OnMsgClassSIMessage(const std::wstring& text, int value) { 375 } 376 377 int unhandled_msgs_; 378 379 DISALLOW_COPY_AND_ASSIGN(ServerMacroExTest); 380}; 381 382TEST_F(IPCFuzzingTest, MsgMapExMacro) { 383 IPC::Message* msg = NULL; 384 ServerMacroExTest server; 385 386 // Test the regular messages. 387 msg = new MsgClassIS(3, L"text3"); 388 EXPECT_TRUE(server.OnMessageReceived(*msg)); 389 delete msg; 390 msg = new MsgClassSI(L"text2", 2); 391 EXPECT_TRUE(server.OnMessageReceived(*msg)); 392 delete msg; 393 394#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON) 395 // Test a bad message. 396 msg = new IPC::Message(MSG_ROUTING_CONTROL, MsgClassSI::ID, 397 IPC::Message::PRIORITY_NORMAL); 398 msg->WriteInt(2); 399 EXPECT_FALSE(server.OnMessageReceived(*msg)); 400 delete msg; 401 402 msg = new IPC::Message(MSG_ROUTING_CONTROL, MsgClassIS::ID, 403 IPC::Message::PRIORITY_NORMAL); 404 msg->WriteInt(0x64); 405 msg->WriteInt(0x32); 406 EXPECT_FALSE(server.OnMessageReceived(*msg)); 407 delete msg; 408 409 EXPECT_EQ(0, server.unhandled_msgs()); 410#endif 411} 412 413} // namespace 414