зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1821010 - Remove legacy IPC fuzzing code. r=truber,nika
Differential Revision: https://phabricator.services.mozilla.com/D171981
This commit is contained in:
Родитель
86dc96bec2
Коммит
3cb30b35f1
|
@ -78,9 +78,6 @@ using mozilla::loader::PScriptCacheParent;
|
|||
namespace ipc {
|
||||
class CrashReporterHost;
|
||||
class TestShellParent;
|
||||
#ifdef FUZZING
|
||||
class ProtocolFuzzerHelper;
|
||||
#endif
|
||||
class SharedPreferenceSerializer;
|
||||
} // namespace ipc
|
||||
|
||||
|
@ -132,9 +129,6 @@ class ContentParent final : public PContentParent,
|
|||
friend class mozilla::PreallocatedProcessManagerImpl;
|
||||
friend class PContentParent;
|
||||
friend class mozilla::dom::RemoteWorkerManager;
|
||||
#ifdef FUZZING
|
||||
friend class mozilla::ipc::ProtocolFuzzerHelper;
|
||||
#endif
|
||||
|
||||
public:
|
||||
using LaunchError = mozilla::ipc::LaunchError;
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "FuzzingInterface.h"
|
||||
#include "ProtocolFuzzer.h"
|
||||
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/devtools/PHeapSnapshotTempFileHelper.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/gfx/gfxVars.h"
|
||||
|
||||
int FuzzingInitContentParentIPC(int* argc, char*** argv) { return 0; }
|
||||
|
||||
static int RunContentParentIPCFuzzing(const uint8_t* data, size_t size) {
|
||||
static mozilla::dom::ContentParent* p =
|
||||
mozilla::ipc::ProtocolFuzzerHelper::CreateContentParent(
|
||||
DEFAULT_REMOTE_TYPE);
|
||||
|
||||
static nsTArray<nsCString> ignored = mozilla::ipc::LoadIPCMessageBlacklist(
|
||||
getenv("MOZ_IPC_MESSAGE_FUZZ_BLACKLIST"));
|
||||
|
||||
mozilla::ipc::FuzzProtocol(p, data, size, ignored);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MOZ_FUZZING_INTERFACE_RAW(FuzzingInitContentParentIPC,
|
||||
RunContentParentIPCFuzzing, ContentParentIPC);
|
|
@ -1,20 +0,0 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
Library("FuzzingContentParentIPC")
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
"/dom/base",
|
||||
]
|
||||
|
||||
SOURCES += ["content_parent_ipc_libfuzz.cpp"]
|
||||
|
||||
include("/ipc/chromium/chromium-config.mozbuild")
|
||||
|
||||
FINAL_LIBRARY = "xul-gtest"
|
||||
|
||||
# Add libFuzzer configuration directives
|
||||
include("/tools/fuzzing/libfuzzer-config.mozbuild")
|
|
@ -269,8 +269,5 @@ XPCSHELL_TESTS_MANIFESTS += ["tests/xpcshell.ini"]
|
|||
if CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk":
|
||||
CXXFLAGS += CONFIG["MOZ_GTK3_CFLAGS"]
|
||||
|
||||
if CONFIG["FUZZING"] and CONFIG["FUZZING_INTERFACES"]:
|
||||
TEST_DIRS += ["fuzztest"]
|
||||
|
||||
# Add libFuzzer configuration directives
|
||||
include("/tools/fuzzing/libfuzzer-config.mozbuild")
|
||||
|
|
|
@ -34,9 +34,6 @@ class GPUParent;
|
|||
|
||||
namespace ipc {
|
||||
class Shmem;
|
||||
#ifdef FUZZING
|
||||
class ProtocolFuzzerHelper;
|
||||
#endif
|
||||
} // namespace ipc
|
||||
|
||||
namespace widget {
|
||||
|
@ -237,9 +234,6 @@ class CompositorBridgeParent final : public CompositorBridgeParentBase,
|
|||
friend class gfx::GPUProcessManager;
|
||||
friend class gfx::GPUParent;
|
||||
friend class PCompositorBridgeParent;
|
||||
#ifdef FUZZING
|
||||
friend class mozilla::ipc::ProtocolFuzzerHelper;
|
||||
#endif
|
||||
|
||||
public:
|
||||
NS_IMETHOD_(MozExternalRefCountType) AddRef() override {
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "FuzzingInterface.h"
|
||||
#include "ProtocolFuzzer.h"
|
||||
|
||||
#include "mozilla/layers/CompositorBridgeParent.h"
|
||||
#include "mozilla/layers/CompositorManagerParent.h"
|
||||
#include "mozilla/layers/LayerTreeOwnerTracker.h"
|
||||
|
||||
int FuzzingInitCompositorManagerParentIPC(int* argc, char*** argv) {
|
||||
mozilla::ipc::ProtocolFuzzerHelper::CompositorBridgeParentSetup();
|
||||
mozilla::layers::LayerTreeOwnerTracker::Initialize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int RunCompositorManagerParentIPCFuzzing(const uint8_t* data,
|
||||
size_t size) {
|
||||
static mozilla::layers::CompositorManagerParent* p =
|
||||
mozilla::layers::CompositorManagerParent::CreateSameProcess().take();
|
||||
|
||||
static nsTArray<nsCString> ignored = mozilla::ipc::LoadIPCMessageBlacklist(
|
||||
getenv("MOZ_IPC_MESSAGE_FUZZ_BLACKLIST"));
|
||||
|
||||
mozilla::ipc::FuzzProtocol(p, data, size, ignored);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MOZ_FUZZING_INTERFACE_RAW(FuzzingInitCompositorManagerParentIPC,
|
||||
RunCompositorManagerParentIPCFuzzing,
|
||||
CompositorManagerParentIPC);
|
|
@ -1,16 +0,0 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
Library("FuzzingCompositorManagerParentIPC")
|
||||
|
||||
SOURCES += ["compositor_manager_parent_ipc_libfuzz.cpp"]
|
||||
|
||||
include("/ipc/chromium/chromium-config.mozbuild")
|
||||
|
||||
FINAL_LIBRARY = "xul-gtest"
|
||||
|
||||
# Add libFuzzer configuration directives
|
||||
include("/tools/fuzzing/libfuzzer-config.mozbuild")
|
|
@ -517,8 +517,5 @@ if CONFIG["CC_TYPE"] == "gcc":
|
|||
|
||||
UNIFIED_SOURCES += []
|
||||
|
||||
if CONFIG["FUZZING"] and CONFIG["FUZZING_INTERFACES"]:
|
||||
TEST_DIRS += ["ipc/fuzztest"]
|
||||
|
||||
# Add libFuzzer configuration directives
|
||||
include("/tools/fuzzing/libfuzzer-config.mozbuild")
|
||||
|
|
|
@ -482,84 +482,47 @@ void Pickle::EndWrite(uint32_t length) {
|
|||
WritePadding(buffers_, padding);
|
||||
}
|
||||
|
||||
bool Pickle::WriteBool(bool value) {
|
||||
#ifdef FUZZING
|
||||
mozilla::ipc::Faulty::instance().FuzzBool(&value);
|
||||
#endif
|
||||
return WriteInt(value ? 1 : 0);
|
||||
}
|
||||
bool Pickle::WriteBool(bool value) { return WriteInt(value ? 1 : 0); }
|
||||
|
||||
bool Pickle::WriteInt16(int16_t value) {
|
||||
#ifdef FUZZING
|
||||
mozilla::ipc::Faulty::instance().FuzzInt16(&value);
|
||||
#endif
|
||||
return WriteBytes(&value, sizeof(value));
|
||||
}
|
||||
|
||||
bool Pickle::WriteUInt16(uint16_t value) {
|
||||
#ifdef FUZZING
|
||||
mozilla::ipc::Faulty::instance().FuzzUInt16(&value);
|
||||
#endif
|
||||
return WriteBytes(&value, sizeof(value));
|
||||
}
|
||||
|
||||
bool Pickle::WriteInt(int value) {
|
||||
#ifdef FUZZING
|
||||
mozilla::ipc::Faulty::instance().FuzzInt(&value);
|
||||
#endif
|
||||
return WriteBytes(&value, sizeof(value));
|
||||
}
|
||||
bool Pickle::WriteInt(int value) { return WriteBytes(&value, sizeof(value)); }
|
||||
|
||||
bool Pickle::WriteLong(long value) {
|
||||
// Always written as a 64-bit value since the size for this type can
|
||||
// differ between architectures.
|
||||
#ifdef FUZZING
|
||||
mozilla::ipc::Faulty::instance().FuzzLong(&value);
|
||||
#endif
|
||||
return WriteInt64(int64_t(value));
|
||||
}
|
||||
|
||||
bool Pickle::WriteULong(unsigned long value) {
|
||||
// Always written as a 64-bit value since the size for this type can
|
||||
// differ between architectures.
|
||||
#ifdef FUZZING
|
||||
mozilla::ipc::Faulty::instance().FuzzULong(&value);
|
||||
#endif
|
||||
return WriteUInt64(uint64_t(value));
|
||||
}
|
||||
|
||||
bool Pickle::WriteInt32(int32_t value) {
|
||||
#ifdef FUZZING
|
||||
mozilla::ipc::Faulty::instance().FuzzInt(&value);
|
||||
#endif
|
||||
return WriteBytes(&value, sizeof(value));
|
||||
}
|
||||
|
||||
bool Pickle::WriteUInt32(uint32_t value) {
|
||||
#ifdef FUZZING
|
||||
mozilla::ipc::Faulty::instance().FuzzUInt32(&value);
|
||||
#endif
|
||||
return WriteBytes(&value, sizeof(value));
|
||||
}
|
||||
|
||||
bool Pickle::WriteInt64(int64_t value) {
|
||||
#ifdef FUZZING
|
||||
mozilla::ipc::Faulty::instance().FuzzInt64(&value);
|
||||
#endif
|
||||
return WriteBytes(&value, sizeof(value));
|
||||
}
|
||||
|
||||
bool Pickle::WriteUInt64(uint64_t value) {
|
||||
#ifdef FUZZING
|
||||
mozilla::ipc::Faulty::instance().FuzzUInt64(&value);
|
||||
#endif
|
||||
return WriteBytes(&value, sizeof(value));
|
||||
}
|
||||
|
||||
bool Pickle::WriteDouble(double value) {
|
||||
#ifdef FUZZING
|
||||
mozilla::ipc::Faulty::instance().FuzzDouble(&value);
|
||||
#endif
|
||||
return WriteBytes(&value, sizeof(value));
|
||||
}
|
||||
|
||||
|
@ -570,9 +533,6 @@ bool Pickle::WriteIntPtr(intptr_t value) {
|
|||
}
|
||||
|
||||
bool Pickle::WriteUnsignedChar(unsigned char value) {
|
||||
#ifdef FUZZING
|
||||
mozilla::ipc::Faulty::instance().FuzzUChar(&value);
|
||||
#endif
|
||||
return WriteBytes(&value, sizeof(value));
|
||||
}
|
||||
|
||||
|
@ -612,32 +572,16 @@ bool Pickle::WriteBytes(const void* data, uint32_t data_len) {
|
|||
}
|
||||
|
||||
bool Pickle::WriteString(const std::string& value) {
|
||||
#ifdef FUZZING
|
||||
std::string v(value);
|
||||
mozilla::ipc::Faulty::instance().FuzzString(v);
|
||||
if (!WriteInt(static_cast<int>(v.size()))) return false;
|
||||
|
||||
return WriteBytes(v.data(), static_cast<int>(v.size()));
|
||||
#else
|
||||
if (!WriteInt(static_cast<int>(value.size()))) return false;
|
||||
|
||||
return WriteBytes(value.data(), static_cast<int>(value.size()));
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Pickle::WriteWString(const std::wstring& value) {
|
||||
#ifdef FUZZING
|
||||
std::wstring v(value);
|
||||
mozilla::ipc::Faulty::instance().FuzzWString(v);
|
||||
if (!WriteInt(static_cast<int>(v.size()))) return false;
|
||||
|
||||
return WriteBytes(v.data(), static_cast<int>(v.size() * sizeof(wchar_t)));
|
||||
#else
|
||||
if (!WriteInt(static_cast<int>(value.size()))) return false;
|
||||
|
||||
return WriteBytes(value.data(),
|
||||
static_cast<int>(value.size() * sizeof(wchar_t)));
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Pickle::WriteData(const char* data, uint32_t length) {
|
||||
|
|
|
@ -17,9 +17,6 @@
|
|||
#include "mozilla/BufferList.h"
|
||||
#include "mozilla/mozalloc.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#ifdef FUZZING
|
||||
# include "mozilla/ipc/Faulty.h"
|
||||
#endif
|
||||
#if !defined(FUZZING) && (!defined(RELEASE_OR_BETA) || defined(DEBUG))
|
||||
# define MOZ_PICKLE_SENTINEL_CHECKING
|
||||
#endif
|
||||
|
|
|
@ -45,10 +45,6 @@
|
|||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/Unused.h"
|
||||
|
||||
#ifdef FUZZING
|
||||
# include "mozilla/ipc/Faulty.h"
|
||||
#endif
|
||||
|
||||
// Use OS specific iovec array limit where it's possible.
|
||||
#if defined(IOV_MAX)
|
||||
static const size_t kMaxIOVecSize = IOV_MAX;
|
||||
|
@ -587,9 +583,6 @@ bool Channel::ChannelImpl::ProcessOutgoingMessages() {
|
|||
// Write out all the messages we can till the write blocks or there are no
|
||||
// more outgoing messages.
|
||||
while (!output_queue_.IsEmpty()) {
|
||||
#ifdef FUZZING
|
||||
mozilla::ipc::Faulty::instance().MaybeCollectAndClosePipe(pipe_);
|
||||
#endif
|
||||
Message* msg = output_queue_.FirstElement().get();
|
||||
|
||||
struct msghdr msgh = {0};
|
||||
|
@ -809,11 +802,6 @@ bool Channel::ChannelImpl::Send(mozilla::UniquePtr<Message> message) {
|
|||
<< output_queue_.Count() << " in queue)";
|
||||
#endif
|
||||
|
||||
#ifdef FUZZING
|
||||
message = mozilla::ipc::Faulty::instance().MutateIPCMessage(
|
||||
"Channel::ChannelImpl::Send", std::move(message));
|
||||
#endif
|
||||
|
||||
// If the channel has been closed, ProcessOutgoingMessages() is never going
|
||||
// to pop anything off output_queue; output_queue will only get emptied when
|
||||
// the channel is destructed. We might as well delete message now, instead
|
||||
|
|
|
@ -25,10 +25,6 @@
|
|||
#include "mozilla/RandomNum.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#ifdef FUZZING
|
||||
# include "mozilla/ipc/Faulty.h"
|
||||
#endif
|
||||
|
||||
using namespace mozilla::ipc;
|
||||
|
||||
namespace IPC {
|
||||
|
@ -165,11 +161,6 @@ bool Channel::ChannelImpl::Send(mozilla::UniquePtr<Message> message) {
|
|||
<< output_queue_.Count() << " in queue)";
|
||||
#endif
|
||||
|
||||
#ifdef FUZZING
|
||||
message = mozilla::ipc::Faulty::instance().MutateIPCMessage(
|
||||
"Channel::ChannelImpl::Send", std::move(message));
|
||||
#endif
|
||||
|
||||
if (pipe_ == INVALID_HANDLE_VALUE) {
|
||||
if (mozilla::ipc::LoggingEnabled()) {
|
||||
fprintf(stderr,
|
||||
|
|
|
@ -19,10 +19,6 @@
|
|||
#include "mozilla/ipc/ScopedPort.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
#ifdef FUZZING
|
||||
# include "mozilla/ipc/Faulty.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
#ifdef FUZZING_SNAPSHOT
|
||||
|
@ -47,9 +43,6 @@ class Channel;
|
|||
class Message;
|
||||
class MessageReader;
|
||||
class MessageWriter;
|
||||
#ifdef FUZZING
|
||||
class Faulty;
|
||||
#endif
|
||||
struct LogData;
|
||||
|
||||
class Message : public mojo::core::ports::UserMessage, public Pickle {
|
||||
|
@ -361,9 +354,6 @@ class Message : public mojo::core::ports::UserMessage, public Pickle {
|
|||
friend class Channel;
|
||||
friend class MessageReplyDeserializer;
|
||||
friend class SyncMessage;
|
||||
#ifdef FUZZING
|
||||
friend class mozilla::ipc::Faulty;
|
||||
#endif
|
||||
friend class mozilla::ipc::MiniTransceiver;
|
||||
|
||||
#if !defined(OS_MACOSX) && !defined(FUZZING_SNAPSHOT)
|
||||
|
|
|
@ -109,9 +109,6 @@ class AutoEnterTransaction;
|
|||
|
||||
class MessageChannel : HasResultCodes {
|
||||
friend class PortLink;
|
||||
#ifdef FUZZING
|
||||
friend class ProtocolFuzzerHelper;
|
||||
#endif
|
||||
|
||||
typedef mozilla::Monitor Monitor;
|
||||
|
||||
|
|
|
@ -100,10 +100,6 @@ class NeckoParent;
|
|||
|
||||
namespace ipc {
|
||||
|
||||
#ifdef FUZZING
|
||||
class ProtocolFuzzerHelper;
|
||||
#endif
|
||||
|
||||
// Scoped base::ProcessHandle to ensure base::CloseProcessHandle is called.
|
||||
struct ScopedProcessHandleTraits {
|
||||
typedef base::ProcessHandle type;
|
||||
|
@ -380,10 +376,6 @@ class ManagedEndpoint;
|
|||
* this protocol actor.
|
||||
*/
|
||||
class IToplevelProtocol : public IProtocol {
|
||||
#ifdef FUZZING
|
||||
friend class mozilla::ipc::ProtocolFuzzerHelper;
|
||||
#endif
|
||||
|
||||
template <class PFooSide>
|
||||
friend class Endpoint;
|
||||
|
||||
|
|
|
@ -63,10 +63,6 @@ namespace ipc {
|
|||
class IProtocol;
|
||||
class IToplevelProtocol;
|
||||
|
||||
#ifdef FUZZING
|
||||
class ProtocolFuzzerHelper;
|
||||
#endif
|
||||
|
||||
template <typename P>
|
||||
struct IPDLParamTraits;
|
||||
|
||||
|
@ -78,12 +74,6 @@ class Shmem final {
|
|||
// For ShadowLayerForwarder::CheckSurfaceDescriptor
|
||||
friend class mozilla::layers::ShadowLayerForwarder;
|
||||
#endif
|
||||
#ifdef FUZZING
|
||||
friend class ProtocolFuzzerHelper;
|
||||
template <typename T>
|
||||
friend void FuzzProtocol(T*, const uint8_t*, size_t,
|
||||
const nsTArray<nsCString>&);
|
||||
#endif
|
||||
|
||||
public:
|
||||
typedef int32_t id_t;
|
||||
|
|
|
@ -1,778 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include <cerrno>
|
||||
#include <climits>
|
||||
#include <cmath>
|
||||
#include <fstream>
|
||||
#include <mutex>
|
||||
#include <prinrval.h>
|
||||
#include <type_traits>
|
||||
#ifdef _WINDOWS
|
||||
# include <process.h>
|
||||
# define getpid _getpid
|
||||
#else
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#include "base/string_util.h"
|
||||
#include "FuzzingMutate.h"
|
||||
#include "FuzzingTraits.h"
|
||||
#include "chrome/common/ipc_channel.h"
|
||||
#include "chrome/common/ipc_message.h"
|
||||
#include "mozilla/ipc/Faulty.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIFileStreams.h"
|
||||
#include "nsILineInputStream.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsLocalFile.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "prenv.h"
|
||||
|
||||
#ifdef IsLoggingEnabled
|
||||
// This is defined in the Windows SDK urlmon.h
|
||||
# undef IsLoggingEnabled
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
using namespace mozilla::fuzzing;
|
||||
|
||||
/**
|
||||
* FuzzIntegralType mutates an incercepted integral type of a pickled message.
|
||||
*/
|
||||
template <typename T>
|
||||
void FuzzIntegralType(T* v, bool largeValues) {
|
||||
static_assert(std::is_integral_v<T> == true, "T must be an integral type");
|
||||
switch (FuzzingTraits::Random(6)) {
|
||||
case 0:
|
||||
if (largeValues) {
|
||||
(*v) = RandomInteger<T>();
|
||||
break;
|
||||
}
|
||||
[[fallthrough]];
|
||||
case 1:
|
||||
if (largeValues) {
|
||||
(*v) = RandomNumericLimit<T>();
|
||||
break;
|
||||
}
|
||||
[[fallthrough]];
|
||||
case 2:
|
||||
if (largeValues) {
|
||||
(*v) = RandomIntegerRange<T>(std::numeric_limits<T>::min(),
|
||||
std::numeric_limits<T>::max());
|
||||
break;
|
||||
}
|
||||
[[fallthrough]];
|
||||
default:
|
||||
switch (FuzzingTraits::Random(2)) {
|
||||
case 0:
|
||||
// Prevent underflow
|
||||
if (*v != std::numeric_limits<T>::min()) {
|
||||
(*v)--;
|
||||
break;
|
||||
}
|
||||
[[fallthrough]];
|
||||
case 1:
|
||||
// Prevent overflow
|
||||
if (*v != std::numeric_limits<T>::max()) {
|
||||
(*v)++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* FuzzFloatingPointType mutates an incercepted floating-point type of a
|
||||
* pickled message.
|
||||
*/
|
||||
template <typename T>
|
||||
void FuzzFloatingPointType(T* v, bool largeValues) {
|
||||
static_assert(std::is_floating_point_v<T> == true,
|
||||
"T must be a floating point type");
|
||||
switch (FuzzingTraits::Random(6)) {
|
||||
case 0:
|
||||
if (largeValues) {
|
||||
(*v) = RandomNumericLimit<T>();
|
||||
break;
|
||||
}
|
||||
[[fallthrough]];
|
||||
case 1:
|
||||
if (largeValues) {
|
||||
(*v) = RandomFloatingPointRange<T>(std::numeric_limits<T>::min(),
|
||||
std::numeric_limits<T>::max());
|
||||
break;
|
||||
}
|
||||
[[fallthrough]];
|
||||
default:
|
||||
(*v) = RandomFloatingPoint<T>();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* FuzzStringType mutates an incercepted string type of a pickled message.
|
||||
*/
|
||||
template <typename T>
|
||||
void FuzzStringType(T& v, const T& literal1, const T& literal2) {
|
||||
switch (FuzzingTraits::Random(5)) {
|
||||
case 4:
|
||||
v = v + v;
|
||||
[[fallthrough]];
|
||||
case 3:
|
||||
v = v + v;
|
||||
[[fallthrough]];
|
||||
case 2:
|
||||
v = v + v;
|
||||
break;
|
||||
case 1:
|
||||
v += literal1;
|
||||
break;
|
||||
case 0:
|
||||
v = literal2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Faulty::Faulty()
|
||||
// Mutate messages as a blob.
|
||||
: mFuzzMessages(!!PR_GetEnv("FAULTY_MESSAGES"))
|
||||
// Enables the strategy for fuzzing pipes.
|
||||
,
|
||||
mFuzzPipes(!!PR_GetEnv("FAULTY_PIPE"))
|
||||
// Enables the strategy for fuzzing pickled messages.
|
||||
,
|
||||
mFuzzPickle(!!PR_GetEnv("FAULTY_PICKLE"))
|
||||
// Uses very large values while fuzzing pickled messages.
|
||||
// This may cause a high amount of malloc_abort() / NS_ABORT_OOM crashes.
|
||||
,
|
||||
mUseLargeValues(!!PR_GetEnv("FAULTY_LARGE_VALUES"))
|
||||
// Use the provided blacklist as whitelist.
|
||||
,
|
||||
mUseAsWhitelist(!!PR_GetEnv("FAULTY_AS_WHITELIST"))
|
||||
// Sets up our target process.
|
||||
,
|
||||
mIsValidProcessType(IsValidProcessType()) {
|
||||
if (mIsValidProcessType) {
|
||||
FAULTY_LOG("Initializing for new process of type '%s' with pid %u.",
|
||||
XRE_GetProcessTypeString(), getpid());
|
||||
|
||||
/* Setup random seed. */
|
||||
const char* userSeed = PR_GetEnv("FAULTY_SEED");
|
||||
unsigned long randomSeed = static_cast<unsigned long>(PR_IntervalNow());
|
||||
if (userSeed) {
|
||||
long n = std::strtol(userSeed, nullptr, 10);
|
||||
if (n != 0) {
|
||||
randomSeed = static_cast<unsigned long>(n);
|
||||
}
|
||||
}
|
||||
FuzzingTraits::Rng().seed(randomSeed);
|
||||
|
||||
/* Setup directory for dumping messages. */
|
||||
mMessagePath = PR_GetEnv("FAULTY_MESSAGE_PATH");
|
||||
if (mMessagePath && *mMessagePath) {
|
||||
if (CreateOutputDirectory(mMessagePath) != NS_OK) {
|
||||
mMessagePath = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set IPC messages blacklist. */
|
||||
mBlacklistPath = PR_GetEnv("FAULTY_BLACKLIST");
|
||||
if (mBlacklistPath && *mBlacklistPath) {
|
||||
FAULTY_LOG("* Using message blacklist = %s", mBlacklistPath);
|
||||
}
|
||||
|
||||
FAULTY_LOG("* Fuzzing strategy: messages = %s",
|
||||
mFuzzMessages ? "enabled" : "disabled");
|
||||
FAULTY_LOG("* Fuzzing strategy: pickle = %s",
|
||||
mFuzzPickle ? "enabled" : "disabled");
|
||||
FAULTY_LOG("* Fuzzing strategy: pipe = %s",
|
||||
mFuzzPipes ? "enabled" : "disabled");
|
||||
FAULTY_LOG("* Fuzzing probability = %u", DefaultProbability());
|
||||
FAULTY_LOG("* Fuzzing mutation factor = %u", MutationFactor());
|
||||
FAULTY_LOG("* RNG seed = %lu", randomSeed);
|
||||
|
||||
sMsgCounter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
bool Faulty::IsValidProcessType(void) {
|
||||
bool isValidProcessType;
|
||||
const bool targetChildren = !!PR_GetEnv("FAULTY_CHILDREN");
|
||||
const bool targetParent = !!PR_GetEnv("FAULTY_PARENT");
|
||||
const bool isParent = XRE_IsParentProcess();
|
||||
|
||||
if (targetChildren && !targetParent) {
|
||||
// Fuzz every child process type but not the parent process.
|
||||
isValidProcessType = isParent;
|
||||
} else if (!targetChildren && targetParent && !isParent) {
|
||||
// Fuzz inside any of the above child process only.
|
||||
isValidProcessType = true;
|
||||
} else if (targetChildren && targetParent) {
|
||||
// Fuzz every process type.
|
||||
isValidProcessType = true;
|
||||
} else {
|
||||
// Fuzz no process type at all.
|
||||
isValidProcessType = false;
|
||||
}
|
||||
|
||||
if (!isValidProcessType) {
|
||||
FAULTY_LOG("Disabled for this process of type '%s' with pid %d.",
|
||||
XRE_GetProcessTypeString(), getpid());
|
||||
}
|
||||
|
||||
return isValidProcessType;
|
||||
}
|
||||
|
||||
// static
|
||||
unsigned int Faulty::DefaultProbability() {
|
||||
static std::once_flag flag;
|
||||
static unsigned probability;
|
||||
|
||||
std::call_once(flag, [&] {
|
||||
probability = FAULTY_DEFAULT_PROBABILITY;
|
||||
// Defines the likelihood of fuzzing a message.
|
||||
if (const char* p = PR_GetEnv("FAULTY_PROBABILITY")) {
|
||||
long n = std::strtol(p, nullptr, 10);
|
||||
if (n != 0) {
|
||||
probability = n;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return probability;
|
||||
}
|
||||
|
||||
// static
|
||||
bool Faulty::IsLoggingEnabled(void) {
|
||||
static bool enabled;
|
||||
static std::once_flag flag;
|
||||
std::call_once(flag, [&] { enabled = !!PR_GetEnv("FAULTY_ENABLE_LOGGING"); });
|
||||
return enabled;
|
||||
}
|
||||
|
||||
// static
|
||||
uint32_t Faulty::MutationFactor() {
|
||||
static uint64_t sPropValue = FAULTY_DEFAULT_MUTATION_FACTOR;
|
||||
static bool sInitialized = false;
|
||||
|
||||
if (sInitialized) {
|
||||
return sPropValue;
|
||||
}
|
||||
sInitialized = true;
|
||||
|
||||
const char* factor = PR_GetEnv("FAULTY_MUTATION_FACTOR");
|
||||
if (factor) {
|
||||
long n = strtol(factor, nullptr, 10);
|
||||
if (n != 0) {
|
||||
sPropValue = n;
|
||||
return sPropValue;
|
||||
}
|
||||
}
|
||||
return sPropValue;
|
||||
}
|
||||
|
||||
// static
|
||||
Faulty& Faulty::instance() {
|
||||
static Faulty faulty;
|
||||
return faulty;
|
||||
}
|
||||
|
||||
//
|
||||
// Strategy: Pipes
|
||||
//
|
||||
|
||||
void Faulty::MaybeCollectAndClosePipe(int aPipe, unsigned int aProbability) {
|
||||
#ifndef _WINDOWS
|
||||
if (!mFuzzPipes) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aPipe > -1) {
|
||||
FAULTY_LOG("Collecting pipe %d to bucket of pipes (count: %zu)", aPipe,
|
||||
mFds.size());
|
||||
mFds.insert(aPipe);
|
||||
}
|
||||
|
||||
if (mFds.size() > 0 && FuzzingTraits::Sometimes(aProbability)) {
|
||||
std::set<int>::iterator it(mFds.begin());
|
||||
std::advance(it, FuzzingTraits::Random(mFds.size()));
|
||||
FAULTY_LOG("Trying to close collected pipe: %d", *it);
|
||||
errno = 0;
|
||||
while ((close(*it) == -1 && (errno == EINTR))) {
|
||||
;
|
||||
}
|
||||
FAULTY_LOG("Pipe status after attempt to close: %d", errno);
|
||||
mFds.erase(it);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
// Strategy: Pickle
|
||||
//
|
||||
|
||||
void Faulty::MutateBool(bool* aValue) { *aValue = !(*aValue); }
|
||||
|
||||
void Faulty::FuzzBool(bool* aValue, unsigned int aProbability) {
|
||||
if (mIsValidProcessType) {
|
||||
if (mFuzzPickle && FuzzingTraits::Sometimes(aProbability)) {
|
||||
bool oldValue = *aValue;
|
||||
MutateBool(aValue);
|
||||
FAULTY_LOG("Message field |bool| of value: %d mutated to: %d",
|
||||
(int)oldValue, (int)*aValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Faulty::MutateChar(char* aValue) { FuzzIntegralType<char>(aValue, true); }
|
||||
|
||||
void Faulty::FuzzChar(char* aValue, unsigned int aProbability) {
|
||||
if (mIsValidProcessType) {
|
||||
if (mFuzzPickle && FuzzingTraits::Sometimes(aProbability)) {
|
||||
char oldValue = *aValue;
|
||||
MutateChar(aValue);
|
||||
FAULTY_LOG("Message field |char| of value: %c mutated to: %c", oldValue,
|
||||
*aValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Faulty::MutateUChar(unsigned char* aValue) {
|
||||
FuzzIntegralType<unsigned char>(aValue, true);
|
||||
}
|
||||
|
||||
void Faulty::FuzzUChar(unsigned char* aValue, unsigned int aProbability) {
|
||||
if (mIsValidProcessType) {
|
||||
if (mFuzzPickle && FuzzingTraits::Sometimes(aProbability)) {
|
||||
unsigned char oldValue = *aValue;
|
||||
MutateUChar(aValue);
|
||||
FAULTY_LOG("Message field |unsigned char| of value: %u mutated to: %u",
|
||||
oldValue, *aValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Faulty::MutateInt16(int16_t* aValue) {
|
||||
FuzzIntegralType<int16_t>(aValue, true);
|
||||
}
|
||||
|
||||
void Faulty::FuzzInt16(int16_t* aValue, unsigned int aProbability) {
|
||||
if (mIsValidProcessType) {
|
||||
if (mFuzzPickle && FuzzingTraits::Sometimes(aProbability)) {
|
||||
int16_t oldValue = *aValue;
|
||||
MutateInt16(aValue);
|
||||
FAULTY_LOG("Message field |int16| of value: %d mutated to: %d", oldValue,
|
||||
*aValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Faulty::MutateUInt16(uint16_t* aValue) {
|
||||
FuzzIntegralType<uint16_t>(aValue, true);
|
||||
}
|
||||
|
||||
void Faulty::FuzzUInt16(uint16_t* aValue, unsigned int aProbability) {
|
||||
if (mIsValidProcessType) {
|
||||
if (mFuzzPickle && FuzzingTraits::Sometimes(aProbability)) {
|
||||
uint16_t oldValue = *aValue;
|
||||
MutateUInt16(aValue);
|
||||
FAULTY_LOG("Message field |uint16| of value: %d mutated to: %d", oldValue,
|
||||
*aValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Faulty::MutateInt(int* aValue) {
|
||||
FuzzIntegralType<int>(aValue, mUseLargeValues);
|
||||
}
|
||||
|
||||
void Faulty::FuzzInt(int* aValue, unsigned int aProbability) {
|
||||
if (mIsValidProcessType) {
|
||||
if (mFuzzPickle && FuzzingTraits::Sometimes(aProbability)) {
|
||||
int oldValue = *aValue;
|
||||
MutateInt(aValue);
|
||||
FAULTY_LOG("Message field |int| of value: %d mutated to: %d", oldValue,
|
||||
*aValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Faulty::MutateUInt32(uint32_t* aValue) {
|
||||
FuzzIntegralType<uint32_t>(aValue, mUseLargeValues);
|
||||
}
|
||||
|
||||
void Faulty::FuzzUInt32(uint32_t* aValue, unsigned int aProbability) {
|
||||
if (mIsValidProcessType) {
|
||||
if (mFuzzPickle && FuzzingTraits::Sometimes(aProbability)) {
|
||||
uint32_t oldValue = *aValue;
|
||||
MutateUInt32(aValue);
|
||||
FAULTY_LOG("Message field |uint32| of value: %u mutated to: %u", oldValue,
|
||||
*aValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Faulty::MutateLong(long* aValue) {
|
||||
FuzzIntegralType<long>(aValue, mUseLargeValues);
|
||||
}
|
||||
|
||||
void Faulty::FuzzLong(long* aValue, unsigned int aProbability) {
|
||||
if (mIsValidProcessType) {
|
||||
if (mFuzzPickle && FuzzingTraits::Sometimes(aProbability)) {
|
||||
long oldValue = *aValue;
|
||||
MutateLong(aValue);
|
||||
FAULTY_LOG("Message field |long| of value: %ld mutated to: %ld", oldValue,
|
||||
*aValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Faulty::MutateULong(unsigned long* aValue) {
|
||||
FuzzIntegralType<unsigned long>(aValue, mUseLargeValues);
|
||||
}
|
||||
|
||||
void Faulty::FuzzULong(unsigned long* aValue, unsigned int aProbability) {
|
||||
if (mIsValidProcessType) {
|
||||
if (mFuzzPickle && FuzzingTraits::Sometimes(aProbability)) {
|
||||
unsigned long oldValue = *aValue;
|
||||
MutateULong(aValue);
|
||||
FAULTY_LOG("Message field |unsigned long| of value: %lu mutated to: %lu",
|
||||
oldValue, *aValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Faulty::MutateUInt64(uint64_t* aValue) {
|
||||
FuzzIntegralType<uint64_t>(aValue, mUseLargeValues);
|
||||
}
|
||||
|
||||
void Faulty::FuzzUInt64(uint64_t* aValue, unsigned int aProbability) {
|
||||
if (mIsValidProcessType) {
|
||||
if (mFuzzPickle && FuzzingTraits::Sometimes(aProbability)) {
|
||||
uint64_t oldValue = *aValue;
|
||||
MutateUInt64(aValue);
|
||||
FAULTY_LOG("Message field |uint64| of value: %" PRIu64
|
||||
" mutated to: %" PRIu64,
|
||||
oldValue, *aValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Faulty::MutateInt64(int64_t* aValue) {
|
||||
FuzzIntegralType<int64_t>(aValue, mUseLargeValues);
|
||||
}
|
||||
|
||||
void Faulty::FuzzInt64(int64_t* aValue, unsigned int aProbability) {
|
||||
if (mIsValidProcessType) {
|
||||
if (mFuzzPickle && FuzzingTraits::Sometimes(aProbability)) {
|
||||
int64_t oldValue = *aValue;
|
||||
MutateInt64(aValue);
|
||||
FAULTY_LOG("Message field |int64| of value: %" PRIu64
|
||||
" mutated to: %" PRIu64,
|
||||
oldValue, *aValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Faulty::MutateDouble(double* aValue) {
|
||||
FuzzFloatingPointType<double>(aValue, mUseLargeValues);
|
||||
}
|
||||
|
||||
void Faulty::FuzzDouble(double* aValue, unsigned int aProbability) {
|
||||
if (mIsValidProcessType) {
|
||||
if (mFuzzPickle && FuzzingTraits::Sometimes(aProbability)) {
|
||||
double oldValue = *aValue;
|
||||
MutateDouble(aValue);
|
||||
FAULTY_LOG("Message field |double| of value: %f mutated to: %f", oldValue,
|
||||
*aValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Faulty::MutateFloat(float* aValue) {
|
||||
FuzzFloatingPointType<float>(aValue, mUseLargeValues);
|
||||
}
|
||||
|
||||
void Faulty::FuzzFloat(float* aValue, unsigned int aProbability) {
|
||||
if (mIsValidProcessType) {
|
||||
if (mFuzzPickle && FuzzingTraits::Sometimes(aProbability)) {
|
||||
float oldValue = *aValue;
|
||||
MutateFloat(aValue);
|
||||
FAULTY_LOG("Message field |float| of value: %f mutated to: %f", oldValue,
|
||||
*aValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Faulty::FuzzString(std::string& aValue, unsigned int aProbability) {
|
||||
if (mIsValidProcessType) {
|
||||
if (mFuzzPickle && FuzzingTraits::Sometimes(aProbability)) {
|
||||
std::string oldValue = aValue;
|
||||
FuzzStringType<std::string>(aValue, "xoferiF", std::string());
|
||||
FAULTY_LOG("Message field |string| of value: %s mutated to: %s",
|
||||
oldValue.c_str(), aValue.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Faulty::FuzzWString(std::wstring& aValue, unsigned int aProbability) {
|
||||
if (mIsValidProcessType) {
|
||||
if (mFuzzPickle && FuzzingTraits::Sometimes(aProbability)) {
|
||||
std::wstring oldValue = aValue;
|
||||
FAULTY_LOG("Message field |wstring|");
|
||||
FuzzStringType<std::wstring>(aValue, L"xoferiF", std::wstring());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult Faulty::CreateOutputDirectory(const char* aPathname) {
|
||||
nsCOMPtr<nsIFile> path;
|
||||
bool exists;
|
||||
nsresult rv;
|
||||
|
||||
rv = NS_NewNativeLocalFile(nsDependentCString(aPathname), true,
|
||||
getter_AddRefs(path));
|
||||
|
||||
rv = path->Exists(&exists);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!exists) {
|
||||
rv = path->Create(nsIFile::DIRECTORY_TYPE, 0755);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsresult Faulty::ReadFile(const char* aPathname, nsTArray<nsCString>& aArray) {
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIFile> file;
|
||||
|
||||
rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(aPathname), true,
|
||||
getter_AddRefs(file));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool exists = false;
|
||||
rv = file->Exists(&exists);
|
||||
if (NS_WARN_IF(NS_FAILED(rv)) || !exists) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFileInputStream> fileStream(
|
||||
do_CreateInstance(NS_LOCALFILEINPUTSTREAM_CONTRACTID, &rv));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = fileStream->Init(file, -1, -1, 0);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsILineInputStream> lineStream(do_QueryInterface(fileStream, &rv));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsAutoCString line;
|
||||
bool more = true;
|
||||
do {
|
||||
rv = lineStream->ReadLine(line, &more);
|
||||
if (line.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if (line.CharAt(0) == '#') {
|
||||
/* Ignore comments. */
|
||||
continue;
|
||||
}
|
||||
aArray.AppendElement(line);
|
||||
} while (more);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool Faulty::IsMessageNameBlacklisted(const char* aMessageName) {
|
||||
static bool sFileLoaded = false;
|
||||
static nsTArray<nsCString> sMessageBlacklist;
|
||||
|
||||
if (!sFileLoaded && mBlacklistPath) {
|
||||
/* Run ReadFile() on the main thread to prevent
|
||||
MOZ_ASSERT(NS_IsMainThread()) in nsStandardURL via nsNetStartup(). */
|
||||
nsCOMPtr<nsIRunnable> r =
|
||||
NS_NewRunnableFunction("Fuzzer::ReadBlacklistOnMainThread", [&]() {
|
||||
if (Faulty::ReadFile(mBlacklistPath, sMessageBlacklist) != NS_OK) {
|
||||
sFileLoaded = false;
|
||||
} else {
|
||||
sFileLoaded = true;
|
||||
}
|
||||
});
|
||||
NS_DispatchToMainThread(r.forget(), NS_DISPATCH_SYNC);
|
||||
}
|
||||
|
||||
if (!sFileLoaded) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sMessageBlacklist.Length() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return sMessageBlacklist.Contains(aMessageName);
|
||||
}
|
||||
|
||||
// static
|
||||
std::vector<uint8_t> Faulty::GetDataFromIPCMessage(IPC::Message* aMsg) {
|
||||
const Pickle::BufferList& buffers = aMsg->Buffers();
|
||||
std::vector<uint8_t> data;
|
||||
data.reserve(buffers.Size());
|
||||
|
||||
Pickle::BufferList::IterImpl i = buffers.Iter();
|
||||
while (!i.Done()) {
|
||||
size_t s = i.RemainingInSegment();
|
||||
data.insert(data.end(), i.Data(), i.Data() + s);
|
||||
|
||||
i.Advance(buffers, s);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
// static
|
||||
void Faulty::CopyFDs(IPC::Message* aDstMsg, IPC::Message* aSrcMsg) {
|
||||
std::swap(aDstMsg->attached_handles_, aSrcMsg->attached_handles_);
|
||||
}
|
||||
|
||||
UniquePtr<IPC::Message> Faulty::MutateIPCMessage(const char* aChannel,
|
||||
UniquePtr<IPC::Message> aMsg,
|
||||
unsigned int aProbability) {
|
||||
if (!mIsValidProcessType || !mFuzzMessages) {
|
||||
return aMsg;
|
||||
}
|
||||
|
||||
sMsgCounter += 1;
|
||||
LogMessage(aChannel, aMsg.get());
|
||||
|
||||
/* Skip immediately if we shall not try to fuzz this message. */
|
||||
if (!FuzzingTraits::Sometimes(aProbability)) {
|
||||
return aMsg;
|
||||
}
|
||||
|
||||
const bool isMessageListed = IsMessageNameBlacklisted(aMsg->name());
|
||||
|
||||
/* Check if this message is blacklisted and shall not get fuzzed. */
|
||||
if (isMessageListed && !mUseAsWhitelist) {
|
||||
FAULTY_LOG("BLACKLISTED: %s", aMsg->name());
|
||||
return aMsg;
|
||||
}
|
||||
|
||||
/* Check if the message is whitelisted. */
|
||||
if (!isMessageListed && mUseAsWhitelist) {
|
||||
/* Silently skip this message. */
|
||||
return aMsg;
|
||||
}
|
||||
|
||||
/* Retrieve BufferLists as data from original message. */
|
||||
std::vector<uint8_t> data(GetDataFromIPCMessage(aMsg.get()));
|
||||
|
||||
/* Check if there is enough data in the message to fuzz. */
|
||||
uint32_t headerSize = aMsg->HeaderSize();
|
||||
if (headerSize == data.size()) {
|
||||
FAULTY_LOG("IGNORING: %s", aMsg->name());
|
||||
return aMsg;
|
||||
}
|
||||
|
||||
/* Mutate the message data. */
|
||||
size_t maxMutations = FuzzingTraits::Frequency(data.size(), MutationFactor());
|
||||
FAULTY_LOG("FUZZING (%zu bytes): %s", maxMutations, aMsg->name());
|
||||
while (maxMutations--) {
|
||||
/* Ignore the header data of the message. */
|
||||
uint32_t pos = RandomIntegerRange<uint32_t>(headerSize, data.size() - 1);
|
||||
switch (FuzzingTraits::Random(6)) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
data.at(pos) = RandomIntegerRange<uint8_t>(0, 1);
|
||||
break;
|
||||
case 2:
|
||||
data.at(pos) ^= (1 << FuzzingTraits::Random(9));
|
||||
break;
|
||||
case 3:
|
||||
data.at(pos) = RandomIntegerRange<uint8_t>(254, 255);
|
||||
break;
|
||||
default:
|
||||
data.at(pos) = RandomIntegerRange<uint8_t>(0, 255);
|
||||
}
|
||||
}
|
||||
|
||||
/* Build new message. */
|
||||
auto mutatedMsg = MakeUnique<IPC::Message>(
|
||||
reinterpret_cast<const char*>(data.data()), data.size());
|
||||
CopyFDs(mutatedMsg.get(), aMsg.get());
|
||||
|
||||
/* Dump original message for diff purposes. */
|
||||
DumpMessage(aChannel, aMsg.get(),
|
||||
nsPrintfCString(".%zu.o", sMsgCounter).get());
|
||||
/* Dump mutated message for diff purposes. */
|
||||
DumpMessage(aChannel, mutatedMsg.get(),
|
||||
nsPrintfCString(".%zu.m", sMsgCounter).get());
|
||||
|
||||
return mutatedMsg;
|
||||
}
|
||||
|
||||
void Faulty::LogMessage(const char* aChannel, IPC::Message* aMsg) {
|
||||
if (!mIsValidProcessType) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string fileName =
|
||||
nsPrintfCString("message.%u.%zu", getpid(), sMsgCounter).get();
|
||||
|
||||
FAULTY_LOG("Process: %u | Size: %10zu | %-20s | %s => %s",
|
||||
XRE_GetProcessType(), aMsg->Buffers().Size(), fileName.c_str(),
|
||||
aChannel, aMsg->name());
|
||||
}
|
||||
|
||||
void Faulty::DumpMessage(const char* aChannel, IPC::Message* aMsg,
|
||||
std::string aAppendix) {
|
||||
if (!mIsValidProcessType || !mMessagePath) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> data(GetDataFromIPCMessage(aMsg));
|
||||
std::string fileName;
|
||||
|
||||
if (!aAppendix.empty()) {
|
||||
fileName = nsPrintfCString("%s/message.%u%s", mMessagePath, getpid(),
|
||||
aAppendix.c_str())
|
||||
.get();
|
||||
} else {
|
||||
fileName = nsPrintfCString("%s/%s", mMessagePath, fileName.c_str()).get();
|
||||
}
|
||||
|
||||
std::fstream fp;
|
||||
fp.open(fileName, std::fstream::out | std::fstream::binary);
|
||||
fp.write(reinterpret_cast<const char*>(data.data()), data.size());
|
||||
fp.close();
|
||||
}
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
|
@ -1,136 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_ipc_Faulty_h
|
||||
#define mozilla_ipc_Faulty_h
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "base/string16.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsTArray.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
#ifdef IsLoggingEnabled
|
||||
// This is defined in the Windows SDK urlmon.h
|
||||
# undef IsLoggingEnabled
|
||||
#endif
|
||||
|
||||
#define FAULTY_DEFAULT_PROBABILITY 1000
|
||||
#define FAULTY_DEFAULT_MUTATION_FACTOR 10
|
||||
#define FAULTY_LOG(fmt, args...) \
|
||||
if (mozilla::ipc::Faulty::IsLoggingEnabled()) { \
|
||||
printf_stderr("[Faulty] (%10u) " fmt "\n", getpid(), ##args); \
|
||||
}
|
||||
|
||||
namespace IPC {
|
||||
// Needed for blacklisting messages.
|
||||
class Message;
|
||||
class MessageReader;
|
||||
class MessageWriter;
|
||||
} // namespace IPC
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
class Faulty {
|
||||
public:
|
||||
// Used as a default argument for the Fuzz|datatype| methods.
|
||||
static unsigned int DefaultProbability();
|
||||
static bool IsLoggingEnabled(void);
|
||||
static std::vector<uint8_t> GetDataFromIPCMessage(IPC::Message* aMsg);
|
||||
static nsresult CreateOutputDirectory(const char* aPathname);
|
||||
static nsresult ReadFile(const char* aPathname, nsTArray<nsCString>& aArray);
|
||||
static void CopyFDs(IPC::Message* aDstMsg, IPC::Message* aSrcMsg);
|
||||
|
||||
static Faulty& instance();
|
||||
|
||||
// Fuzzing methods for Pickle.
|
||||
void FuzzBool(bool* aValue, unsigned int aProbability = DefaultProbability());
|
||||
void FuzzChar(char* aValue, unsigned int aProbability = DefaultProbability());
|
||||
void FuzzUChar(unsigned char* aValue,
|
||||
unsigned int aProbability = DefaultProbability());
|
||||
void FuzzInt16(int16_t* aValue,
|
||||
unsigned int aProbability = DefaultProbability());
|
||||
void FuzzUInt16(uint16_t* aValue,
|
||||
unsigned int aProbability = DefaultProbability());
|
||||
void FuzzInt(int* aValue, unsigned int aProbability = DefaultProbability());
|
||||
void FuzzUInt32(uint32_t* aValue,
|
||||
unsigned int aProbability = DefaultProbability());
|
||||
void FuzzLong(long* aValue, unsigned int aProbability = DefaultProbability());
|
||||
void FuzzULong(unsigned long* aValue,
|
||||
unsigned int aProbability = DefaultProbability());
|
||||
void FuzzInt64(int64_t* aValue,
|
||||
unsigned int aProbability = DefaultProbability());
|
||||
void FuzzUInt64(uint64_t* aValue,
|
||||
unsigned int aProbability = DefaultProbability());
|
||||
void FuzzFloat(float* aValue,
|
||||
unsigned int aProbability = DefaultProbability());
|
||||
void FuzzDouble(double* aValue,
|
||||
unsigned int aProbability = DefaultProbability());
|
||||
void FuzzString(std::string& aValue,
|
||||
unsigned int aProbability = DefaultProbability());
|
||||
void FuzzWString(std::wstring& aValue,
|
||||
unsigned int aProbability = DefaultProbability());
|
||||
void FuzzBytes(void* aData, int aLength,
|
||||
unsigned int aProbability = DefaultProbability());
|
||||
|
||||
// Fuzzing methods for pipe fuzzing.
|
||||
void MaybeCollectAndClosePipe(
|
||||
int aPipe, unsigned int aProbability = DefaultProbability());
|
||||
|
||||
// Fuzzing methods for message blob fuzzing.
|
||||
void DumpMessage(const char* aChannel, IPC::Message* aMsg,
|
||||
std::string aAppendix = nullptr);
|
||||
bool IsMessageNameBlacklisted(const char* aMessageName);
|
||||
UniquePtr<IPC::Message> MutateIPCMessage(
|
||||
const char* aChannel, UniquePtr<IPC::Message> aMsg,
|
||||
unsigned int aProbability = DefaultProbability());
|
||||
|
||||
void LogMessage(const char* aChannel, IPC::Message* aMsg);
|
||||
|
||||
private:
|
||||
std::set<int> mFds;
|
||||
|
||||
const bool mFuzzMessages;
|
||||
const bool mFuzzPipes;
|
||||
const bool mFuzzPickle;
|
||||
const bool mUseLargeValues;
|
||||
const bool mUseAsWhitelist;
|
||||
const bool mIsValidProcessType;
|
||||
|
||||
const char* mMessagePath;
|
||||
const char* mBlacklistPath;
|
||||
|
||||
size_t sMsgCounter;
|
||||
|
||||
Faulty();
|
||||
DISALLOW_EVIL_CONSTRUCTORS(Faulty);
|
||||
|
||||
static bool IsValidProcessType(void);
|
||||
static uint32_t MutationFactor();
|
||||
|
||||
// Fuzzing methods for Pickle
|
||||
void MutateBool(bool* aValue);
|
||||
void MutateChar(char* aValue);
|
||||
void MutateUChar(unsigned char* aValue);
|
||||
void MutateInt16(int16_t* aValue);
|
||||
void MutateUInt16(uint16_t* aValue);
|
||||
void MutateInt(int* aValue);
|
||||
void MutateUInt32(uint32_t* aValue);
|
||||
void MutateLong(long* aValue);
|
||||
void MutateULong(unsigned long* aValue);
|
||||
void MutateInt64(int64_t* aValue);
|
||||
void MutateUInt64(uint64_t* aValue);
|
||||
void MutateFloat(float* aValue);
|
||||
void MutateDouble(double* aValue);
|
||||
};
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
|
@ -1,13 +0,0 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
SOURCES += ["Faulty.cpp"]
|
||||
|
||||
EXPORTS.mozilla.ipc += ["Faulty.h"]
|
||||
|
||||
include("/ipc/chromium/chromium-config.mozbuild")
|
||||
|
||||
FINAL_LIBRARY = "xul"
|
|
@ -1,36 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/layers/CompositorBridgeParent.h"
|
||||
|
||||
#include "ProtocolFuzzer.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
nsTArray<nsCString> LoadIPCMessageBlacklist(const char* aPath) {
|
||||
nsTArray<nsCString> blacklist;
|
||||
if (aPath) {
|
||||
nsresult result = Faulty::ReadFile(aPath, blacklist);
|
||||
MOZ_RELEASE_ASSERT(result == NS_OK);
|
||||
}
|
||||
return blacklist;
|
||||
}
|
||||
|
||||
mozilla::dom::ContentParent* ProtocolFuzzerHelper::CreateContentParent(
|
||||
const nsACString& aRemoteType) {
|
||||
auto* cp = new mozilla::dom::ContentParent(aRemoteType);
|
||||
// TODO: this duplicates MessageChannel::Open
|
||||
cp->GetIPCChannel()->mWorkerThread = GetCurrentSerialEventTarget();
|
||||
return cp;
|
||||
}
|
||||
|
||||
void ProtocolFuzzerHelper::CompositorBridgeParentSetup() {
|
||||
mozilla::layers::CompositorBridgeParent::Setup();
|
||||
}
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
|
@ -1,112 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_ipc_ProtocolFuzzer_h
|
||||
#define mozilla_ipc_ProtocolFuzzer_h
|
||||
|
||||
#include "chrome/common/ipc_message.h"
|
||||
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/UniquePtrExtensions.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
class ProtocolFuzzerHelper {
|
||||
public:
|
||||
static mozilla::dom::ContentParent* CreateContentParent(
|
||||
const nsACString& aRemoteType);
|
||||
|
||||
static void CompositorBridgeParentSetup();
|
||||
|
||||
static void AddShmemToProtocol(IToplevelProtocol* aProtocol,
|
||||
Shmem::SharedMemory* aSegment, int32_t aId) {
|
||||
MOZ_ASSERT(!aProtocol->mShmemMap.Contains(aId),
|
||||
"Don't insert with an existing ID");
|
||||
aProtocol->mShmemMap.InsertOrUpdate(aId, aSegment);
|
||||
}
|
||||
|
||||
static void RemoveShmemFromProtocol(IToplevelProtocol* aProtocol,
|
||||
int32_t aId) {
|
||||
aProtocol->mShmemMap.Remove(aId);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
void FuzzProtocol(T* aProtocol, const uint8_t* aData, size_t aSize,
|
||||
const nsTArray<nsCString>& aIgnoredMessageTypes) {
|
||||
while (true) {
|
||||
uint32_t msg_size =
|
||||
IPC::Message::MessageSize(reinterpret_cast<const char*>(aData),
|
||||
reinterpret_cast<const char*>(aData) + aSize);
|
||||
if (msg_size == 0 || msg_size > aSize) {
|
||||
break;
|
||||
}
|
||||
IPC::Message m(reinterpret_cast<const char*>(aData), msg_size);
|
||||
aSize -= msg_size;
|
||||
aData += msg_size;
|
||||
|
||||
// We ignore certain message types
|
||||
if (aIgnoredMessageTypes.Contains(m.name())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint8_t num_shmems = 0;
|
||||
if (aSize) {
|
||||
num_shmems = *aData;
|
||||
aData++;
|
||||
aSize--;
|
||||
|
||||
for (uint32_t i = 0; i < num_shmems; i++) {
|
||||
if (aSize < sizeof(uint16_t)) {
|
||||
break;
|
||||
}
|
||||
size_t shmem_size = *reinterpret_cast<const uint16_t*>(aData);
|
||||
aData += sizeof(uint16_t);
|
||||
aSize -= sizeof(uint16_t);
|
||||
|
||||
if (shmem_size > aSize) {
|
||||
break;
|
||||
}
|
||||
RefPtr<Shmem::SharedMemory> segment(Shmem::Alloc(shmem_size, false));
|
||||
if (!segment) {
|
||||
break;
|
||||
}
|
||||
|
||||
Shmem shmem(segment.get(), i + 1);
|
||||
memcpy(shmem.get<uint8_t>(), aData, shmem_size);
|
||||
ProtocolFuzzerHelper::AddShmemToProtocol(
|
||||
aProtocol, segment.forget().take(), i + 1);
|
||||
|
||||
aData += shmem_size;
|
||||
aSize -= shmem_size;
|
||||
}
|
||||
}
|
||||
// TODO: attach |m.header().num_fds| file descriptors to |m|. MVP can be
|
||||
// empty files, next implementation maybe read a length header from |data|
|
||||
// and then that many bytes.
|
||||
|
||||
if (m.is_sync()) {
|
||||
UniquePtr<IPC::Message> reply;
|
||||
aProtocol->OnMessageReceived(m, reply);
|
||||
} else {
|
||||
aProtocol->OnMessageReceived(m);
|
||||
}
|
||||
for (uint32_t i = 0; i < num_shmems; i++) {
|
||||
Shmem::SharedMemory* segment = aProtocol->LookupSharedMemory(i + 1);
|
||||
Shmem::Dealloc(segment);
|
||||
ProtocolFuzzerHelper::RemoveShmemFromProtocol(aProtocol, i + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsTArray<nsCString> LoadIPCMessageBlacklist(const char* aPath);
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
|
@ -12,22 +12,13 @@ LOCAL_INCLUDES += [
|
|||
]
|
||||
|
||||
SOURCES += [
|
||||
"ProtocolFuzzer.cpp",
|
||||
"IPCFuzzController.cpp",
|
||||
]
|
||||
|
||||
EXPORTS += [
|
||||
"ProtocolFuzzer.h",
|
||||
EXPORTS.mozilla.fuzzing += [
|
||||
"IPCFuzzController.h",
|
||||
]
|
||||
|
||||
if CONFIG["FUZZING_SNAPSHOT"]:
|
||||
SOURCES += [
|
||||
"IPCFuzzController.cpp",
|
||||
]
|
||||
|
||||
EXPORTS.mozilla.fuzzing += [
|
||||
"IPCFuzzController.h",
|
||||
]
|
||||
|
||||
include("/ipc/chromium/chromium-config.mozbuild")
|
||||
|
||||
FINAL_LIBRARY = "xul"
|
||||
|
|
|
@ -12,14 +12,13 @@ DIRS += [
|
|||
if not CONFIG["JS_STANDALONE"]:
|
||||
DIRS += [
|
||||
"common",
|
||||
"faulty",
|
||||
"messagemanager",
|
||||
"shmem",
|
||||
"ipc",
|
||||
]
|
||||
|
||||
if CONFIG["FUZZING_SNAPSHOT"]:
|
||||
DIRS += [
|
||||
"ipc",
|
||||
"nyx",
|
||||
]
|
||||
|
||||
|
|
|
@ -106,7 +106,6 @@ avoid-blacklist-and-whitelist:
|
|||
- dom/html/MediaError.cpp
|
||||
- dom/indexedDB/ActorsParent.cpp
|
||||
- dom/ipc/ContentParent.cpp
|
||||
- dom/ipc/fuzztest/content_parent_ipc_libfuzz.cpp
|
||||
- dom/ipc/URLClassifierParent.cpp
|
||||
- dom/media/autoplay/AutoplayPolicy.cpp
|
||||
- dom/media/gmp/GMPChild.cpp
|
||||
|
@ -127,7 +126,6 @@ avoid-blacklist-and-whitelist:
|
|||
- dom/tests/mochitest/whatwg/test_postMessage_origin.xhtml
|
||||
- gfx/gl/GLContextProviderWGL.cpp
|
||||
- gfx/gl/GLUploadHelpers.cpp
|
||||
- gfx/layers/ipc/fuzztest/compositor_manager_parent_ipc_libfuzz.cpp
|
||||
- gfx/tests/mochitest/test_font_whitelist.html
|
||||
- gfx/thebes/gfxFT2FontList.cpp
|
||||
- gfx/thebes/gfxPlatformFontList.cpp
|
||||
|
@ -307,10 +305,6 @@ avoid-blacklist-and-whitelist:
|
|||
- toolkit/mozapps/extensions/test/xpinstall/browser_localfile4.js
|
||||
- toolkit/mozapps/extensions/test/xpinstall/browser_localfile4_postDownload.js
|
||||
- toolkit/mozapps/extensions/test/xpinstall/head.js
|
||||
- tools/fuzzing/faulty/Faulty.cpp
|
||||
- tools/fuzzing/faulty/Faulty.h
|
||||
- tools/fuzzing/ipc/ProtocolFuzzer.cpp
|
||||
- tools/fuzzing/ipc/ProtocolFuzzer.h
|
||||
- tools/fuzzing/messagemanager/MessageManagerFuzzer.cpp
|
||||
- tools/fuzzing/messagemanager/MessageManagerFuzzer.h
|
||||
- tools/lint/eslint/eslint-plugin-mozilla/lib/rules/no-define-cc-etc.js
|
||||
|
|
Загрузка…
Ссылка в новой задаче