[go: nahoru, domu]

blob: 2cf58950e3d8bc6287b82b961ddf052ff6284aff [file] [log] [blame]
tedvessenes@gmail.comb5393332012-01-13 00:11:011// Copyright (c) 2012 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
tfarina10a5c062015-09-04 18:47:575#include <stdint.h>
initial.commit09911bf2008-07-26 23:55:296#include <stdio.h>
tfarina10a5c062015-09-04 18:47:577
tfarina7023f522015-09-11 19:58:488#include <limits>
danakj03de39b2016-04-23 04:21:099#include <memory>
initial.commit09911bf2008-07-26 23:55:2910#include <sstream>
tfarina10a5c062015-09-04 18:47:5711#include <string>
initial.commit09911bf2008-07-26 23:55:2912
avi@chromium.org2a9ec0e2013-07-17 23:00:3013#include "base/message_loop/message_loop.h"
fdoray8e32586852016-06-22 19:56:1614#include "base/run_loop.h"
thestigf84f17f2015-03-11 20:41:5515#include "base/strings/string16.h"
16#include "base/strings/utf_string_conversions.h"
brettw@google.comf214f872011-01-01 02:17:0817#include "base/threading/platform_thread.h"
avi246998d2015-12-22 02:39:0418#include "build/build_config.h"
viettrungluu@chromium.org0cb7d8c82013-01-11 15:13:3719#include "ipc/ipc_test_base.h"
initial.commit09911bf2008-07-26 23:55:2920#include "testing/gtest/include/gtest/gtest.h"
darin@chromium.org1d4ecf42011-08-26 21:27:3021
viettrungluu@chromium.org2a3aa7b52013-01-11 20:56:2222// IPC messages for testing ----------------------------------------------------
darin@chromium.org1d4ecf42011-08-26 21:27:3023
24#define IPC_MESSAGE_IMPL
25#include "ipc/ipc_message_macros.h"
26
27#define IPC_MESSAGE_START TestMsgStart
28
thestigf84f17f2015-03-11 20:41:5529// Generic message class that is an int followed by a string16.
30IPC_MESSAGE_CONTROL2(MsgClassIS, int, base::string16)
darin@chromium.org1d4ecf42011-08-26 21:27:3031
thestigf84f17f2015-03-11 20:41:5532// Generic message class that is a string16 followed by an int.
33IPC_MESSAGE_CONTROL2(MsgClassSI, base::string16, int)
darin@chromium.org1d4ecf42011-08-26 21:27:3034
35// Message to create a mutex in the IPC server, using the received name.
thestigf84f17f2015-03-11 20:41:5536IPC_MESSAGE_CONTROL2(MsgDoMutex, base::string16, int)
darin@chromium.org1d4ecf42011-08-26 21:27:3037
38// Used to generate an ID for a message that should not exist.
39IPC_MESSAGE_CONTROL0(MsgUnhandled)
40
viettrungluu@chromium.org2a3aa7b52013-01-11 20:56:2241// -----------------------------------------------------------------------------
42
43namespace {
initial.commit09911bf2008-07-26 23:55:2944
45TEST(IPCMessageIntegrity, ReadBeyondBufferStr) {
thestigf84f17f2015-03-11 20:41:5546 // This was BUG 984408.
tfarina7023f522015-09-11 19:58:4847 uint32_t v1 = std::numeric_limits<uint32_t>::max() - 1;
initial.commit09911bf2008-07-26 23:55:2948 int v2 = 666;
bbudge@chromium.org753bb252013-11-04 22:28:1249 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL);
initial.commit09911bf2008-07-26 23:55:2950 EXPECT_TRUE(m.WriteInt(v1));
51 EXPECT_TRUE(m.WriteInt(v2));
52
brettwbd4d7112015-06-03 04:29:2553 base::PickleIterator iter(m);
initial.commit09911bf2008-07-26 23:55:2954 std::string vs;
avi48fc13b2014-12-28 23:31:4855 EXPECT_FALSE(iter.ReadString(&vs));
initial.commit09911bf2008-07-26 23:55:2956}
57
thestigf84f17f2015-03-11 20:41:5558TEST(IPCMessageIntegrity, ReadBeyondBufferStr16) {
59 // This was BUG 984408.
tfarina7023f522015-09-11 19:58:4860 uint32_t v1 = std::numeric_limits<uint32_t>::max() - 1;
initial.commit09911bf2008-07-26 23:55:2961 int v2 = 777;
bbudge@chromium.org753bb252013-11-04 22:28:1262 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL);
initial.commit09911bf2008-07-26 23:55:2963 EXPECT_TRUE(m.WriteInt(v1));
64 EXPECT_TRUE(m.WriteInt(v2));
65
brettwbd4d7112015-06-03 04:29:2566 base::PickleIterator iter(m);
thestigf84f17f2015-03-11 20:41:5567 base::string16 vs;
68 EXPECT_FALSE(iter.ReadString16(&vs));
initial.commit09911bf2008-07-26 23:55:2969}
70
71TEST(IPCMessageIntegrity, ReadBytesBadIterator) {
72 // This was BUG 1035467.
bbudge@chromium.org753bb252013-11-04 22:28:1273 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL);
initial.commit09911bf2008-07-26 23:55:2974 EXPECT_TRUE(m.WriteInt(1));
75 EXPECT_TRUE(m.WriteInt(2));
76
brettwbd4d7112015-06-03 04:29:2577 base::PickleIterator iter(m);
initial.commit09911bf2008-07-26 23:55:2978 const char* data = NULL;
avi48fc13b2014-12-28 23:31:4879 EXPECT_TRUE(iter.ReadBytes(&data, sizeof(int)));
initial.commit09911bf2008-07-26 23:55:2980}
81
82TEST(IPCMessageIntegrity, ReadVectorNegativeSize) {
83 // A slight variation of BUG 984408. Note that the pickling of vector<char>
84 // has a specialized template which is not vulnerable to this bug. So here
85 // try to hit the non-specialized case vector<P>.
bbudge@chromium.org753bb252013-11-04 22:28:1286 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL);
initial.commit09911bf2008-07-26 23:55:2987 EXPECT_TRUE(m.WriteInt(-1)); // This is the count of elements.
88 EXPECT_TRUE(m.WriteInt(1));
89 EXPECT_TRUE(m.WriteInt(2));
90 EXPECT_TRUE(m.WriteInt(3));
91
92 std::vector<double> vec;
brettwbd4d7112015-06-03 04:29:2593 base::PickleIterator iter(m);
initial.commit09911bf2008-07-26 23:55:2994 EXPECT_FALSE(ReadParam(&m, &iter, &vec));
95}
96
tfarina8514f0d2015-07-28 14:41:4797#if defined(OS_ANDROID)
98#define MAYBE_ReadVectorTooLarge1 DISABLED_ReadVectorTooLarge1
99#else
100#define MAYBE_ReadVectorTooLarge1 ReadVectorTooLarge1
101#endif
102TEST(IPCMessageIntegrity, MAYBE_ReadVectorTooLarge1) {
initial.commit09911bf2008-07-26 23:55:29103 // This was BUG 1006367. This is the large but positive length case. Again
104 // we try to hit the non-specialized case vector<P>.
bbudge@chromium.org753bb252013-11-04 22:28:12105 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL);
initial.commit09911bf2008-07-26 23:55:29106 EXPECT_TRUE(m.WriteInt(0x21000003)); // This is the count of elements.
107 EXPECT_TRUE(m.WriteInt64(1));
108 EXPECT_TRUE(m.WriteInt64(2));
109
tfarina10a5c062015-09-04 18:47:57110 std::vector<int64_t> vec;
brettwbd4d7112015-06-03 04:29:25111 base::PickleIterator iter(m);
initial.commit09911bf2008-07-26 23:55:29112 EXPECT_FALSE(ReadParam(&m, &iter, &vec));
113}
114
115TEST(IPCMessageIntegrity, ReadVectorTooLarge2) {
116 // This was BUG 1006367. This is the large but positive with an additional
117 // integer overflow when computing the actual byte size. Again we try to hit
118 // the non-specialized case vector<P>.
bbudge@chromium.org753bb252013-11-04 22:28:12119 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL);
initial.commit09911bf2008-07-26 23:55:29120 EXPECT_TRUE(m.WriteInt(0x71000000)); // This is the count of elements.
121 EXPECT_TRUE(m.WriteInt64(1));
122 EXPECT_TRUE(m.WriteInt64(2));
123
tfarina10a5c062015-09-04 18:47:57124 std::vector<int64_t> vec;
brettwbd4d7112015-06-03 04:29:25125 base::PickleIterator iter(m);
initial.commit09911bf2008-07-26 23:55:29126 EXPECT_FALSE(ReadParam(&m, &iter, &vec));
127}
128
brettw@chromium.org57319ce2012-06-11 22:35:26129class SimpleListener : public IPC::Listener {
initial.commit09911bf2008-07-26 23:55:29130 public:
131 SimpleListener() : other_(NULL) {
132 }
brettw@chromium.org57319ce2012-06-11 22:35:26133 void Init(IPC::Sender* s) {
initial.commit09911bf2008-07-26 23:55:29134 other_ = s;
135 }
136 protected:
brettw@chromium.org57319ce2012-06-11 22:35:26137 IPC::Sender* other_;
initial.commit09911bf2008-07-26 23:55:29138};
139
140enum {
141 FUZZER_ROUTING_ID = 5
142};
143
144// The fuzzer server class. It runs in a child process and expects
145// only two IPC calls; after that it exits the message loop which
146// terminates the child process.
147class FuzzerServerListener : public SimpleListener {
148 public:
149 FuzzerServerListener() : message_count_(2), pending_messages_(0) {
150 }
dchengfe61fca2014-10-22 02:29:52151 bool OnMessageReceived(const IPC::Message& msg) override {
initial.commit09911bf2008-07-26 23:55:29152 if (msg.routing_id() == MSG_ROUTING_CONTROL) {
153 ++pending_messages_;
154 IPC_BEGIN_MESSAGE_MAP(FuzzerServerListener, msg)
155 IPC_MESSAGE_HANDLER(MsgClassIS, OnMsgClassISMessage)
156 IPC_MESSAGE_HANDLER(MsgClassSI, OnMsgClassSIMessage)
157 IPC_END_MESSAGE_MAP()
158 if (pending_messages_) {
159 // Probably a problem de-serializing the message.
160 ReplyMsgNotHandled(msg.type());
161 }
162 }
jam@chromium.orga95986a2010-12-24 06:19:28163 return true;
initial.commit09911bf2008-07-26 23:55:29164 }
165
166 private:
thestigf84f17f2015-03-11 20:41:55167 void OnMsgClassISMessage(int value, const base::string16& text) {
initial.commit09911bf2008-07-26 23:55:29168 UseData(MsgClassIS::ID, value, text);
169 RoundtripAckReply(FUZZER_ROUTING_ID, MsgClassIS::ID, value);
170 Cleanup();
171 }
172
thestigf84f17f2015-03-11 20:41:55173 void OnMsgClassSIMessage(const base::string16& text, int value) {
initial.commit09911bf2008-07-26 23:55:29174 UseData(MsgClassSI::ID, value, text);
175 RoundtripAckReply(FUZZER_ROUTING_ID, MsgClassSI::ID, value);
176 Cleanup();
177 }
178
tfarina10a5c062015-09-04 18:47:57179 bool RoundtripAckReply(int routing, uint32_t type_id, int reply) {
bbudge@chromium.org753bb252013-11-04 22:28:12180 IPC::Message* message = new IPC::Message(routing, type_id,
181 IPC::Message::PRIORITY_NORMAL);
initial.commit09911bf2008-07-26 23:55:29182 message->WriteInt(reply + 1);
183 message->WriteInt(reply);
184 return other_->Send(message);
185 }
186
187 void Cleanup() {
188 --message_count_;
189 --pending_messages_;
190 if (0 == message_count_)
ki.stfua21ed8c2015-10-12 17:26:00191 base::MessageLoop::current()->QuitWhenIdle();
initial.commit09911bf2008-07-26 23:55:29192 }
193
tfarina10a5c062015-09-04 18:47:57194 void ReplyMsgNotHandled(uint32_t type_id) {
darin@chromium.org1d4ecf42011-08-26 21:27:30195 RoundtripAckReply(FUZZER_ROUTING_ID, MsgUnhandled::ID, type_id);
initial.commit09911bf2008-07-26 23:55:29196 Cleanup();
197 }
198
thestigf84f17f2015-03-11 20:41:55199 void UseData(int caller, int value, const base::string16& text) {
200 std::ostringstream os;
201 os << "IPC fuzzer:" << caller << " [" << value << " "
202 << base::UTF16ToUTF8(text) << "]\n";
203 std::string output = os.str();
204 LOG(WARNING) << output;
205 }
initial.commit09911bf2008-07-26 23:55:29206
207 int message_count_;
208 int pending_messages_;
209};
210
211class FuzzerClientListener : public SimpleListener {
212 public:
213 FuzzerClientListener() : last_msg_(NULL) {
214 }
215
dchengfe61fca2014-10-22 02:29:52216 bool OnMessageReceived(const IPC::Message& msg) override {
initial.commit09911bf2008-07-26 23:55:29217 last_msg_ = new IPC::Message(msg);
ki.stfua21ed8c2015-10-12 17:26:00218 base::MessageLoop::current()->QuitWhenIdle();
jam@chromium.orga95986a2010-12-24 06:19:28219 return true;
initial.commit09911bf2008-07-26 23:55:29220 }
221
tfarina10a5c062015-09-04 18:47:57222 bool ExpectMessage(int value, uint32_t type_id) {
initial.commit09911bf2008-07-26 23:55:29223 if (!MsgHandlerInternal(type_id))
224 return false;
225 int msg_value1 = 0;
226 int msg_value2 = 0;
brettwbd4d7112015-06-03 04:29:25227 base::PickleIterator iter(*last_msg_);
avi48fc13b2014-12-28 23:31:48228 if (!iter.ReadInt(&msg_value1))
initial.commit09911bf2008-07-26 23:55:29229 return false;
avi48fc13b2014-12-28 23:31:48230 if (!iter.ReadInt(&msg_value2))
initial.commit09911bf2008-07-26 23:55:29231 return false;
232 if ((msg_value2 + 1) != msg_value1)
233 return false;
234 if (msg_value2 != value)
235 return false;
236
237 delete last_msg_;
238 last_msg_ = NULL;
239 return true;
240 }
241
tfarina10a5c062015-09-04 18:47:57242 bool ExpectMsgNotHandled(uint32_t type_id) {
darin@chromium.org1d4ecf42011-08-26 21:27:30243 return ExpectMessage(type_id, MsgUnhandled::ID);
initial.commit09911bf2008-07-26 23:55:29244 }
245
246 private:
tfarina10a5c062015-09-04 18:47:57247 bool MsgHandlerInternal(uint32_t type_id) {
fdoray8e32586852016-06-22 19:56:16248 base::RunLoop().Run();
initial.commit09911bf2008-07-26 23:55:29249 if (NULL == last_msg_)
250 return false;
251 if (FUZZER_ROUTING_ID != last_msg_->routing_id())
252 return false;
253 return (type_id == last_msg_->type());
thestigf84f17f2015-03-11 20:41:55254 }
initial.commit09911bf2008-07-26 23:55:29255
256 IPC::Message* last_msg_;
257};
258
viettrungluu@chromium.org3c788582013-01-25 21:51:35259// Runs the fuzzing server child mode. Returns when the preset number of
260// messages have been received.
261MULTIPROCESS_IPC_TEST_CLIENT_MAIN(FuzzServerClient) {
xhwang@chromium.orgfd0a773a2013-04-30 20:55:03262 base::MessageLoopForIO main_message_loop;
initial.commit09911bf2008-07-26 23:55:29263 FuzzerServerListener listener;
danakj03de39b2016-04-23 04:21:09264 std::unique_ptr<IPC::Channel> channel(IPC::Channel::CreateClient(
rockota34707ca2016-07-20 04:28:32265 IPCTestBase::GetChannelName("FuzzServerClient"), &listener,
266 main_message_loop.task_runner()));
morrita@chromium.orge482111a82014-05-30 03:58:59267 CHECK(channel->Connect());
268 listener.Init(channel.get());
fdoray8e32586852016-06-22 19:56:16269 base::RunLoop().Run();
jeremy@chromium.org95cb7fb92008-12-09 22:00:47270 return 0;
initial.commit09911bf2008-07-26 23:55:29271}
jeremy@chromium.org95cb7fb92008-12-09 22:00:47272
viettrungluu@chromium.org0cb7d8c82013-01-11 15:13:37273class IPCFuzzingTest : public IPCTestBase {
jeremy@chromium.org95cb7fb92008-12-09 22:00:47274};
initial.commit09911bf2008-07-26 23:55:29275
276// This test makes sure that the FuzzerClientListener and FuzzerServerListener
277// are working properly by generating two well formed IPC calls.
amistry6de2ee4f2016-05-05 05:12:09278TEST_F(IPCFuzzingTest, SanityTest) {
viettrungluu@chromium.org3c788582013-01-25 21:51:35279 Init("FuzzServerClient");
280
jeremy@chromium.orgdf3c1ca12008-12-19 21:37:01281 FuzzerClientListener listener;
viettrungluu@chromium.org3c788582013-01-25 21:51:35282 CreateChannel(&listener);
283 listener.Init(channel());
284 ASSERT_TRUE(ConnectChannel());
285 ASSERT_TRUE(StartClient());
initial.commit09911bf2008-07-26 23:55:29286
287 IPC::Message* msg = NULL;
288 int value = 43;
thestigf84f17f2015-03-11 20:41:55289 msg = new MsgClassIS(value, base::ASCIIToUTF16("expect 43"));
viettrungluu@chromium.org3c788582013-01-25 21:51:35290 sender()->Send(msg);
initial.commit09911bf2008-07-26 23:55:29291 EXPECT_TRUE(listener.ExpectMessage(value, MsgClassIS::ID));
292
thestigf84f17f2015-03-11 20:41:55293 msg = new MsgClassSI(base::ASCIIToUTF16("expect 44"), ++value);
viettrungluu@chromium.org3c788582013-01-25 21:51:35294 sender()->Send(msg);
initial.commit09911bf2008-07-26 23:55:29295 EXPECT_TRUE(listener.ExpectMessage(value, MsgClassSI::ID));
296
viettrungluu@chromium.org3c788582013-01-25 21:51:35297 EXPECT_TRUE(WaitForClientShutdown());
298 DestroyChannel();
initial.commit09911bf2008-07-26 23:55:29299}
300
viettrungluu@chromium.org3c788582013-01-25 21:51:35301// This test uses a payload that is smaller than expected. This generates an
302// error while unpacking the IPC buffer which in debug trigger an assertion and
303// in release is ignored (!). Right after we generate another valid IPC to make
304// sure framing is working properly.
nsylvain@chromium.org20960e072011-09-20 20:59:01305#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
amistry6de2ee4f2016-05-05 05:12:09306TEST_F(IPCFuzzingTest, MsgBadPayloadShort) {
viettrungluu@chromium.org3c788582013-01-25 21:51:35307 Init("FuzzServerClient");
308
jeremy@chromium.orgdf3c1ca12008-12-19 21:37:01309 FuzzerClientListener listener;
viettrungluu@chromium.org3c788582013-01-25 21:51:35310 CreateChannel(&listener);
311 listener.Init(channel());
312 ASSERT_TRUE(ConnectChannel());
313 ASSERT_TRUE(StartClient());
initial.commit09911bf2008-07-26 23:55:29314
bbudge@chromium.org753bb252013-11-04 22:28:12315 IPC::Message* msg = new IPC::Message(MSG_ROUTING_CONTROL, MsgClassIS::ID,
316 IPC::Message::PRIORITY_NORMAL);
initial.commit09911bf2008-07-26 23:55:29317 msg->WriteInt(666);
viettrungluu@chromium.org3c788582013-01-25 21:51:35318 sender()->Send(msg);
initial.commit09911bf2008-07-26 23:55:29319 EXPECT_TRUE(listener.ExpectMsgNotHandled(MsgClassIS::ID));
320
thestigf84f17f2015-03-11 20:41:55321 msg = new MsgClassSI(base::ASCIIToUTF16("expect one"), 1);
viettrungluu@chromium.org3c788582013-01-25 21:51:35322 sender()->Send(msg);
initial.commit09911bf2008-07-26 23:55:29323 EXPECT_TRUE(listener.ExpectMessage(1, MsgClassSI::ID));
324
viettrungluu@chromium.org3c788582013-01-25 21:51:35325 EXPECT_TRUE(WaitForClientShutdown());
326 DestroyChannel();
initial.commit09911bf2008-07-26 23:55:29327}
nsylvain@chromium.org20960e072011-09-20 20:59:01328#endif
initial.commit09911bf2008-07-26 23:55:29329
viettrungluu@chromium.org3c788582013-01-25 21:51:35330// This test uses a payload that has too many arguments, but so the payload size
331// is big enough so the unpacking routine does not generate an error as in the
332// case of MsgBadPayloadShort test. This test does not pinpoint a flaw (per se)
333// as by design we don't carry type information on the IPC message.
amistry6de2ee4f2016-05-05 05:12:09334TEST_F(IPCFuzzingTest, MsgBadPayloadArgs) {
viettrungluu@chromium.org3c788582013-01-25 21:51:35335 Init("FuzzServerClient");
336
jeremy@chromium.orgdf3c1ca12008-12-19 21:37:01337 FuzzerClientListener listener;
viettrungluu@chromium.org3c788582013-01-25 21:51:35338 CreateChannel(&listener);
339 listener.Init(channel());
340 ASSERT_TRUE(ConnectChannel());
341 ASSERT_TRUE(StartClient());
initial.commit09911bf2008-07-26 23:55:29342
bbudge@chromium.org753bb252013-11-04 22:28:12343 IPC::Message* msg = new IPC::Message(MSG_ROUTING_CONTROL, MsgClassSI::ID,
344 IPC::Message::PRIORITY_NORMAL);
thestigf84f17f2015-03-11 20:41:55345 msg->WriteString16(base::ASCIIToUTF16("d"));
initial.commit09911bf2008-07-26 23:55:29346 msg->WriteInt(0);
jeremy@chromium.org95cb7fb92008-12-09 22:00:47347 msg->WriteInt(0x65); // Extra argument.
348
viettrungluu@chromium.org3c788582013-01-25 21:51:35349 sender()->Send(msg);
initial.commit09911bf2008-07-26 23:55:29350 EXPECT_TRUE(listener.ExpectMessage(0, MsgClassSI::ID));
351
jeremy@chromium.org95cb7fb92008-12-09 22:00:47352 // Now send a well formed message to make sure the receiver wasn't
353 // thrown out of sync by the extra argument.
thestigf84f17f2015-03-11 20:41:55354 msg = new MsgClassIS(3, base::ASCIIToUTF16("expect three"));
viettrungluu@chromium.org3c788582013-01-25 21:51:35355 sender()->Send(msg);
initial.commit09911bf2008-07-26 23:55:29356 EXPECT_TRUE(listener.ExpectMessage(3, MsgClassIS::ID));
357
viettrungluu@chromium.org3c788582013-01-25 21:51:35358 EXPECT_TRUE(WaitForClientShutdown());
359 DestroyChannel();
initial.commit09911bf2008-07-26 23:55:29360}
361
viettrungluu@chromium.org2a3aa7b52013-01-11 20:56:22362} // namespace