Skip to content

Commit

Permalink
FileManagement: Gate new openat2() codepaths on recent enough kernel
Browse files Browse the repository at this point in the history
  • Loading branch information
asahilina committed Dec 19, 2024
1 parent 6862e72 commit 01d56e0
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 6 deletions.
18 changes: 12 additions & 6 deletions Source/Tools/LinuxEmulation/LinuxSyscalls/FileManagement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,8 @@ FileManager::FileManager(FEXCore::Context::Context* ctx)
ProcFSDev = Buffer.st_dev;
}

uint32_t KernelVersion = FEX::HLE::SyscallHandler::CalculateHostKernelVersion();
HasOpenat2 = KernelVersion >= FEX::HLE::SyscallHandler::KernelVersion(5, 8, 0);
UpdatePID(::getpid());
}

Expand Down Expand Up @@ -646,15 +648,17 @@ uint64_t FileManager::Open(const char* pathname, int flags, uint32_t mode) {

if (!ShouldSkipOpenInEmu(flags)) {
FDPathTmpData TmpFilename;
auto Path = GetEmulatedFDPath(AT_FDCWD, SelfPath, false, TmpFilename);
auto Path = GetEmulatedFDPath(AT_FDCWD, SelfPath, !HasOpenat2, TmpFilename);
if (Path.first != -1) {
FEX::HLE::open_how how = {
.flags = (uint64_t)flags,
.mode = (flags & (O_CREAT | O_TMPFILE)) ? mode & 07777 : 0, // openat2() is stricter about this
.resolve = RESOLVE_IN_ROOT,
};
fd = ::syscall(SYSCALL_DEF(openat2), Path.first, Path.second, &how, sizeof(how));
if (fd == -1 && errno == EXDEV) {
if (HasOpenat2) {
fd = ::syscall(SYSCALL_DEF(openat2), Path.first, Path.second, &how, sizeof(how));
}
if (fd == -1 && (!HasOpenat2 || errno == EXDEV)) {
// This means a magic symlink (/proc/foo) was involved. In this case we
// just punt and do the access without RESOLVE_IN_ROOT.
fd = ::syscall(SYSCALL_DEF(openat), Path.first, Path.second, flags, mode);
Expand Down Expand Up @@ -899,15 +903,17 @@ uint64_t FileManager::Openat([[maybe_unused]] int dirfs, const char* pathname, i

if (!ShouldSkipOpenInEmu(flags)) {
FDPathTmpData TmpFilename;
auto Path = GetEmulatedFDPath(dirfs, SelfPath, false, TmpFilename);
auto Path = GetEmulatedFDPath(dirfs, SelfPath, !HasOpenat2, TmpFilename);
if (Path.first != -1) {
FEX::HLE::open_how how = {
.flags = (uint64_t)flags,
.mode = (flags & (O_CREAT | O_TMPFILE)) ? mode & 07777 : 0, // openat2() is stricter about this,
.resolve = RESOLVE_IN_ROOT,
};
fd = ::syscall(SYSCALL_DEF(openat2), Path.first, Path.second, &how, sizeof(how));
if (fd == -1 && errno == EXDEV) {
if (HasOpenat2) {
fd = ::syscall(SYSCALL_DEF(openat2), Path.first, Path.second, &how, sizeof(how));
}
if (fd == -1 && (!HasOpenat2 || errno == EXDEV)) {
// This means a magic symlink (/proc/foo) was involved. In this case we
// just punt and do the access without RESOLVE_IN_ROOT.
fd = ::syscall(SYSCALL_DEF(openat), Path.first, Path.second, flags, mode);
Expand Down
1 change: 1 addition & 0 deletions Source/Tools/LinuxEmulation/LinuxSyscalls/FileManagement.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,5 +170,6 @@ class FileManager final {
int64_t RootFSFDInode = 0;
int64_t ProcFDInode = 0;
dev_t ProcFSDev;
bool HasOpenat2;
};
} // namespace FEX::HLE

0 comments on commit 01d56e0

Please sign in to comment.