1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 10:42:36 +01:00

ux/core: Add module verification step for some critical libraries

- Prevents running the emu with downloaded dll files
This commit is contained in:
kd-11 2022-12-06 00:19:42 +03:00 committed by Megamouse
parent 14a388b3fe
commit ca0ca2e5a8
5 changed files with 110 additions and 2 deletions

View File

@ -30,9 +30,10 @@
#include "Utilities/sema.h"
#include "Crypto/decrypt_binaries.h"
#ifdef _WIN32
#include <windows.h>
#include "module_verifier.hpp"
#include "util/dyn_lib.hpp"
// TODO(cjj19970505@live.cn)
// When compiling with WIN32_LEAN_AND_MEAN definition
// NTSTATUS is defined in CMake build but not in VS build
@ -410,6 +411,13 @@ void fmt_class_string<std::chrono::sys_time<typename std::chrono::system_clock::
out += ss.str();
}
void run_platform_sanity_checks()
{
#ifdef _WIN32
// Check if we loaded modules correctly
WIN32_module_verifier::run();
#endif
}
int main(int argc, char** argv)
{
@ -439,6 +447,9 @@ int main(int argc, char** argv)
report_fatal_error(error);
}
// Before we proceed, run some sanity checks
run_platform_sanity_checks();
const std::string lock_name = fs::get_cache_dir() + "RPCS3.buf";
static fs::file instance_lock;

82
rpcs3/module_verifier.hpp Normal file
View File

@ -0,0 +1,82 @@
#pragma once
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <Windows.h>
#include <util/types.hpp>
#include <Utilities/StrUtil.h>
#include <Utilities/StrFmt.h>
[[noreturn]] void report_fatal_error(std::string_view);
// Validates that system modules are properly installed
// Only relevant for WIN32
class WIN32_module_verifier
{
struct module_info_t
{
std::wstring_view name;
std::string_view package_name;
std::string_view dl_link;
};
const std::vector<module_info_t> special_module_infos = {
{ L"vulkan-1.dll", "Vulkan Runtime", "https://sdk.lunarg.com/sdk/download/latest/windows/vulkan-runtime.exe" },
{ L"msvcp140.dll", "C++ Redistributable for Visual Studio 2015", "https://www.microsoft.com/en-us/download/details.aspx?id=48145" },
{ L"vcruntime140.dll", "C++ Redistributable for Visual Studio 2015", "https://www.microsoft.com/en-us/download/details.aspx?id=48145" },
{ L"msvcp140_1.dll", "C++ Redistributable for Visual Studio 2015", "https://www.microsoft.com/en-us/download/details.aspx?id=48145" },
{ L"vcruntime140_1.dll", "C++ Redistributable for Visual Studio 2015", "https://www.microsoft.com/en-us/download/details.aspx?id=48145" }
};
// Unless we support ReactOS in future, this is a constant
const std::wstring_view system_root = L"C:\\WINDOWS\\";
// Inline impl. This class is only referenced once.
void run_module_verification()
{
for (const auto& module : special_module_infos)
{
const auto hModule = GetModuleHandle(module.name.data());
if (hModule == NULL)
{
continue;
}
WCHAR path[MAX_PATH];
if (const auto len = GetModuleFileName(hModule, path, MAX_PATH))
{
const std::wstring_view s = path;
if (s.find(system_root) != 0)
{
const auto error_message = fmt::format(
"The module '%s' was incorrectly installed.\n"
"This module is part of the '%s' package.\n"
"You can install this package from this URL:\n"
"<a href='%s'>%s</a>",
wchar_to_utf8(module.name),
module.package_name,
module.dl_link,
module.dl_link
);
report_fatal_error(error_message);
}
}
}
}
WIN32_module_verifier() = default;
public:
static void run()
{
WIN32_module_verifier verifier{};
verifier.run_module_verification();
}
};
#endif // _WIN32

View File

@ -884,6 +884,7 @@
</CustomBuild>
<ClInclude Include="Input\pad_thread.h" />
<ClInclude Include="Input\product_info.h" />
<ClInclude Include="module_verifier.hpp" />
<ClInclude Include="QTGeneratedFiles\ui_about_dialog.h" />
<ClInclude Include="QTGeneratedFiles\ui_camera_settings_dialog.h" />
<ClInclude Include="QTGeneratedFiles\ui_main_window.h" />

View File

@ -1037,6 +1037,9 @@
<ClInclude Include="Input\evdev_gun_handler.h">
<Filter>Io\evdev</Filter>
</ClInclude>
<ClInclude Include="module_verifier.hpp">
<Filter>rpcs3</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="debug\moc_predefs.h.cbt">

View File

@ -4,6 +4,17 @@
#include <QTextDocument>
#include <QIcon>
static QString process_dialog_text(std::string_view text)
{
auto html = Qt::convertFromPlainText(QString::fromUtf8(text.data(), text.size()));
// Let's preserve some html elements destroyed by convertFromPlainText
const QRegExp link_re{ R"(&lt;a\shref='([a-z0-9?=&#:\/\.\-]+)'&gt;([a-z0-9?=&#:\/\.\-]+)&lt;\/a&gt;)", Qt::CaseSensitive, QRegExp::RegExp2};
html = html.replace(link_re, "<a href=\\1>\\2</a>");
return html;
}
fatal_error_dialog::fatal_error_dialog(std::string_view text) : QMessageBox()
{
#ifndef __APPLE__
@ -20,7 +31,7 @@ fatal_error_dialog::fatal_error_dialog(std::string_view text) : QMessageBox()
%3<br>
</p>
)")
.arg(Qt::convertFromPlainText(QString::fromUtf8(text.data(), text.size())))
.arg(process_dialog_text(text))
.arg(tr("HOW TO REPORT ERRORS:"))
.arg(tr("Please, don't send incorrect reports. Thanks for understanding.")));
layout()->setSizeConstraint(QLayout::SetFixedSize);