From 230193129f2a143e50c6dddebc2eaec1ee4bedbb Mon Sep 17 00:00:00 2001 From: Ivan Chikish Date: Wed, 12 Jul 2023 17:24:28 +0300 Subject: [PATCH] [orbis-kernel] Add basic EFAULT check Check for valid pointer range Replace some deprecated checks --- orbis-kernel/src/sys/sys_generic.cpp | 4 +++- orbis-kernel/src/sys/sys_sce.cpp | 5 +++- orbis-kernel/src/sys/sys_umtx.cpp | 4 +++- orbis-kernel/src/umtx.cpp | 24 ++++++++++++++----- rpcsx-os/orbis-kernel-config/orbis-config.hpp | 24 ++++++++++--------- 5 files changed, 41 insertions(+), 20 deletions(-) diff --git a/orbis-kernel/src/sys/sys_generic.cpp b/orbis-kernel/src/sys/sys_generic.cpp index e9eb0d54f..11ef3f596 100644 --- a/orbis-kernel/src/sys/sys_generic.cpp +++ b/orbis-kernel/src/sys/sys_generic.cpp @@ -108,7 +108,9 @@ orbis::SysResult orbis::sys_nfssvc(Thread *thread, sint flag, caddr_t argp) { } orbis::SysResult orbis::sys_sysarch(Thread *thread, sint op, ptr parms) { if (op == 129) { - auto fs = uread((ptr)parms); + uint64_t fs; + if (auto error = uread(fs, (ptr)parms); error != ErrorCode{}) + return error; std::printf("sys_sysarch: set FS to 0x%zx\n", (std::size_t)fs); thread->fsBase = fs; return {}; diff --git a/orbis-kernel/src/sys/sys_sce.cpp b/orbis-kernel/src/sys/sys_sce.cpp index 14c60453f..0e50732bc 100644 --- a/orbis-kernel/src/sys/sys_sce.cpp +++ b/orbis-kernel/src/sys/sys_sce.cpp @@ -601,7 +601,10 @@ orbis::SysResult orbis::sys_mdbg_service(Thread *thread, uint32_t op, switch (op) { case 1: { - auto prop = uread((ptr)arg0); + mdbg_property prop; + if (auto error = uread(prop, (ptr)arg0); + error != ErrorCode{}) + return error; ORBIS_LOG_WARNING(__FUNCTION__, prop.name, prop.addr_ptr, prop.areaSize); break; } diff --git a/orbis-kernel/src/sys/sys_umtx.cpp b/orbis-kernel/src/sys/sys_umtx.cpp index b73a008de..3a1cf57a2 100644 --- a/orbis-kernel/src/sys/sys_umtx.cpp +++ b/orbis-kernel/src/sys/sys_umtx.cpp @@ -6,7 +6,9 @@ static orbis::ErrorCode ureadTimespec(orbis::timespec &ts, orbis::ptr addr) { - ts = uread(addr); + orbis::ErrorCode error = uread(ts, addr); + if (error != orbis::ErrorCode{}) + return error; if (ts.sec < 0 || ts.nsec < 0 || ts.nsec > 1000000000) { return orbis::ErrorCode::INVAL; } diff --git a/orbis-kernel/src/umtx.cpp b/orbis-kernel/src/umtx.cpp index 5bea53c86..000de7319 100644 --- a/orbis-kernel/src/umtx.cpp +++ b/orbis-kernel/src/umtx.cpp @@ -216,7 +216,9 @@ static ErrorCode do_unlock_pp(Thread *thread, ptr m, uint flags) { orbis::ErrorCode orbis::umtx_trylock_umutex(Thread *thread, ptr m) { ORBIS_LOG_TRACE(__FUNCTION__, m); - uint flags = uread(&m->flags); + uint flags; + if (ErrorCode err = uread(flags, &m->flags); err != ErrorCode{}) + return err; switch (flags & (kUmutexPrioInherit | kUmutexPrioProtect)) { case 0: return do_lock_normal(thread, m, flags, 0, umutex_lock_mode::try_); @@ -231,7 +233,9 @@ orbis::ErrorCode orbis::umtx_trylock_umutex(Thread *thread, ptr m) { orbis::ErrorCode orbis::umtx_lock_umutex(Thread *thread, ptr m, std::uint64_t ut) { ORBIS_LOG_TRACE(__FUNCTION__, m, ut); - uint flags = uread(&m->flags); + uint flags; + if (ErrorCode err = uread(flags, &m->flags); err != ErrorCode{}) + return err; switch (flags & (kUmutexPrioInherit | kUmutexPrioProtect)) { case 0: return do_lock_normal(thread, m, flags, ut, umutex_lock_mode::lock); @@ -245,7 +249,9 @@ orbis::ErrorCode orbis::umtx_lock_umutex(Thread *thread, ptr m, orbis::ErrorCode orbis::umtx_unlock_umutex(Thread *thread, ptr m) { ORBIS_LOG_TRACE(__FUNCTION__, m); - uint flags = uread(&m->flags); + uint flags; + if (ErrorCode err = uread(flags, &m->flags); err != ErrorCode{}) + return err; switch (flags & (kUmutexPrioInherit | kUmutexPrioProtect)) { case 0: return do_unlock_normal(thread, m, flags); @@ -268,7 +274,9 @@ orbis::ErrorCode orbis::umtx_cv_wait(Thread *thread, ptr cv, ptr m, std::uint64_t ut, ulong wflags) { ORBIS_LOG_NOTICE(__FUNCTION__, thread, cv, m, ut, wflags); - const uint flags = uread(&cv->flags); + uint flags; + if (ErrorCode err = uread(flags, &m->flags); err != ErrorCode{}) + return err; if ((wflags & kCvWaitClockId) != 0) { ORBIS_LOG_FATAL("umtx_cv_wait: CLOCK_ID unimplemented", wflags); return ErrorCode::NOSYS; @@ -360,7 +368,9 @@ orbis::ErrorCode orbis::umtx_wake_private(Thread *thread, ptr uaddr, orbis::ErrorCode orbis::umtx_wait_umutex(Thread *thread, ptr m, std::uint64_t ut) { ORBIS_LOG_TRACE(__FUNCTION__, m, ut); - uint flags = uread(&m->flags); + uint flags; + if (ErrorCode err = uread(flags, &m->flags); err != ErrorCode{}) + return err; switch (flags & (kUmutexPrioInherit | kUmutexPrioProtect)) { case 0: return do_lock_normal(thread, m, flags, ut, umutex_lock_mode::wait); @@ -378,7 +388,9 @@ orbis::ErrorCode orbis::umtx_wake_umutex(Thread *thread, ptr m) { if ((owner & ~kUmutexContested) != 0) return {}; - [[maybe_unused]] uint flags = uread(&m->flags); + [[maybe_unused]] uint flags; + if (ErrorCode err = uread(flags, &m->flags); err != ErrorCode{}) + return err; auto [chain, key, lock] = g_context.getUmtxChain1(thread->tproc->pid, m); std::size_t count = chain.sleep_queue.count(key); diff --git a/rpcsx-os/orbis-kernel-config/orbis-config.hpp b/rpcsx-os/orbis-kernel-config/orbis-config.hpp index b1c7e276d..867242465 100644 --- a/rpcsx-os/orbis-kernel-config/orbis-config.hpp +++ b/rpcsx-os/orbis-kernel-config/orbis-config.hpp @@ -42,34 +42,36 @@ using caddr_t = ptr; [[nodiscard]] inline ErrorCode ureadRaw(void *kernelAddress, ptr userAddress, size_t size) { + auto addr = reinterpret_cast(userAddress); + if (addr < 0x40000 || addr + size > 0x100'0000'0000 || addr + size < addr) + return ErrorCode::FAULT; std::memcpy(kernelAddress, userAddress, size); return {}; } [[nodiscard]] inline ErrorCode uwriteRaw(ptr userAddress, const void *kernelAddress, size_t size) { + auto addr = reinterpret_cast(userAddress); + if (addr < 0x40000 || addr + size > 0x100'0000'0000 || addr + size < addr) + return ErrorCode::FAULT; std::memcpy(userAddress, kernelAddress, size); return {}; } -[[nodiscard]] inline ErrorCode ureadString(char *kernelAddress, - size_t kernelSize, +[[nodiscard]] inline ErrorCode ureadString(char *kernelAddress, size_t size, ptr userAddress) { - std::strncpy(kernelAddress, userAddress, kernelSize); - if (kernelAddress[kernelSize - 1] != '\0') { - kernelAddress[kernelSize - 1] = '\0'; + auto addr = reinterpret_cast(userAddress); + if (addr < 0x40000 || addr + size > 0x100'0000'0000 || addr + size < addr) + return ErrorCode::FAULT; + std::strncpy(kernelAddress, userAddress, size); + if (kernelAddress[size - 1] != '\0') { + kernelAddress[size - 1] = '\0'; return ErrorCode::NAMETOOLONG; } return {}; } -template [[deprecated]] T uread(ptr pointer) { - T result{}; - ureadRaw(&result, pointer, sizeof(T)); - return result; -} - template [[nodiscard]] ErrorCode uread(T &result, ptr pointer) { return ureadRaw(&result, pointer, sizeof(T)); }