-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
app-emulation/FEX: add lina's Chromium/CEF patches
Fixes a whole host of issues with Steam and probably Electron Signed-off-by: James Calligeros <[email protected]>
- Loading branch information
Showing
6 changed files
with
713 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
From 4a67893f1d36fc2611a63eaac30eea3b9e69213d Mon Sep 17 00:00:00 2001 | ||
From: Asahi Lina <[email protected]> | ||
Date: Wed, 13 Nov 2024 03:47:03 +0900 | ||
Subject: [PATCH] FEXLoader: Align stack base | ||
|
||
This ensures that __libc_stack_end is aligned, the same way it is on | ||
native. | ||
--- | ||
Source/Tools/FEXLoader/ELFCodeLoader.h | 3 +++ | ||
1 file changed, 3 insertions(+) | ||
|
||
diff --git a/Source/Tools/FEXLoader/ELFCodeLoader.h b/Source/Tools/FEXLoader/ELFCodeLoader.h | ||
index 8e24f75b83..733be0317f 100644 | ||
--- a/Source/Tools/FEXLoader/ELFCodeLoader.h | ||
+++ b/Source/Tools/FEXLoader/ELFCodeLoader.h | ||
@@ -725,6 +725,9 @@ class ELFCodeLoader final : public FEX::CodeLoader { | ||
uint64_t ExecFNLocation = TotalArgumentMemSize; | ||
TotalArgumentMemSize += Args[0].size() + 1; | ||
|
||
+ // Align the argument block to 16 bytes to keep the stack aligned | ||
+ TotalArgumentMemSize = FEXCore::AlignUp(TotalArgumentMemSize, 16); | ||
+ | ||
// Offset the stack by how much memory we need | ||
StackPointer -= TotalArgumentMemSize; | ||
|
72 changes: 72 additions & 0 deletions
72
app-emulation/FEX/files/FEX-2410-clone-fork-semantics.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
From bfed21870fff0be99327f21c0a4cb1c68861d999 Mon Sep 17 00:00:00 2001 | ||
From: Asahi Lina <[email protected]> | ||
Date: Tue, 12 Nov 2024 22:16:58 +0900 | ||
Subject: [PATCH] Support CLONE_FS and CLONE_FILES with fork() semantics | ||
|
||
Needed by Discord, part of the Chromium sandbox code. The warning still | ||
triggers because Chromium asks for CLONE_VM on x86_64, but that can be | ||
safely ignored (CLONE_FS is the one that matters). | ||
--- | ||
.../LinuxEmulation/LinuxSyscalls/Syscalls.cpp | 2 +- | ||
.../LinuxSyscalls/Syscalls/Thread.cpp | 14 ++++++++++++-- | ||
2 files changed, 13 insertions(+), 3 deletions(-) | ||
|
||
diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.cpp | ||
index 9541471059..bcb92096a7 100644 | ||
--- a/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.cpp | ||
+++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.cpp | ||
@@ -583,7 +583,7 @@ uint64_t CloneHandler(FEXCore::Core::CpuStateFrame* Frame, FEX::HLE::clone3_args | ||
return false; | ||
} | ||
} else { | ||
- if (AnyFlagsSet(args->args.flags, CLONE_SYSVSEM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_VM)) { | ||
+ if (AnyFlagsSet(args->args.flags, CLONE_SYSVSEM | CLONE_SIGHAND | CLONE_VM)) { | ||
// CLONE_VM is particularly nasty here | ||
// Memory regions at the point of clone(More similar to a fork) are shared | ||
LogMan::Msg::IFmt("clone: Unsupported flags w/o CLONE_THREAD (Shared Resources), {:X}", args->args.flags); | ||
diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls/Thread.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls/Thread.cpp | ||
index 0a1178019b..7f2313b03e 100644 | ||
--- a/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls/Thread.cpp | ||
+++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls/Thread.cpp | ||
@@ -26,6 +26,7 @@ tags: LinuxSyscalls|syscalls-shared | ||
#include <limits.h> | ||
#include <linux/futex.h> | ||
#include <linux/seccomp.h> | ||
+#include <linux/sched.h> | ||
#include <stdint.h> | ||
#include <sched.h> | ||
#include <sys/personality.h> | ||
@@ -228,6 +229,15 @@ uint64_t HandleNewClone(FEX::HLE::ThreadStateObject* Thread, FEXCore::Context::C | ||
return Thread->Thread->StatusCode; | ||
} | ||
|
||
+static int Clone3Fork(uint32_t flags) { | ||
+ struct clone_args cl_args = { | ||
+ .flags = (flags & (CLONE_FS | CLONE_FILES)), | ||
+ .exit_signal = SIGCHLD, | ||
+ }; | ||
+ | ||
+ return syscall(SYS_clone3, cl_args, sizeof(cl_args)); | ||
+} | ||
+ | ||
uint64_t ForkGuest(FEXCore::Core::InternalThreadState* Thread, FEXCore::Core::CpuStateFrame* Frame, uint32_t flags, void* stack, | ||
size_t StackSize, pid_t* parent_tid, pid_t* child_tid, void* tls) { | ||
// Just before we fork, we lock all syscall mutexes so that both processes will end up with a locked mutex | ||
@@ -248,7 +258,7 @@ uint64_t ForkGuest(FEXCore::Core::InternalThreadState* Thread, FEXCore::Core::Cp | ||
|
||
// XXX: We don't currently support a real `vfork` as it causes problems. | ||
// Currently behaves like a fork (with wait after the fact), which isn't correct. Need to find where the problem is | ||
- Result = fork(); | ||
+ Result = Clone3Fork(flags); | ||
|
||
if (Result == 0) { | ||
// Close the read end of the pipe. | ||
@@ -259,7 +269,7 @@ uint64_t ForkGuest(FEXCore::Core::InternalThreadState* Thread, FEXCore::Core::Cp | ||
close(VForkFDs[1]); | ||
} | ||
} else { | ||
- Result = fork(); | ||
+ Result = Clone3Fork(flags); | ||
} | ||
const bool IsChild = Result == 0; | ||
|
107 changes: 107 additions & 0 deletions
107
app-emulation/FEX/files/FEX-2410-hide-rootfs-fd-2.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
From 73ffaa1e18e80c6ee0bbd38b3f3e6baebff4b60a Mon Sep 17 00:00:00 2001 | ||
From: Asahi Lina <[email protected]> | ||
Date: Wed, 13 Nov 2024 01:22:42 +0900 | ||
Subject: [PATCH] FileManagement: Hide the FEX RootFS fd from /proc/self/fd | ||
take 2 | ||
|
||
Apparently Chromium/CEF can chroot or otherwise sandbox the filesystem | ||
away before forking and checking for directory FDs, making /proc | ||
inaccessible, which means we can't stat it for our inode check, breaking | ||
the hiding. | ||
|
||
So, double down on things and do what Chromium does: open an fd to /proc | ||
ahead of time, so that continues to work. Then we use it to update the | ||
inode of our RootFS fd instead, and finally, also do the /proc fd itself | ||
to hide that one too. | ||
|
||
We also don't need to check the st_dev of /proc more than once, since | ||
that's not expected to change anyway. | ||
|
||
Fixes cefsimple. | ||
--- | ||
.../LinuxSyscalls/FileManagement.cpp | 33 +++++++++++++++---- | ||
.../LinuxSyscalls/FileManagement.h | 2 ++ | ||
2 files changed, 28 insertions(+), 7 deletions(-) | ||
|
||
diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/FileManagement.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/FileManagement.cpp | ||
index e71d3e049c..d4ccaa5a4a 100644 | ||
--- a/Source/Tools/LinuxEmulation/LinuxSyscalls/FileManagement.cpp | ||
+++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/FileManagement.cpp | ||
@@ -322,6 +322,16 @@ FileManager::FileManager(FEXCore::Context::Context* ctx) | ||
} | ||
} | ||
|
||
+ // Keep an fd open for /proc, to bypass chroot-style sandboxes | ||
+ ProcFD = open("/proc", O_RDONLY | O_CLOEXEC); | ||
+ | ||
+ // Track the st_dev of /proc, to check for inode equality | ||
+ struct stat Buffer; | ||
+ auto Result = fstat(ProcFD, &Buffer); | ||
+ if (Result >= 0) { | ||
+ ProcFSDev = Buffer.st_dev; | ||
+ } | ||
+ | ||
UpdatePID(::getpid()); | ||
} | ||
|
||
@@ -998,30 +1008,39 @@ void FileManager::UpdatePID(uint32_t PID) { | ||
CurrentPID = PID; | ||
|
||
// Track the inode of /proc/self/fd/<RootFSFD>, to be able to hide it | ||
- auto FDpath = fextl::fmt::format("/proc/self/fd/{}", RootFSFD); | ||
+ auto FDpath = fextl::fmt::format("self/fd/{}", RootFSFD); | ||
struct stat Buffer {}; | ||
- int Result = fstatat(AT_FDCWD, FDpath.c_str(), &Buffer, AT_SYMLINK_NOFOLLOW); | ||
+ int Result = fstatat(ProcFD, FDpath.c_str(), &Buffer, AT_SYMLINK_NOFOLLOW); | ||
if (Result >= 0) { | ||
RootFSFDInode = Buffer.st_ino; | ||
+ } else { | ||
+ // Probably in a strict sandbox | ||
+ RootFSFDInode = 0; | ||
+ ProcFDInode = 0; | ||
+ return; | ||
} | ||
|
||
- // Track the st_dev of /proc, to check for inode equality | ||
- Result = stat("/proc/self", &Buffer); | ||
+ // And track the ProcFSFD itself | ||
+ FDpath = fextl::fmt::format("self/fd/{}", ProcFD); | ||
+ Result = fstatat(ProcFD, FDpath.c_str(), &Buffer, AT_SYMLINK_NOFOLLOW); | ||
if (Result >= 0) { | ||
- ProcFSDev = Buffer.st_dev; | ||
+ ProcFDInode = Buffer.st_ino; | ||
+ } else { | ||
+ // ?? | ||
+ ProcFDInode = 0; | ||
+ return; | ||
} | ||
} | ||
|
||
bool FileManager::IsRootFSFD(int dirfd, uint64_t inode) { | ||
|
||
// Check if we have to hide this entry | ||
- if (inode == RootFSFDInode) { | ||
+ if (inode == RootFSFDInode || inode == ProcFDInode) { | ||
struct stat Buffer; | ||
if (fstat(dirfd, &Buffer) >= 0) { | ||
if (Buffer.st_dev == ProcFSDev) { | ||
LogMan::Msg::DFmt("Hiding directory entry for RootFSFD"); | ||
return true; | ||
- } else { | ||
} | ||
} | ||
} | ||
diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/FileManagement.h b/Source/Tools/LinuxEmulation/LinuxSyscalls/FileManagement.h | ||
index f84ef30be6..aecf9a874c 100644 | ||
--- a/Source/Tools/LinuxEmulation/LinuxSyscalls/FileManagement.h | ||
+++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/FileManagement.h | ||
@@ -161,7 +161,9 @@ class FileManager final { | ||
FEX_CONFIG_OPT(Is64BitMode, IS64BIT_MODE); | ||
uint32_t CurrentPID {}; | ||
int RootFSFD {AT_FDCWD}; | ||
+ int ProcFD {0}; | ||
int64_t RootFSFDInode = 0; | ||
+ int64_t ProcFDInode = 0; | ||
dev_t ProcFSDev; | ||
}; | ||
} // namespace FEX::HLE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
From 3d701f5fcf8a729246ad51f5e9e57a0d48732cd6 Mon Sep 17 00:00:00 2001 | ||
From: Asahi Lina <[email protected]> | ||
Date: Sun, 27 Oct 2024 07:00:54 +0900 | ||
Subject: [PATCH] FileManagement: Hide the FEX RootFS fd from /proc/self/fd | ||
|
||
Chromium/CEF has code that iterates through all open FDs and bails if | ||
any are directories (apparently a sandboxing sanity check). To avoid | ||
this check, we need to hide the RootFS FD. This requires hooking all the | ||
getdents variants to skip that entry. | ||
|
||
To keep the runtime cost low, we keep track of the inode of | ||
/proc/self/fd/<rootfs fd> (note: not the RootFS inode, the inode of the | ||
magic symlink in /proc), and first do a quick check on that. If it | ||
matches, then we stat the dirfd we are reading and check against the | ||
procfs device, to complete the inode equality check. | ||
|
||
As an extra benefit, this also fixes code that tries to iterate and | ||
close all/extra FDs and ends up closing the RootFS fd. | ||
--- | ||
.../LinuxSyscalls/FileManagement.cpp | 34 +++++++++++++++++++ | ||
.../LinuxSyscalls/FileManagement.h | 7 ++-- | ||
.../LinuxEmulation/LinuxSyscalls/Syscalls.cpp | 5 +++ | ||
.../LinuxSyscalls/Syscalls/Passthrough.cpp | 2 -- | ||
.../LinuxEmulation/LinuxSyscalls/x32/FD.cpp | 5 +++ | ||
.../LinuxEmulation/LinuxSyscalls/x64/FD.cpp | 17 ++++++++++ | ||
6 files changed, 65 insertions(+), 5 deletions(-) | ||
|
||
diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/FileManagement.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/FileManagement.cpp | ||
index e57c281586..e71d3e049c 100644 | ||
--- a/Source/Tools/LinuxEmulation/LinuxSyscalls/FileManagement.cpp | ||
+++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/FileManagement.cpp | ||
@@ -994,4 +994,38 @@ uint64_t FileManager::LRemovexattr(const char* path, const char* name) { | ||
return ::lremovexattr(SelfPath, name); | ||
} | ||
|
||
+void FileManager::UpdatePID(uint32_t PID) { | ||
+ CurrentPID = PID; | ||
+ | ||
+ // Track the inode of /proc/self/fd/<RootFSFD>, to be able to hide it | ||
+ auto FDpath = fextl::fmt::format("/proc/self/fd/{}", RootFSFD); | ||
+ struct stat Buffer {}; | ||
+ int Result = fstatat(AT_FDCWD, FDpath.c_str(), &Buffer, AT_SYMLINK_NOFOLLOW); | ||
+ if (Result >= 0) { | ||
+ RootFSFDInode = Buffer.st_ino; | ||
+ } | ||
+ | ||
+ // Track the st_dev of /proc, to check for inode equality | ||
+ Result = stat("/proc/self", &Buffer); | ||
+ if (Result >= 0) { | ||
+ ProcFSDev = Buffer.st_dev; | ||
+ } | ||
+} | ||
+ | ||
+bool FileManager::IsRootFSFD(int dirfd, uint64_t inode) { | ||
+ | ||
+ // Check if we have to hide this entry | ||
+ if (inode == RootFSFDInode) { | ||
+ struct stat Buffer; | ||
+ if (fstat(dirfd, &Buffer) >= 0) { | ||
+ if (Buffer.st_dev == ProcFSDev) { | ||
+ LogMan::Msg::DFmt("Hiding directory entry for RootFSFD"); | ||
+ return true; | ||
+ } else { | ||
+ } | ||
+ } | ||
+ } | ||
+ return false; | ||
+} | ||
+ | ||
} // namespace FEX::HLE | ||
diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/FileManagement.h b/Source/Tools/LinuxEmulation/LinuxSyscalls/FileManagement.h | ||
index c230aedb48..f84ef30be6 100644 | ||
--- a/Source/Tools/LinuxEmulation/LinuxSyscalls/FileManagement.h | ||
+++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/FileManagement.h | ||
@@ -81,9 +81,8 @@ class FileManager final { | ||
std::optional<std::string_view> GetSelf(const char* Pathname); | ||
bool IsSelfNoFollow(const char* Pathname, int flags) const; | ||
|
||
- void UpdatePID(uint32_t PID) { | ||
- CurrentPID = PID; | ||
- } | ||
+ void UpdatePID(uint32_t PID); | ||
+ bool IsRootFSFD(int dirfd, uint64_t inode); | ||
|
||
fextl::string GetEmulatedPath(const char* pathname, bool FollowSymlink = false); | ||
using FDPathTmpData = std::array<char[PATH_MAX], 2>; | ||
@@ -162,5 +161,7 @@ class FileManager final { | ||
FEX_CONFIG_OPT(Is64BitMode, IS64BIT_MODE); | ||
uint32_t CurrentPID {}; | ||
int RootFSFD {AT_FDCWD}; | ||
+ int64_t RootFSFDInode = 0; | ||
+ dev_t ProcFSDev; | ||
}; | ||
} // namespace FEX::HLE | ||
diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.cpp | ||
index 01d6554256..9541471059 100644 | ||
--- a/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.cpp | ||
+++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls.cpp | ||
@@ -120,6 +120,11 @@ uint64_t GetDentsEmulation(int fd, T* dirp, uint32_t count) { | ||
Outgoing->d_name[Outgoing->d_reclen - offsetof(T, d_name) - 1] = Tmp->d_type; | ||
|
||
TmpOffset += Tmp->d_reclen; | ||
+ | ||
+ if (FEX::HLE::_SyscallHandler->FM.IsRootFSFD(fd, Outgoing->d_ino)) { | ||
+ continue; | ||
+ } | ||
+ | ||
// Outgoing is 5 bytes smaller | ||
Offset += NewRecLen; | ||
|
||
diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls/Passthrough.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls/Passthrough.cpp | ||
index d8e02c87ad..b75d09dfcd 100644 | ||
--- a/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls/Passthrough.cpp | ||
+++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/Syscalls/Passthrough.cpp | ||
@@ -694,8 +694,6 @@ namespace x64 { | ||
SyscallPassthrough6<SYSCALL_DEF(futex)>); | ||
REGISTER_SYSCALL_IMPL_X64_PASS_FLAGS(io_getevents, SyscallFlags::OPTIMIZETHROUGH | SyscallFlags::NOSYNCSTATEONENTRY, | ||
SyscallPassthrough5<SYSCALL_DEF(io_getevents)>); | ||
- REGISTER_SYSCALL_IMPL_X64_PASS_FLAGS(getdents64, SyscallFlags::OPTIMIZETHROUGH | SyscallFlags::NOSYNCSTATEONENTRY, | ||
- SyscallPassthrough3<SYSCALL_DEF(getdents64)>); | ||
REGISTER_SYSCALL_IMPL_X64_PASS_FLAGS(semtimedop, SyscallFlags::OPTIMIZETHROUGH | SyscallFlags::NOSYNCSTATEONENTRY, | ||
SyscallPassthrough4<SYSCALL_DEF(semtimedop)>); | ||
REGISTER_SYSCALL_IMPL_X64_PASS_FLAGS(timer_create, SyscallFlags::OPTIMIZETHROUGH | SyscallFlags::NOSYNCSTATEONENTRY, | ||
diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/x32/FD.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/x32/FD.cpp | ||
index 9a2dfabaf1..01712da60a 100644 | ||
--- a/Source/Tools/LinuxEmulation/LinuxSyscalls/x32/FD.cpp | ||
+++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/x32/FD.cpp | ||
@@ -600,6 +600,11 @@ void RegisterFD(FEX::HLE::SyscallHandler* Handler) { | ||
for (size_t i = 0, num = 0; i < Result; ++num) { | ||
linux_dirent_64* Incoming = (linux_dirent_64*)(reinterpret_cast<uint64_t>(dirp) + i); | ||
Incoming->d_off = num; | ||
+ if (FEX::HLE::_SyscallHandler->FM.IsRootFSFD(fd, Incoming->d_ino)) { | ||
+ Result -= Incoming->d_reclen; | ||
+ memmove(Incoming, (linux_dirent_64*)(reinterpret_cast<uint64_t>(Incoming) + Incoming->d_reclen), Result - i); | ||
+ continue; | ||
+ } | ||
i += Incoming->d_reclen; | ||
} | ||
} | ||
diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/FD.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/FD.cpp | ||
index e973bce1f3..ea2d78265e 100644 | ||
--- a/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/FD.cpp | ||
+++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/x64/FD.cpp | ||
@@ -112,6 +112,23 @@ void RegisterFD(FEX::HLE::SyscallHandler* Handler) { | ||
return GetDentsEmulation<false>(fd, reinterpret_cast<FEX::HLE::x64::linux_dirent*>(dirp), count); | ||
}); | ||
|
||
+ REGISTER_SYSCALL_IMPL_X64(getdents64, [](FEXCore::Core::CpuStateFrame* Frame, int fd, void* dirp, uint32_t count) -> uint64_t { | ||
+ uint64_t Result = ::syscall(SYSCALL_DEF(getdents64), static_cast<uint64_t>(fd), dirp, static_cast<uint64_t>(count)); | ||
+ if (Result != -1) { | ||
+ // Check for and hide the RootFS FD | ||
+ for (size_t i = 0; i < Result;) { | ||
+ linux_dirent_64* Incoming = (linux_dirent_64*)(reinterpret_cast<uint64_t>(dirp) + i); | ||
+ if (FEX::HLE::_SyscallHandler->FM.IsRootFSFD(fd, Incoming->d_ino)) { | ||
+ Result -= Incoming->d_reclen; | ||
+ memmove(Incoming, (linux_dirent_64*)(reinterpret_cast<uint64_t>(Incoming) + Incoming->d_reclen), Result - i); | ||
+ continue; | ||
+ } | ||
+ i += Incoming->d_reclen; | ||
+ } | ||
+ } | ||
+ SYSCALL_ERRNO(); | ||
+ }); | ||
+ | ||
REGISTER_SYSCALL_IMPL_X64(dup2, [](FEXCore::Core::CpuStateFrame* Frame, int oldfd, int newfd) -> uint64_t { | ||
uint64_t Result = ::dup2(oldfd, newfd); | ||
SYSCALL_ERRNO(); |
Oops, something went wrong.