mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-06 14:00:16 +02:00
FEXLoader: Drop the binfmt_misc I flag
Upstream has rejected this flag which would have let FEX close the gap in functionality between binfmt_misc interpreters and PT_INTERP interpreters for how `/proc/exe` is handled. Since we are unable to change their opinions, just remove the code from FEX since it's never going to happen. Removes a little bit of confusing behaviour in execveat and filemanagement handling. Leaving us with only the regular confusing behaviour of trying to track accesses to `/proc/exe` instead.
This commit is contained in:
6 files changed
+26
-83
No files matched your search
@@ -6,4 +6,3 @@ mask \xff\xff\xff\xff\xff\xfe\xfe\x00\x00\x00\x00\xff\xff\xff\xff\xff\xfe\xff\xf
|
||||
credentials yes
|
||||
fix_binary yes
|
||||
preserve yes
|
||||
expose_interpreter optional
|
||||
@@ -6,4 +6,3 @@ mask \xff\xff\xff\xff\xff\xfe\xfe\x00\x00\x00\x00\xff\xff\xff\xff\xff\xfe\xff\xf
|
||||
credentials yes
|
||||
fix_binary yes
|
||||
preserve yes
|
||||
expose_interpreter optional
|
||||
@@ -96,17 +96,6 @@ if (CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64")
|
||||
add_dependencies(uninstall uninstall_binfmt_misc_64)
|
||||
endif()
|
||||
else()
|
||||
set (SUPPORTED_BINFMT_MISC_FLAGS "POCF")
|
||||
execute_process(COMMAND uname -r OUTPUT_VARIABLE UNAME_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
string(REGEX MATCH "[0-9]+.[0-9]+" KERNEL_VERSION ${UNAME_VERSION})
|
||||
message(STATUS "Kernel version: ${KERNEL_VERSION}")
|
||||
|
||||
if (KERNEL_VERSION VERSION_GREATER_EQUAL 9999.0)
|
||||
# New binfmt_misc flag for exposing the interpreter was added in version '9999.0'
|
||||
# Only enable it if the host kernel is at least that.
|
||||
set (SUPPORTED_BINFMT_MISC_FLAGS "POCFI")
|
||||
endif()
|
||||
|
||||
# In the case of update-binfmts not being available (Arch for example) then we need to install manually
|
||||
add_custom_target(binfmt_misc_32
|
||||
COMMAND ${CMAKE_COMMAND} -E
|
||||
@@ -117,7 +106,7 @@ if (CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64")
|
||||
echo "Attempting to install FEX-x86 misc now."
|
||||
COMMAND ${CMAKE_COMMAND} -E
|
||||
echo
|
||||
':FEX-x86:M:0:\\x7fELF\\x01\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x03\\x00:\\xff\\xff\\xff\\xff\\xff\\xfe\\xfe\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xfe\\xff\\xff\\xff:${CMAKE_INSTALL_PREFIX}/bin/FEXInterpreter:${SUPPORTED_BINFMT_MISC_FLAGS}' > /proc/sys/fs/binfmt_misc/register
|
||||
':FEX-x86:M:0:\\x7fELF\\x01\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x03\\x00:\\xff\\xff\\xff\\xff\\xff\\xfe\\xfe\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xfe\\xff\\xff\\xff:${CMAKE_INSTALL_PREFIX}/bin/FEXInterpreter:POCF' > /proc/sys/fs/binfmt_misc/register
|
||||
COMMAND ${CMAKE_COMMAND} -E
|
||||
echo "binfmt_misc FEX-x86 installed"
|
||||
)
|
||||
@@ -130,7 +119,7 @@ if (CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64")
|
||||
echo "Attempting to install FEX-x86_64 misc now."
|
||||
COMMAND ${CMAKE_COMMAND} -E
|
||||
echo
|
||||
':FEX-x86_64:M:0:\\x7fELF\\x02\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x3e\\x00:\\xff\\xff\\xff\\xff\\xff\\xfe\\xfe\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xfe\\xff\\xff\\xff:${CMAKE_INSTALL_PREFIX}/bin/FEXInterpreter:${SUPPORTED_BINFMT_MISC_FLAGS}' > /proc/sys/fs/binfmt_misc/register
|
||||
':FEX-x86_64:M:0:\\x7fELF\\x02\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x3e\\x00:\\xff\\xff\\xff\\xff\\xff\\xfe\\xfe\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xfe\\xff\\xff\\xff:${CMAKE_INSTALL_PREFIX}/bin/FEXInterpreter:POCF' > /proc/sys/fs/binfmt_misc/register
|
||||
COMMAND ${CMAKE_COMMAND} -E
|
||||
echo "binfmt_misc FEX-x86_64 installed"
|
||||
)
|
||||
|
||||
@@ -322,32 +322,6 @@ FileManager::FileManager(FEXCore::Context::Context* ctx)
|
||||
}
|
||||
}
|
||||
|
||||
// Check to see if this kernel exposes `/proc/self/interpreter`.
|
||||
// In the case that it does then behaviour is different than without.
|
||||
//
|
||||
// When procfs/interpreter is supported (binfmt_misc flag enabled):
|
||||
// - procfs/exe -> symlink to the correct executable just like when executing natively.
|
||||
// - procfs/interpreter -> symlink to FEXInterpreter.
|
||||
//
|
||||
// FEX no longer needs to track accesses to procfs/exe which improves performance and also improves correctness.
|
||||
//
|
||||
// When procfs/interpreter is supported (binfmt_misc flag not enabled):
|
||||
// When procfs/interpreter is NOT supported:
|
||||
// - procfs/exe -> symlink to FEXInterpreter.
|
||||
// - procfs/interpreter -> symlink doesn't exist.
|
||||
//
|
||||
// In either of these two cases, FEX still needs to track procfs/exe so we can't completely get away from it.
|
||||
// This happens in a few edge cases
|
||||
// - binfmt_misc not installed
|
||||
// - binfmt_misc doesn't support enabling the new flag
|
||||
// - executable called through FEXInterpreter directly
|
||||
// - Can happen because of directly executing the process through FEXIntepreter or through FEXBash.
|
||||
char FilenameExe[PATH_MAX];
|
||||
char FilenameInterpreter[PATH_MAX];
|
||||
const auto ExeSymlinkPath = FHU::Symlinks::ResolveSymlink("/proc/self/exe", FilenameExe);
|
||||
const auto InterpreterSymlinkPath = FHU::Symlinks::ResolveSymlink("/proc/self/interpreter", FilenameInterpreter);
|
||||
SupportsProcFSInterpreter = !InterpreterSymlinkPath.empty() && ExeSymlinkPath != InterpreterSymlinkPath;
|
||||
|
||||
UpdatePID(::getpid());
|
||||
}
|
||||
|
||||
@@ -498,11 +472,6 @@ bool FileManager::IsSelfNoFollow(const char* Pathname, int flags) const {
|
||||
}
|
||||
|
||||
std::optional<std::string_view> FileManager::GetSelf(const char* Pathname) {
|
||||
if (SupportsProcFSInterpreter) {
|
||||
// FEX doesn't need to track procfs/exe if this is supported.
|
||||
return Pathname;
|
||||
}
|
||||
|
||||
if (!Pathname) {
|
||||
return std::nullopt;
|
||||
}
|
||||
@@ -666,17 +635,15 @@ uint64_t FileManager::FAccessat2(int dirfd, const char* pathname, int mode, int
|
||||
}
|
||||
|
||||
uint64_t FileManager::Readlink(const char* pathname, char* buf, size_t bufsiz) {
|
||||
if (!SupportsProcFSInterpreter) {
|
||||
// calculate the non-self link to exe
|
||||
// Some executables do getpid, stat("/proc/$pid/exe")
|
||||
char PidSelfPath[50];
|
||||
snprintf(PidSelfPath, 50, "/proc/%i/exe", CurrentPID);
|
||||
// calculate the non-self link to exe
|
||||
// Some executables do getpid, stat("/proc/$pid/exe")
|
||||
char PidSelfPath[50];
|
||||
snprintf(PidSelfPath, 50, "/proc/%i/exe", CurrentPID);
|
||||
|
||||
if (strcmp(pathname, "/proc/self/exe") == 0 || strcmp(pathname, "/proc/thread-self/exe") == 0 || strcmp(pathname, PidSelfPath) == 0) {
|
||||
const auto& App = Filename();
|
||||
strncpy(buf, App.c_str(), bufsiz);
|
||||
return std::min(bufsiz, App.size());
|
||||
}
|
||||
if (strcmp(pathname, "/proc/self/exe") == 0 || strcmp(pathname, "/proc/thread-self/exe") == 0 || strcmp(pathname, PidSelfPath) == 0) {
|
||||
const auto& App = Filename();
|
||||
strncpy(buf, App.c_str(), bufsiz);
|
||||
return std::min(bufsiz, App.size());
|
||||
}
|
||||
|
||||
FDPathTmpData TmpFilename;
|
||||
@@ -745,15 +712,13 @@ uint64_t FileManager::Readlinkat(int dirfd, const char* pathname, char* buf, siz
|
||||
}
|
||||
}
|
||||
|
||||
if (!SupportsProcFSInterpreter) {
|
||||
char PidSelfPath[50];
|
||||
snprintf(PidSelfPath, 50, "/proc/%i/exe", CurrentPID);
|
||||
char PidSelfPath[50];
|
||||
snprintf(PidSelfPath, 50, "/proc/%i/exe", CurrentPID);
|
||||
|
||||
if (Path == "/proc/self/exe" || Path == "/proc/thread-self/exe" || Path == PidSelfPath) {
|
||||
const auto& App = Filename();
|
||||
strncpy(buf, App.c_str(), bufsiz);
|
||||
return std::min(bufsiz, App.size());
|
||||
}
|
||||
if (Path == "/proc/self/exe" || Path == "/proc/thread-self/exe" || Path == PidSelfPath) {
|
||||
const auto& App = Filename();
|
||||
strncpy(buf, App.c_str(), bufsiz);
|
||||
return std::min(bufsiz, App.size());
|
||||
}
|
||||
|
||||
FDPathTmpData TmpFilename;
|
||||
|
||||
@@ -89,10 +89,6 @@ public:
|
||||
using FDPathTmpData = std::array<char[PATH_MAX], 2>;
|
||||
std::pair<int, const char*> GetEmulatedFDPath(int dirfd, const char* pathname, bool FollowSymlink, FDPathTmpData& TmpFilename);
|
||||
|
||||
bool SupportsProcFSInterpreterPath() const {
|
||||
return SupportsProcFSInterpreter;
|
||||
}
|
||||
|
||||
#if defined(ASSERTIONS_ENABLED) && ASSERTIONS_ENABLED
|
||||
void TrackFEXFD(int FD) noexcept {
|
||||
std::lock_guard lk(FEXTrackingFDMutex);
|
||||
@@ -166,6 +162,5 @@ private:
|
||||
FEX_CONFIG_OPT(Is64BitMode, IS64BIT_MODE);
|
||||
uint32_t CurrentPID {};
|
||||
int RootFSFD {AT_FDCWD};
|
||||
bool SupportsProcFSInterpreter {};
|
||||
};
|
||||
} // namespace FEX::HLE
|
||||
@@ -205,7 +205,6 @@ uint64_t ExecveHandler(FEXCore::Core::CpuStateFrame* Frame, const char* pathname
|
||||
|
||||
// AT_EMPTY_PATH is only used if the pathname is empty.
|
||||
const bool IsFDExec = (Args.flags & AT_EMPTY_PATH) && strlen(pathname) == 0;
|
||||
const bool SupportsProcFSInterpreter = SyscallHandler->FM.SupportsProcFSInterpreterPath();
|
||||
fextl::string FDExecEnv;
|
||||
fextl::string FDSeccompEnv;
|
||||
|
||||
@@ -233,19 +232,17 @@ uint64_t ExecveHandler(FEXCore::Core::CpuStateFrame* Frame, const char* pathname
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (!SupportsProcFSInterpreter) {
|
||||
int pid = getpid();
|
||||
int pid = getpid();
|
||||
|
||||
char PidSelfPath[50];
|
||||
snprintf(PidSelfPath, 50, "/proc/%i/exe", pid);
|
||||
char PidSelfPath[50];
|
||||
snprintf(PidSelfPath, 50, "/proc/%i/exe", pid);
|
||||
|
||||
if (strcmp(pathname, "/proc/self/exe") == 0 || strcmp(pathname, "/proc/thread-self/exe") == 0 || strcmp(pathname, PidSelfPath) == 0) {
|
||||
// If the application is trying to execve `/proc/self/exe` or its variants,
|
||||
// then we need to redirect this path to the true application path.
|
||||
// This is because this path is a symlink to the executing application, which is always `FEXInterpreter` or `FEXLoader`.
|
||||
// ex: JRE and shapez.io do this self-execution.
|
||||
Filename = SyscallHandler->Filename();
|
||||
}
|
||||
if (strcmp(pathname, "/proc/self/exe") == 0 || strcmp(pathname, "/proc/thread-self/exe") == 0 || strcmp(pathname, PidSelfPath) == 0) {
|
||||
// If the application is trying to execve `/proc/self/exe` or its variants,
|
||||
// then we need to redirect this path to the true application path.
|
||||
// This is because this path is a symlink to the executing application, which is always `FEXInterpreter` or `FEXLoader`.
|
||||
// ex: JRE and shapez.io do this self-execution.
|
||||
Filename = SyscallHandler->Filename();
|
||||
}
|
||||
|
||||
Type = ELFLoader::ELFContainer::GetELFType(Filename);
|
||||
@@ -392,8 +389,7 @@ uint64_t ExecveHandler(FEXCore::Core::CpuStateFrame* Frame, const char* pathname
|
||||
ExecveArgs.emplace_back(nullptr);
|
||||
}
|
||||
|
||||
const char* InterpreterPath = SupportsProcFSInterpreter ? "/proc/self/interpreter" : "/proc/self/exe";
|
||||
Result = ::syscall(SYS_execveat, Args.dirfd, InterpreterPath, const_cast<char* const*>(ExecveArgs.data()), EnvpPtr, Args.flags);
|
||||
Result = ::syscall(SYS_execveat, Args.dirfd, "/proc/self/exe", const_cast<char* const*>(ExecveArgs.data()), EnvpPtr, Args.flags);
|
||||
CloseSeccompFD();
|
||||
CloseFDExecFD();
|
||||
|
||||
|
||||
Reference in new issue
Block a user