mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-11 16:32:59 +00:00
Bug 1528951 - Implement Websocket fuzzing target for Necko. r=dragana
Differential Revision: https://phabricator.services.mozilla.com/D42816 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
72e1ec0f20
commit
95fc013b8b
@ -121,6 +121,11 @@ static PRInt32 FuzzyRecv(PRFileDesc* fd, void* buf, PRInt32 amount,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (gFuzzingConnClosed) {
|
||||
FUZZING_LOG(("[FuzzyRecv] Denying read, connection is closed."));
|
||||
return 0;
|
||||
}
|
||||
|
||||
// No data left, act as if the connection was closed.
|
||||
if (!gFuzzingSize) return 0;
|
||||
|
||||
|
@ -3795,8 +3795,14 @@ WebSocketChannel::OnStartRequest(nsIRequest* aRequest) {
|
||||
"HTTP response header Sec-WebSocket-Accept check failed\n"));
|
||||
LOG(("WebSocketChannel::OnStartRequest: Expected %s received %s\n",
|
||||
mHashedSecret.get(), respAccept.get()));
|
||||
AbortSession(NS_ERROR_ILLEGAL_VALUE);
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
#ifdef FUZZING
|
||||
if (NS_FAILED(rv) || respAccept.IsEmpty()) {
|
||||
#endif
|
||||
AbortSession(NS_ERROR_ILLEGAL_VALUE);
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
#ifdef FUZZING
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,3 +57,5 @@ LOCAL_INCLUDES += [
|
||||
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
CXXFLAGS += ['-Wno-error=shadow']
|
||||
|
||||
include('/tools/fuzzing/libfuzzer-config.mozbuild')
|
||||
|
217
netwerk/test/fuzz/TestWebsocketFuzzing.cpp
Normal file
217
netwerk/test/fuzz/TestWebsocketFuzzing.cpp
Normal file
@ -0,0 +1,217 @@
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
#include "FuzzingInterface.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsCycleCollector.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIWebSocketChannel.h"
|
||||
#include "nsIWebSocketListener.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsString.h"
|
||||
#include "nsScriptSecurityManager.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "NullPrincipal.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
// Used to determine if the fuzzing target should use https:// in spec.
|
||||
static bool fuzzWSS = true;
|
||||
|
||||
class FuzzingWebSocketListener final : public nsIWebSocketListener {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIWEBSOCKETLISTENER
|
||||
|
||||
FuzzingWebSocketListener() = default;
|
||||
|
||||
void waitUntilDoneOrStarted() {
|
||||
SpinEventLoopUntil([&]() { return mChannelDone || mChannelStarted; });
|
||||
}
|
||||
|
||||
void waitUntilDone() {
|
||||
SpinEventLoopUntil([&]() { return mChannelDone; });
|
||||
}
|
||||
|
||||
void waitUntilDoneOrAck() {
|
||||
SpinEventLoopUntil([&]() { return mChannelDone || mChannelAck; });
|
||||
}
|
||||
|
||||
bool isStarted() { return mChannelStarted; }
|
||||
|
||||
private:
|
||||
~FuzzingWebSocketListener() = default;
|
||||
bool mChannelDone = false;
|
||||
bool mChannelStarted = false;
|
||||
bool mChannelAck = false;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(FuzzingWebSocketListener, nsIWebSocketListener)
|
||||
|
||||
NS_IMETHODIMP
|
||||
FuzzingWebSocketListener::OnStart(nsISupports* aContext) {
|
||||
FUZZING_LOG(("FuzzingWebSocketListener::OnStart"));
|
||||
mChannelStarted = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FuzzingWebSocketListener::OnStop(nsISupports* aContext, nsresult aStatusCode) {
|
||||
FUZZING_LOG(("FuzzingWebSocketListener::OnStop"));
|
||||
mChannelDone = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FuzzingWebSocketListener::OnAcknowledge(nsISupports* aContext, uint32_t aSize) {
|
||||
FUZZING_LOG(("FuzzingWebSocketListener::OnAcknowledge"));
|
||||
mChannelAck = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FuzzingWebSocketListener::OnServerClose(nsISupports* aContext, uint16_t aCode,
|
||||
const nsACString& aReason) {
|
||||
FUZZING_LOG(("FuzzingWebSocketListener::OnServerClose"));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FuzzingWebSocketListener::OnMessageAvailable(nsISupports* aContext,
|
||||
const nsACString& aMsg) {
|
||||
FUZZING_LOG(("FuzzingWebSocketListener::OnMessageAvailable"));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FuzzingWebSocketListener::OnBinaryMessageAvailable(nsISupports* aContext,
|
||||
const nsACString& aMsg) {
|
||||
FUZZING_LOG(("FuzzingWebSocketListener::OnBinaryMessageAvailable"));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Forward declaration to the function in FuzzyLayer.cpp,
|
||||
// used to set the buffer to the global defined there.
|
||||
void setNetworkFuzzingBuffer(const uint8_t* data, size_t size);
|
||||
extern Atomic<bool> gFuzzingConnClosed;
|
||||
|
||||
static int FuzzingInitNetworkWebsocket(int* argc, char*** argv) {
|
||||
Preferences::SetBool("network.dns.native-is-localhost", true);
|
||||
Preferences::SetBool("fuzzing.necko.enabled", true);
|
||||
Preferences::SetBool("network.websocket.delay-failed-reconnects", false);
|
||||
Preferences::SetInt("network.http.speculative-parallel-limit", 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int FuzzingInitNetworkWebsocketPlain(int* argc, char*** argv) {
|
||||
fuzzWSS = false;
|
||||
return FuzzingInitNetworkWebsocket(argc, argv);
|
||||
}
|
||||
|
||||
static int FuzzingRunNetworkWebsocket(const uint8_t* data, size_t size) {
|
||||
// Set the data to be processed
|
||||
setNetworkFuzzingBuffer(data, size);
|
||||
|
||||
nsWeakPtr channelRef;
|
||||
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsSecurityFlags secFlags;
|
||||
secFlags = nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL |
|
||||
nsILoadInfo::SEC_SANDBOXED;
|
||||
|
||||
nsCOMPtr<nsIURI> url;
|
||||
nsAutoCString spec;
|
||||
RefPtr<FuzzingWebSocketListener> gWebSocketListener;
|
||||
nsCOMPtr<nsIWebSocketChannel> gWebSocketChannel;
|
||||
|
||||
if (fuzzWSS) {
|
||||
spec = "https://127.0.0.1/";
|
||||
gWebSocketChannel =
|
||||
do_CreateInstance("@mozilla.org/network/protocol;1?name=wss", &rv);
|
||||
} else {
|
||||
spec = "http://127.0.0.1/";
|
||||
gWebSocketChannel =
|
||||
do_CreateInstance("@mozilla.org/network/protocol;1?name=ws", &rv);
|
||||
}
|
||||
|
||||
if (rv != NS_OK) {
|
||||
MOZ_CRASH("Failed to create WebSocketChannel");
|
||||
}
|
||||
|
||||
if (NS_NewURI(getter_AddRefs(url), spec) != NS_OK) {
|
||||
MOZ_CRASH("Call to NS_NewURI failed.");
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> nullPrincipal =
|
||||
NullPrincipal::CreateWithoutOriginAttributes();
|
||||
|
||||
rv = gWebSocketChannel->InitLoadInfo(nullptr, nullPrincipal,
|
||||
nsContentUtils::GetSystemPrincipal(),
|
||||
secFlags, nsIContentPolicy::TYPE_WEBSOCKET);
|
||||
|
||||
if (rv != NS_OK) {
|
||||
MOZ_CRASH("Failed to call InitLoadInfo");
|
||||
}
|
||||
|
||||
gWebSocketListener = new FuzzingWebSocketListener();
|
||||
|
||||
rv =
|
||||
gWebSocketChannel->AsyncOpen(url, spec, 0, gWebSocketListener, nullptr);
|
||||
|
||||
if (rv == NS_OK) {
|
||||
FUZZING_LOG(("Successful call to AsyncOpen"));
|
||||
|
||||
// Wait for StartRequest or StopRequest
|
||||
gWebSocketListener->waitUntilDoneOrStarted();
|
||||
|
||||
if (gWebSocketListener->isStarted()) {
|
||||
rv =
|
||||
gWebSocketChannel->SendBinaryMsg(NS_LITERAL_CSTRING("Hello world"));
|
||||
|
||||
if (rv != NS_OK) {
|
||||
FUZZING_LOG(("Warning: Failed to call SendBinaryMsg"));
|
||||
} else {
|
||||
gWebSocketListener->waitUntilDoneOrAck();
|
||||
}
|
||||
|
||||
rv = gWebSocketChannel->Close(1000, NS_LITERAL_CSTRING(""));
|
||||
|
||||
if (rv != NS_OK) {
|
||||
FUZZING_LOG(("Warning: Failed to call close"));
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for StopRequest
|
||||
gWebSocketListener->waitUntilDone();
|
||||
} else {
|
||||
FUZZING_LOG(("Warning: Failed to call AsyncOpen"));
|
||||
}
|
||||
|
||||
channelRef = do_GetWeakReference(gWebSocketChannel);
|
||||
}
|
||||
|
||||
// Wait for the channel to be destroyed
|
||||
SpinEventLoopUntil([&]() -> bool {
|
||||
nsCycleCollector_collect(nullptr);
|
||||
nsCOMPtr<nsIWebSocketChannel> channel = do_QueryReferent(channelRef);
|
||||
return channel == nullptr;
|
||||
});
|
||||
|
||||
// Wait for the connection to indicate closed
|
||||
SpinEventLoopUntil([&]() -> bool { return gFuzzingConnClosed; });
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MOZ_FUZZING_INTERFACE_RAW(FuzzingInitNetworkWebsocket,
|
||||
FuzzingRunNetworkWebsocket, NetworkWebsocket);
|
||||
MOZ_FUZZING_INTERFACE_RAW(FuzzingInitNetworkWebsocketPlain,
|
||||
FuzzingRunNetworkWebsocket, NetworkWebsocketPlain);
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
@ -6,6 +6,7 @@
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'TestHttpFuzzing.cpp',
|
||||
'TestWebsocketFuzzing.cpp',
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
|
Loading…
Reference in New Issue
Block a user