Skip to content

Commit

Permalink
VirtualMachine: add workaround cvars for not disabling platform quali…
Browse files Browse the repository at this point in the history
…fication on arm64 or FreeBSD, and more

- Add workaround cvars for not disabling platform qualification on arm64 or FreeBSD.
- Run nacl_loader on FreeBSD Linuxulator the same way it runs on Linux (using the bootstrap helper).
- Add generic cvars to disable platforme qualification and bootstrap helper.
  • Loading branch information
illwieckz committed Oct 1, 2024
1 parent 4108131 commit 910dfaf
Showing 1 changed file with 115 additions and 29 deletions.
144 changes: 115 additions & 29 deletions src/engine/framework/VirtualMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "qcommon/qcommon.h"
#include "qcommon/sys.h"
#include "VirtualMachine.h"
#include "CvarSystem.h"

#ifdef _WIN32
#include <windows.h>
Expand All @@ -44,6 +45,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <sys/wait.h>
#ifdef __linux__
#include <sys/prctl.h>
#if defined(DAEMON_ARCH_armhf)
#include <sys/utsname.h>
#endif
#endif
#endif

Expand All @@ -55,6 +59,26 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE 0x2000
#endif

static Cvar::Cvar<bool> workaround_naclArchitecture_arm64_disableQualification(
"workaround.naclArchitecture.arm64.disableQualification",
"Disable platform qualification when running armhf NaCl loader on arm64 Linux",
Cvar::NONE, true);

static Cvar::Cvar<bool> workaround_naclSystem_freebsd_disableQualification(
"workaround.naclSystem.freebsd.disableQualification",
"Disable platform qualification when running Linux NaCl loader on FreeBSD through Linuxulator",
Cvar::NONE, true);

static Cvar::Cvar<bool> vm_nacl_qualification(
"vm.nacl.qualification",
"Enable NaCl loader platform qualification",
Cvar::NONE, true);

static Cvar::Cvar<bool> vm_nacl_bootstrap(
"vm.nacl.bootstrap",
"Use NaCl bootstrap helper",
Cvar::NONE, true);

namespace VM {

// https://github.com/Unvanquished/Unvanquished/issues/944#issuecomment-744454772
Expand Down Expand Up @@ -199,6 +223,11 @@ static std::pair<Sys::OSHandle, IPC::Socket> InternalLoadModule(std::pair<IPC::S
}

static std::pair<Sys::OSHandle, IPC::Socket> CreateNaClVM(std::pair<IPC::Socket, IPC::Socket> pair, Str::StringRef name, bool debug, bool extract, int debugLoader) {
Cvar::Latch(workaround_naclArchitecture_arm64_disableQualification);
Cvar::Latch(workaround_naclSystem_freebsd_disableQualification);
Cvar::Latch(vm_nacl_qualification);
Cvar::Latch(vm_nacl_bootstrap);

CheckMinAddressSysctlTooLarge();
const std::string& libPath = FS::GetLibPath();
#ifdef NACL_RUNTIME_PATH
Expand Down Expand Up @@ -246,54 +275,111 @@ static std::pair<Sys::OSHandle, IPC::Socket> CreateNaClVM(std::pair<IPC::Socket,
Log::Warn("NaCl loader not found: %s", nacl_loader);
if (!FS::RawPath::FileExists(irt))
Log::Warn("NaCl integrated runtime not found: %s", irt);
#ifdef __linux__
#if defined(DAEMON_ARCH_arm64)

#if defined(__linux__) || defined(__FreeBSD__)
bool enableBootstrap = vm_nacl_bootstrap.Get();

if (enableBootstrap)
{
#if defined(DAEMON_ARCH_arm64)
bootstrap = FS::Path::Build(naclPath, "nacl_helper_bootstrap-armhf");
#else
#else
bootstrap = FS::Path::Build(naclPath, "nacl_helper_bootstrap");
#endif
if (!FS::RawPath::FileExists(bootstrap))
Log::Warn("NaCl bootstrap helper not found: %s", bootstrap);
args.push_back(bootstrap.c_str());
#endif

if (!FS::RawPath::FileExists(bootstrap))
{
Log::Warn("NaCl bootstrap helper not found: %s", bootstrap);
enableBootstrap = false;
}
}

if (enableBootstrap)
{
args.push_back(bootstrap.c_str());
args.push_back(nacl_loader.c_str());
args.push_back("--r_debug=0xXXXXXXXXXXXXXXXX");
args.push_back("--reserved_at_zero=0xXXXXXXXXXXXXXXXX");
}
else
{
Log::Warn("Not using NaCl bootstrap helper.");
args.push_back(nacl_loader.c_str());
}
#else
Q_UNUSED(bootstrap);
args.push_back(nacl_loader.c_str());
args.push_back("--r_debug=0xXXXXXXXXXXXXXXXX");
args.push_back("--reserved_at_zero=0xXXXXXXXXXXXXXXXX");
#endif

#if defined(DAEMON_ARCH_arm64) || defined(DAEMON_ARCH_armhf)
/* This is required to run on Raspberry Pi 4,
otherwise nexe loading fails with this message:
bool enableQualification = vm_nacl_qualification.Get();

if (enableQualification)
{
#if defined(DAEMON_ARCH_arm64) || defined(DAEMON_ARCH_armhf)
if (workaround_naclArchitecture_arm64_disableQualification.Get())
{
#if defined(DAEMON_ARCH_arm64)
bool onArm64 = true;
#elif defined(DAEMON_ARCH_armhf)
bool onArm64 = false;

struct utsname buf;
if (!uname(&buf))
{
onArm64 = !strcmp(buf.machine, "aarch64");
}
#endif

Error while loading "sgame-armhf.nexe": CPU model is not supported
/* This is required to run armhf NaCl loader on arm64 kernel
otherwise nexe loading fails with this message:
From nacl_loader --help we can read:
> Error while loading "sgame-armhf.nexe": CPU model is not supported
-Q disable platform qualification (dangerous!)
From nacl_loader --help we can read:
When this option is enabled, nacl_loader will print:
> -Q disable platform qualification (dangerous!)
PLATFORM QUALIFICATION DISABLED BY -Q - Native Client's sandbox will be unreliable!
When this option is enabled, nacl_loader will print:
But the nexe will load and run. */
> PLATFORM QUALIFICATION DISABLED BY -Q - Native Client's sandbox will be unreliable!
args.push_back("-Q");
#endif
#else
Q_UNUSED(bootstrap);
args.push_back(nacl_loader.c_str());
But the nexe will load and run. */

if (onArm64)
{
Log::Warn("Disabling NaCL platform qualification on arm64 kernel architecture.");
enableQualification = false;
}
}
#endif

#if defined(__FreeBSD__)
#if defined(__FreeBSD__)
/* While it is possible to build a native FreeBSD engine, the only available NaCl loader
is the Linux one, which can run on Linuxulator (the FreeBSD Linux compatibility layer).
The Linux NaCl loader binary fails to qualify the platform and aborts with this message:
Bus error (core dumped)
> Bus error (core dumped)
The Linux NaCl loader runs properly on Linuxulator when we disable the qualification.
It also works without nacl_helper_bootstrap. */
The Linux NaCl loader runs properly on Linuxulator when we disable the qualification. */

args.push_back("-Q");
#endif
if (workaround_naclSystem_freebsd_disableQualification.Get())
{
Log::Warn("Disabling NaCL platform qualification on FreeBSD system.");
enableQualification = false;
}
#endif
}
else
{
Log::Warn("Not using platform qualification.");
}

if (!enableQualification)
{
args.push_back("-Q");
}

if (debug) {
args.push_back("-g");
}
Expand Down

0 comments on commit 910dfaf

Please sign in to comment.