2018-09-11 01:01:10 +03:00
|
|
|
/* -*- 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/. */
|
|
|
|
|
2018-09-12 13:14:10 +03:00
|
|
|
#include <windows.h>
|
2018-09-11 01:01:10 +03:00
|
|
|
#include <winternl.h>
|
|
|
|
|
2019-06-11 20:15:20 +03:00
|
|
|
#include <process.h>
|
2018-09-11 01:01:10 +03:00
|
|
|
|
2019-06-11 20:15:20 +03:00
|
|
|
#include "gtest/gtest.h"
|
2018-09-11 01:01:10 +03:00
|
|
|
|
2019-06-11 20:15:20 +03:00
|
|
|
#include "mozilla/ArrayUtils.h"
|
|
|
|
#include "mozilla/Char16.h"
|
|
|
|
#include "nsDirectoryServiceDefs.h"
|
|
|
|
#include "nsDirectoryServiceUtils.h"
|
|
|
|
#include "nsString.h"
|
|
|
|
#include "nsTArray.h"
|
|
|
|
#include "nsWindowsHelpers.h"
|
2018-09-11 01:01:10 +03:00
|
|
|
|
2019-06-11 20:15:20 +03:00
|
|
|
static nsString GetFullPath(const nsAString& aLeaf) {
|
2018-09-11 01:01:10 +03:00
|
|
|
nsCOMPtr<nsIFile> f;
|
2019-06-11 20:15:20 +03:00
|
|
|
|
2018-09-11 01:01:10 +03:00
|
|
|
EXPECT_TRUE(NS_SUCCEEDED(
|
|
|
|
NS_GetSpecialDirectory(NS_OS_CURRENT_WORKING_DIR, getter_AddRefs(f))));
|
2019-06-11 20:15:20 +03:00
|
|
|
|
|
|
|
EXPECT_TRUE(NS_SUCCEEDED(f->Append(aLeaf)));
|
2018-09-11 01:01:10 +03:00
|
|
|
|
|
|
|
bool exists;
|
2019-06-11 20:15:20 +03:00
|
|
|
EXPECT_TRUE(NS_SUCCEEDED(f->Exists(&exists)) && exists);
|
2018-09-11 01:01:10 +03:00
|
|
|
|
|
|
|
nsString ret;
|
|
|
|
EXPECT_TRUE(NS_SUCCEEDED(f->GetPath(ret)));
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-07-06 11:18:28 +03:00
|
|
|
TEST(TestDllBlocklist, BlockDllByName)
|
|
|
|
{
|
2018-09-11 01:01:10 +03:00
|
|
|
// The DLL name has capital letters, so this also tests that the comparison
|
|
|
|
// is case-insensitive.
|
2019-06-11 20:15:20 +03:00
|
|
|
NS_NAMED_LITERAL_STRING(kLeafName, "TestDllBlocklist_MatchByName.dll");
|
|
|
|
nsString dllPath = GetFullPath(kLeafName);
|
2018-09-11 01:01:10 +03:00
|
|
|
|
2019-06-11 20:15:20 +03:00
|
|
|
nsModuleHandle hDll(::LoadLibraryW(dllPath.get()));
|
2018-09-11 01:01:10 +03:00
|
|
|
|
2019-06-11 20:15:20 +03:00
|
|
|
EXPECT_TRUE(!hDll);
|
|
|
|
EXPECT_TRUE(!::GetModuleHandleW(kLeafName.get()));
|
2018-09-11 01:01:10 +03:00
|
|
|
}
|
|
|
|
|
2019-07-06 11:18:28 +03:00
|
|
|
TEST(TestDllBlocklist, BlockDllByVersion)
|
|
|
|
{
|
2019-06-11 20:15:20 +03:00
|
|
|
NS_NAMED_LITERAL_STRING(kLeafName, "TestDllBlocklist_MatchByVersion.dll");
|
|
|
|
nsString dllPath = GetFullPath(kLeafName);
|
2018-09-11 01:01:10 +03:00
|
|
|
|
2019-06-11 20:15:20 +03:00
|
|
|
nsModuleHandle hDll(::LoadLibraryW(dllPath.get()));
|
2018-09-11 01:01:10 +03:00
|
|
|
|
2019-06-11 20:15:20 +03:00
|
|
|
EXPECT_TRUE(!hDll);
|
|
|
|
EXPECT_TRUE(!::GetModuleHandleW(kLeafName.get()));
|
|
|
|
}
|
2018-09-11 01:01:10 +03:00
|
|
|
|
2019-07-06 11:18:28 +03:00
|
|
|
TEST(TestDllBlocklist, AllowDllByVersion)
|
|
|
|
{
|
2019-06-11 20:15:20 +03:00
|
|
|
NS_NAMED_LITERAL_STRING(kLeafName, "TestDllBlocklist_AllowByVersion.dll");
|
|
|
|
nsString dllPath = GetFullPath(kLeafName);
|
2018-09-11 01:01:10 +03:00
|
|
|
|
2019-06-11 20:15:20 +03:00
|
|
|
nsModuleHandle hDll(::LoadLibraryW(dllPath.get()));
|
|
|
|
|
|
|
|
EXPECT_TRUE(!!hDll);
|
|
|
|
EXPECT_TRUE(!!::GetModuleHandleW(kLeafName.get()));
|
2018-09-11 01:01:10 +03:00
|
|
|
}
|
|
|
|
|
2019-06-11 20:15:20 +03:00
|
|
|
#define DLL_BLOCKLIST_ENTRY(name, ...) {name, __VA_ARGS__},
|
|
|
|
#define DLL_BLOCKLIST_STRING_TYPE const char*
|
2019-07-16 21:02:13 +03:00
|
|
|
#include "mozilla/WindowsDllBlocklistLegacyDefs.h"
|
2018-09-11 01:01:10 +03:00
|
|
|
|
2019-07-06 11:18:28 +03:00
|
|
|
TEST(TestDllBlocklist, BlocklistIntegrity)
|
|
|
|
{
|
2019-06-11 20:15:20 +03:00
|
|
|
nsTArray<DLL_BLOCKLIST_STRING_TYPE> dupes;
|
|
|
|
DECLARE_POINTER_TO_FIRST_DLL_BLOCKLIST_ENTRY(pFirst);
|
|
|
|
DECLARE_POINTER_TO_LAST_DLL_BLOCKLIST_ENTRY(pLast);
|
2018-09-11 01:01:10 +03:00
|
|
|
|
2019-07-16 21:02:13 +03:00
|
|
|
EXPECT_FALSE(pLast->mName || pLast->mMaxVersion || pLast->mFlags);
|
2019-06-11 20:15:20 +03:00
|
|
|
|
|
|
|
for (size_t i = 0; i < mozilla::ArrayLength(gWindowsDllBlocklist) - 1; ++i) {
|
|
|
|
auto pEntry = pFirst + i;
|
2018-09-11 01:01:10 +03:00
|
|
|
|
2019-06-11 20:15:20 +03:00
|
|
|
// Validate name
|
2019-07-16 21:02:13 +03:00
|
|
|
EXPECT_TRUE(!!pEntry->mName);
|
|
|
|
EXPECT_GT(strlen(pEntry->mName), 3);
|
2019-06-11 20:15:20 +03:00
|
|
|
|
|
|
|
// Check the filename for valid characters.
|
2019-07-16 21:02:13 +03:00
|
|
|
for (auto pch = pEntry->mName; *pch != 0; ++pch) {
|
2019-06-11 20:15:20 +03:00
|
|
|
EXPECT_FALSE(*pch >= 'A' && *pch <= 'Z');
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check for duplicate entries
|
|
|
|
for (auto&& dupe : dupes) {
|
2019-07-16 21:02:13 +03:00
|
|
|
EXPECT_NE(stricmp(dupe, pEntry->mName), 0);
|
2019-06-11 20:15:20 +03:00
|
|
|
}
|
2018-09-11 01:01:10 +03:00
|
|
|
|
2019-07-16 21:02:13 +03:00
|
|
|
dupes.AppendElement(pEntry->mName);
|
2018-09-11 01:01:10 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-06 11:18:28 +03:00
|
|
|
TEST(TestDllBlocklist, BlockThreadWithLoadLibraryEntryPoint)
|
|
|
|
{
|
2019-06-11 20:15:20 +03:00
|
|
|
// Only supported on Nightly
|
|
|
|
#if defined(NIGHTLY_BUILD)
|
|
|
|
using ThreadProc = unsigned(__stdcall*)(void*);
|
|
|
|
|
|
|
|
NS_NAMED_LITERAL_STRING(kLeafNameW, "TestDllBlocklist_MatchByVersion.dll");
|
|
|
|
|
|
|
|
nsString fullPathW = GetFullPath(kLeafNameW);
|
|
|
|
EXPECT_FALSE(fullPathW.IsEmpty());
|
|
|
|
|
|
|
|
nsAutoHandle threadW(reinterpret_cast<HANDLE>(
|
|
|
|
_beginthreadex(nullptr, 0, reinterpret_cast<ThreadProc>(&::LoadLibraryW),
|
|
|
|
(void*)fullPathW.get(), 0, nullptr)));
|
|
|
|
|
|
|
|
EXPECT_TRUE(!!threadW);
|
|
|
|
EXPECT_EQ(::WaitForSingleObject(threadW, INFINITE), WAIT_OBJECT_0);
|
|
|
|
|
|
|
|
DWORD exitCode;
|
|
|
|
EXPECT_TRUE(::GetExitCodeThread(threadW, &exitCode) && !exitCode);
|
|
|
|
EXPECT_TRUE(!::GetModuleHandleW(kLeafNameW.get()));
|
|
|
|
|
|
|
|
const NS_LossyConvertUTF16toASCII fullPathA(fullPathW);
|
|
|
|
EXPECT_FALSE(fullPathA.IsEmpty());
|
|
|
|
|
|
|
|
nsAutoHandle threadA(reinterpret_cast<HANDLE>(
|
|
|
|
_beginthreadex(nullptr, 0, reinterpret_cast<ThreadProc>(&::LoadLibraryA),
|
|
|
|
(void*)fullPathA.get(), 0, nullptr)));
|
|
|
|
|
|
|
|
EXPECT_TRUE(!!threadA);
|
|
|
|
EXPECT_EQ(::WaitForSingleObject(threadA, INFINITE), WAIT_OBJECT_0);
|
|
|
|
EXPECT_TRUE(::GetExitCodeThread(threadA, &exitCode) && !exitCode);
|
|
|
|
EXPECT_TRUE(!::GetModuleHandleW(kLeafNameW.get()));
|
|
|
|
#endif // defined(NIGHTLY_BUILD)
|
2018-09-11 01:01:10 +03:00
|
|
|
}
|