mirror of
https://github.com/FEX-Emu/FEX.git
synced 2025-02-02 04:25:08 +00:00
Merge pull request #4019 from Sonicadvance1/more_efault_handlers
More EFAULT handlers
This commit is contained in:
commit
62e1767ee0
@ -49,6 +49,8 @@ constexpr uint32_t TLS_MaxEntry = TLS_NextEntry + 3;
|
||||
|
||||
uint64_t SetThreadArea(FEXCore::Core::CpuStateFrame* Frame, void* tls) {
|
||||
struct x32::user_desc* u_info = reinterpret_cast<struct x32::user_desc*>(tls);
|
||||
FaultSafeUserMemAccess::VerifyIsReadable(u_info, sizeof(*u_info));
|
||||
|
||||
if (u_info->entry_number == -1) {
|
||||
for (uint32_t i = TLS_NextEntry; i < TLS_MaxEntry; ++i) {
|
||||
auto GDT = &Frame->State.gdt[i];
|
||||
@ -106,6 +108,17 @@ void RegisterThread(FEX::HLE::SyscallHandler* Handler) {
|
||||
|
||||
REGISTER_SYSCALL_IMPL_X32(
|
||||
clone, ([](FEXCore::Core::CpuStateFrame* Frame, uint32_t flags, void* stack, pid_t* parent_tid, void* tls, pid_t* child_tid) -> uint64_t {
|
||||
// This is slightly different EFAULT behaviour, if child_tid or parent_tid is invalid then the kernel just doesn't write to the
|
||||
// pointer. Still need to be EFAULT safe although.
|
||||
if ((flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)) && child_tid) {
|
||||
FaultSafeUserMemAccess::VerifyIsWritable(child_tid, sizeof(*child_tid));
|
||||
}
|
||||
|
||||
if ((flags & CLONE_PARENT_SETTID) && parent_tid) {
|
||||
FaultSafeUserMemAccess::VerifyIsWritable(parent_tid, sizeof(*parent_tid));
|
||||
}
|
||||
|
||||
|
||||
FEX::HLE::clone3_args args {.Type = TypeOfClone::TYPE_CLONE2,
|
||||
.args = {
|
||||
.flags = flags & ~CSIGNAL, // This no longer contains CSIGNAL
|
||||
@ -125,6 +138,7 @@ void RegisterThread(FEX::HLE::SyscallHandler* Handler) {
|
||||
|
||||
REGISTER_SYSCALL_IMPL_X32(waitpid, [](FEXCore::Core::CpuStateFrame* Frame, pid_t pid, int32_t* status, int32_t options) -> uint64_t {
|
||||
uint64_t Result = ::waitpid(pid, status, options);
|
||||
FaultSafeUserMemAccess::VerifyIsWritableOrNull(status, sizeof(*status));
|
||||
SYSCALL_ERRNO();
|
||||
});
|
||||
|
||||
@ -143,6 +157,8 @@ void RegisterThread(FEX::HLE::SyscallHandler* Handler) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
FaultSafeUserMemAccess::VerifyIsWritable(u_info, sizeof(*u_info));
|
||||
|
||||
const auto& GDT = &Frame->State.gdt[Entry];
|
||||
|
||||
memset(u_info, 0, sizeof(*u_info));
|
||||
@ -178,6 +194,9 @@ void RegisterThread(FEX::HLE::SyscallHandler* Handler) {
|
||||
|
||||
REGISTER_SYSCALL_IMPL_X32(
|
||||
get_robust_list, [](FEXCore::Core::CpuStateFrame* Frame, int pid, struct robust_list_head** head, uint32_t* len_ptr) -> uint64_t {
|
||||
FaultSafeUserMemAccess::VerifyIsWritable(head, sizeof(uint32_t));
|
||||
FaultSafeUserMemAccess::VerifyIsWritable(len_ptr, sizeof(*len_ptr));
|
||||
|
||||
auto ThreadObject = FEX::HLE::ThreadManager::GetStateObjectFromCPUState(Frame);
|
||||
// Give the robust list back to the application
|
||||
// Steam specifically checks to make sure the robust list is set
|
||||
@ -192,6 +211,7 @@ void RegisterThread(FEX::HLE::SyscallHandler* Handler) {
|
||||
struct timespec tp64 {};
|
||||
int cmd = futex_op & FUTEX_CMD_MASK;
|
||||
if (timeout && (cmd == FUTEX_WAIT || cmd == FUTEX_LOCK_PI || cmd == FUTEX_WAIT_BITSET || cmd == FUTEX_WAIT_REQUEUE_PI)) {
|
||||
FaultSafeUserMemAccess::VerifyIsReadable(timeout, sizeof(*timeout));
|
||||
// timeout argument is only handled as timespec in these cases
|
||||
// Otherwise just an integer
|
||||
tp64 = *timeout;
|
||||
@ -211,17 +231,20 @@ void RegisterThread(FEX::HLE::SyscallHandler* Handler) {
|
||||
stack_t* old64_ptr {};
|
||||
|
||||
if (ss) {
|
||||
FaultSafeUserMemAccess::VerifyIsReadable(ss, sizeof(*ss));
|
||||
ss64 = *ss;
|
||||
ss64_ptr = &ss64;
|
||||
}
|
||||
|
||||
if (old_ss) {
|
||||
FaultSafeUserMemAccess::VerifyIsReadable(old_ss, sizeof(*old_ss));
|
||||
old64 = *old_ss;
|
||||
old64_ptr = &old64;
|
||||
}
|
||||
uint64_t Result = FEX::HLE::_SyscallHandler->GetSignalDelegator()->RegisterGuestSigAltStack(ss64_ptr, old64_ptr);
|
||||
|
||||
if (Result == 0 && old_ss) {
|
||||
FaultSafeUserMemAccess::VerifyIsWritable(old_ss, sizeof(*old_ss));
|
||||
*old_ss = old64;
|
||||
}
|
||||
return Result;
|
||||
@ -291,11 +314,13 @@ void RegisterThread(FEX::HLE::SyscallHandler* Handler) {
|
||||
struct rusage* usage64_p {};
|
||||
|
||||
if (rusage) {
|
||||
FaultSafeUserMemAccess::VerifyIsReadable(rusage, sizeof(*rusage));
|
||||
usage64 = *rusage;
|
||||
usage64_p = &usage64;
|
||||
}
|
||||
uint64_t Result = ::wait4(pid, wstatus, options, usage64_p);
|
||||
if (rusage) {
|
||||
FaultSafeUserMemAccess::VerifyIsWritable(rusage, sizeof(*rusage));
|
||||
*rusage = usage64;
|
||||
}
|
||||
SYSCALL_ERRNO();
|
||||
@ -311,6 +336,7 @@ void RegisterThread(FEX::HLE::SyscallHandler* Handler) {
|
||||
siginfo_t* info64_p {};
|
||||
|
||||
if (rusage) {
|
||||
FaultSafeUserMemAccess::VerifyIsReadable(rusage, sizeof(*rusage));
|
||||
usage64 = *rusage;
|
||||
usage64_p = &usage64;
|
||||
}
|
||||
@ -323,10 +349,12 @@ void RegisterThread(FEX::HLE::SyscallHandler* Handler) {
|
||||
|
||||
if (Result != -1) {
|
||||
if (rusage) {
|
||||
FaultSafeUserMemAccess::VerifyIsWritable(rusage, sizeof(*rusage));
|
||||
*rusage = usage64;
|
||||
}
|
||||
|
||||
if (info) {
|
||||
FaultSafeUserMemAccess::VerifyIsWritable(info, sizeof(*info));
|
||||
*info = info64;
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ void RegisterTime(FEX::HLE::SyscallHandler* Handler) {
|
||||
uint64_t Result = ::time(&Host);
|
||||
|
||||
if (tloc) {
|
||||
FaultSafeUserMemAccess::VerifyIsWritable(tloc, sizeof(*tloc));
|
||||
// On 32-bit this truncates
|
||||
*tloc = (FEX::HLE::x32::old_time32_t)Host;
|
||||
}
|
||||
@ -47,6 +48,7 @@ void RegisterTime(FEX::HLE::SyscallHandler* Handler) {
|
||||
struct tms Host {};
|
||||
uint64_t Result = ::times(&Host);
|
||||
if (buf) {
|
||||
FaultSafeUserMemAccess::VerifyIsWritable(buf, sizeof(*buf));
|
||||
*buf = Host;
|
||||
}
|
||||
SYSCALL_ERRNO();
|
||||
@ -56,6 +58,7 @@ void RegisterTime(FEX::HLE::SyscallHandler* Handler) {
|
||||
struct utimbuf Host {};
|
||||
struct utimbuf* Host_p {};
|
||||
if (times) {
|
||||
FaultSafeUserMemAccess::VerifyIsReadable(times, sizeof(*times));
|
||||
Host = *times;
|
||||
Host_p = &Host;
|
||||
}
|
||||
@ -73,6 +76,7 @@ void RegisterTime(FEX::HLE::SyscallHandler* Handler) {
|
||||
uint64_t Result = ::gettimeofday(tv_ptr, tz);
|
||||
|
||||
if (tv) {
|
||||
FaultSafeUserMemAccess::VerifyIsWritable(tv, sizeof(*tv));
|
||||
*tv = tv64;
|
||||
}
|
||||
SYSCALL_ERRNO();
|
||||
@ -82,6 +86,7 @@ void RegisterTime(FEX::HLE::SyscallHandler* Handler) {
|
||||
struct timeval tv64 {};
|
||||
struct timeval* tv_ptr {};
|
||||
if (tv) {
|
||||
FaultSafeUserMemAccess::VerifyIsReadable(tv, sizeof(*tv));
|
||||
tv64 = *tv;
|
||||
tv_ptr = &tv64;
|
||||
}
|
||||
@ -95,12 +100,14 @@ void RegisterTime(FEX::HLE::SyscallHandler* Handler) {
|
||||
struct timespec* rem64_ptr {};
|
||||
|
||||
if (rem) {
|
||||
FaultSafeUserMemAccess::VerifyIsReadable(rem, sizeof(*rem));
|
||||
rem64 = *rem;
|
||||
rem64_ptr = &rem64;
|
||||
}
|
||||
|
||||
uint64_t Result = 0;
|
||||
if (req) {
|
||||
FaultSafeUserMemAccess::VerifyIsReadable(req, sizeof(*req));
|
||||
const struct timespec req64 = *req;
|
||||
Result = ::nanosleep(&req64, rem64_ptr);
|
||||
} else {
|
||||
@ -108,6 +115,7 @@ void RegisterTime(FEX::HLE::SyscallHandler* Handler) {
|
||||
}
|
||||
|
||||
if (rem) {
|
||||
FaultSafeUserMemAccess::VerifyIsWritable(rem, sizeof(*rem));
|
||||
*rem = rem64;
|
||||
}
|
||||
SYSCALL_ERRNO();
|
||||
@ -117,6 +125,7 @@ void RegisterTime(FEX::HLE::SyscallHandler* Handler) {
|
||||
struct timespec tp64 {};
|
||||
uint64_t Result = ::clock_gettime(clk_id, &tp64);
|
||||
if (tp) {
|
||||
FaultSafeUserMemAccess::VerifyIsWritable(tp, sizeof(*tp));
|
||||
*tp = tp64;
|
||||
}
|
||||
SYSCALL_ERRNO();
|
||||
@ -126,6 +135,7 @@ void RegisterTime(FEX::HLE::SyscallHandler* Handler) {
|
||||
struct timespec tp64 {};
|
||||
uint64_t Result = ::clock_getres(clk_id, &tp64);
|
||||
if (tp) {
|
||||
FaultSafeUserMemAccess::VerifyIsWritable(tp, sizeof(*tp));
|
||||
*tp = tp64;
|
||||
}
|
||||
SYSCALL_ERRNO();
|
||||
@ -140,11 +150,13 @@ void RegisterTime(FEX::HLE::SyscallHandler* Handler) {
|
||||
struct timespec* rem64_ptr {};
|
||||
|
||||
if (request) {
|
||||
FaultSafeUserMemAccess::VerifyIsReadable(request, sizeof(*request));
|
||||
req64 = *request;
|
||||
req64_ptr = &req64;
|
||||
}
|
||||
|
||||
if (remain) {
|
||||
FaultSafeUserMemAccess::VerifyIsReadable(remain, sizeof(*remain));
|
||||
rem64 = *remain;
|
||||
rem64_ptr = &rem64;
|
||||
}
|
||||
@ -153,6 +165,7 @@ void RegisterTime(FEX::HLE::SyscallHandler* Handler) {
|
||||
uint64_t Result = ::syscall(SYSCALL_DEF(clock_nanosleep), clockid, flags, req64_ptr, rem64_ptr);
|
||||
|
||||
if (remain && (flags & TIMER_ABSTIME) == 0) {
|
||||
FaultSafeUserMemAccess::VerifyIsWritable(remain, sizeof(*remain));
|
||||
// Remain is completely ignored if TIMER_ABSTIME is set.
|
||||
*remain = rem64;
|
||||
}
|
||||
@ -166,6 +179,7 @@ void RegisterTime(FEX::HLE::SyscallHandler* Handler) {
|
||||
}
|
||||
|
||||
uint64_t Result = 0;
|
||||
FaultSafeUserMemAccess::VerifyIsReadable(tp, sizeof(*tp));
|
||||
const struct timespec tp64 = *tp;
|
||||
Result = ::clock_settime(clockid, &tp64);
|
||||
SYSCALL_ERRNO();
|
||||
@ -174,6 +188,7 @@ void RegisterTime(FEX::HLE::SyscallHandler* Handler) {
|
||||
REGISTER_SYSCALL_IMPL_X32(futimesat, [](FEXCore::Core::CpuStateFrame* Frame, int dirfd, const char* pathname, const timeval32 times[2]) -> uint64_t {
|
||||
uint64_t Result = 0;
|
||||
if (times) {
|
||||
FaultSafeUserMemAccess::VerifyIsReadable(times, sizeof(timeval32) * 2);
|
||||
struct timeval times64[2] {};
|
||||
times64[0] = times[0];
|
||||
times64[1] = times[1];
|
||||
@ -188,6 +203,7 @@ void RegisterTime(FEX::HLE::SyscallHandler* Handler) {
|
||||
utimensat, [](FEXCore::Core::CpuStateFrame* Frame, int dirfd, const char* pathname, const compat_ptr<timespec32> times, int flags) -> uint64_t {
|
||||
uint64_t Result = 0;
|
||||
if (times) {
|
||||
FaultSafeUserMemAccess::VerifyIsReadable(times, sizeof(timeval32) * 2);
|
||||
timespec times64[2] {};
|
||||
times64[0] = times[0];
|
||||
times64[1] = times[1];
|
||||
@ -201,6 +217,7 @@ void RegisterTime(FEX::HLE::SyscallHandler* Handler) {
|
||||
REGISTER_SYSCALL_IMPL_X32(utimes, [](FEXCore::Core::CpuStateFrame* Frame, const char* filename, const timeval32 times[2]) -> uint64_t {
|
||||
uint64_t Result = 0;
|
||||
if (times) {
|
||||
FaultSafeUserMemAccess::VerifyIsReadable(times, sizeof(timeval32) * 2);
|
||||
struct timeval times64[2] {};
|
||||
times64[0] = times[0];
|
||||
times64[1] = times[1];
|
||||
@ -212,10 +229,12 @@ void RegisterTime(FEX::HLE::SyscallHandler* Handler) {
|
||||
});
|
||||
|
||||
REGISTER_SYSCALL_IMPL_X32(adjtimex, [](FEXCore::Core::CpuStateFrame* Frame, compat_ptr<FEX::HLE::x32::timex32> buf) -> uint64_t {
|
||||
FaultSafeUserMemAccess::VerifyIsReadable(buf, sizeof(*buf));
|
||||
struct timex Host {};
|
||||
Host = *buf;
|
||||
uint64_t Result = ::adjtimex(&Host);
|
||||
if (Result != -1) {
|
||||
FaultSafeUserMemAccess::VerifyIsWritable(buf, sizeof(*buf));
|
||||
*buf = Host;
|
||||
}
|
||||
SYSCALL_ERRNO();
|
||||
@ -223,10 +242,12 @@ void RegisterTime(FEX::HLE::SyscallHandler* Handler) {
|
||||
|
||||
REGISTER_SYSCALL_IMPL_X32(clock_adjtime,
|
||||
[](FEXCore::Core::CpuStateFrame* Frame, clockid_t clk_id, compat_ptr<FEX::HLE::x32::timex32> buf) -> uint64_t {
|
||||
FaultSafeUserMemAccess::VerifyIsReadable(buf, sizeof(*buf));
|
||||
struct timex Host {};
|
||||
Host = *buf;
|
||||
uint64_t Result = ::clock_adjtime(clk_id, &Host);
|
||||
if (Result != -1) {
|
||||
FaultSafeUserMemAccess::VerifyIsWritable(buf, sizeof(*buf));
|
||||
*buf = Host;
|
||||
}
|
||||
SYSCALL_ERRNO();
|
||||
|
@ -32,12 +32,14 @@ void RegisterTimer(FEX::HLE::SyscallHandler* Handler) {
|
||||
itimerspec old_value_host {};
|
||||
itimerspec* old_value_host_p {};
|
||||
|
||||
FaultSafeUserMemAccess::VerifyIsReadable(new_value, sizeof(*new_value));
|
||||
new_value_host = *new_value;
|
||||
if (old_value) {
|
||||
old_value_host_p = &old_value_host;
|
||||
}
|
||||
uint64_t Result = ::syscall(SYSCALL_DEF(timer_settime), timerid, flags, &new_value_host, old_value_host_p);
|
||||
if (Result != -1 && old_value) {
|
||||
FaultSafeUserMemAccess::VerifyIsWritable(old_value, sizeof(*old_value));
|
||||
*old_value = old_value_host;
|
||||
}
|
||||
SYSCALL_ERRNO();
|
||||
@ -47,6 +49,7 @@ void RegisterTimer(FEX::HLE::SyscallHandler* Handler) {
|
||||
timer_gettime, [](FEXCore::Core::CpuStateFrame* Frame, kernel_timer_t timerid, FEX::HLE::x32::old_itimerspec32* curr_value) -> uint64_t {
|
||||
itimerspec curr_value_host {};
|
||||
uint64_t Result = ::syscall(SYSCALL_DEF(timer_gettime), timerid, curr_value_host);
|
||||
FaultSafeUserMemAccess::VerifyIsWritable(curr_value, sizeof(*curr_value));
|
||||
*curr_value = curr_value_host;
|
||||
SYSCALL_ERRNO();
|
||||
});
|
||||
@ -59,6 +62,7 @@ void RegisterTimer(FEX::HLE::SyscallHandler* Handler) {
|
||||
}
|
||||
uint64_t Result = ::getitimer(which, val_p);
|
||||
if (curr_value) {
|
||||
FaultSafeUserMemAccess::VerifyIsWritable(curr_value, sizeof(*curr_value));
|
||||
*curr_value = val;
|
||||
}
|
||||
SYSCALL_ERRNO();
|
||||
@ -73,6 +77,7 @@ void RegisterTimer(FEX::HLE::SyscallHandler* Handler) {
|
||||
itimerval* old_p {};
|
||||
|
||||
if (new_value) {
|
||||
FaultSafeUserMemAccess::VerifyIsReadable(new_value, sizeof(*new_value));
|
||||
val = *new_value;
|
||||
val_p = &val;
|
||||
}
|
||||
@ -84,6 +89,7 @@ void RegisterTimer(FEX::HLE::SyscallHandler* Handler) {
|
||||
uint64_t Result = ::setitimer(which, val_p, old_p);
|
||||
|
||||
if (old_value) {
|
||||
FaultSafeUserMemAccess::VerifyIsWritable(old_value, sizeof(*old_value));
|
||||
*old_value = old;
|
||||
}
|
||||
SYSCALL_ERRNO();
|
||||
@ -92,6 +98,7 @@ void RegisterTimer(FEX::HLE::SyscallHandler* Handler) {
|
||||
REGISTER_SYSCALL_IMPL_X32(
|
||||
timer_create,
|
||||
[](FEXCore::Core::CpuStateFrame* Frame, clockid_t clockid, compat_ptr<FEX::HLE::x32::sigevent32> sevp, kernel_timer_t* timerid) -> uint64_t {
|
||||
FaultSafeUserMemAccess::VerifyIsReadable(sevp, sizeof(*sevp));
|
||||
sigevent Host = *sevp;
|
||||
uint64_t Result = ::syscall(SYSCALL_DEF(timer_create), clockid, &Host, timerid);
|
||||
SYSCALL_ERRNO();
|
||||
|
@ -38,6 +38,16 @@ void RegisterThread(FEX::HLE::SyscallHandler* Handler) {
|
||||
REGISTER_SYSCALL_IMPL_X64_FLAGS(
|
||||
clone, SyscallFlags::DEFAULT,
|
||||
([](FEXCore::Core::CpuStateFrame* Frame, uint32_t flags, void* stack, pid_t* parent_tid, pid_t* child_tid, void* tls) -> uint64_t {
|
||||
// This is slightly different EFAULT behaviour, if child_tid or parent_tid is invalid then the kernel just doesn't write to the
|
||||
// pointer. Still need to be EFAULT safe although.
|
||||
if ((flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)) && child_tid) {
|
||||
FaultSafeUserMemAccess::VerifyIsWritable(child_tid, sizeof(*child_tid));
|
||||
}
|
||||
|
||||
if ((flags & CLONE_PARENT_SETTID) && parent_tid) {
|
||||
FaultSafeUserMemAccess::VerifyIsWritable(parent_tid, sizeof(*parent_tid));
|
||||
}
|
||||
|
||||
FEX::HLE::clone3_args args {
|
||||
.Type = TypeOfClone::TYPE_CLONE2,
|
||||
.args =
|
||||
@ -59,6 +69,8 @@ void RegisterThread(FEX::HLE::SyscallHandler* Handler) {
|
||||
}));
|
||||
|
||||
REGISTER_SYSCALL_IMPL_X64(sigaltstack, [](FEXCore::Core::CpuStateFrame* Frame, const stack_t* ss, stack_t* old_ss) -> uint64_t {
|
||||
FaultSafeUserMemAccess::VerifyIsReadableOrNull(ss, sizeof(*ss));
|
||||
FaultSafeUserMemAccess::VerifyIsWritableOrNull(old_ss, sizeof(*old_ss));
|
||||
return FEX::HLE::_SyscallHandler->GetSignalDelegator()->RegisterGuestSigAltStack(ss, old_ss);
|
||||
});
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user