diff --git a/kernel/src/Driver/CtrlDriver.cpp b/kernel/src/Driver/CtrlDriver.cpp index 97f8e0d9..73a9d2bc 100644 --- a/kernel/src/Driver/CtrlDriver.cpp +++ b/kernel/src/Driver/CtrlDriver.cpp @@ -65,6 +65,12 @@ CtrlDriver::CtrlDriver() : S_IRWXU | S_IRWXG | S_IRWXO, "mira"); + WriteLog(LL_Debug, "MIRA_MOUNT_IN_SANDBOX: 0x%08x", MIRA_MOUNT_IN_SANDBOX); + WriteLog(LL_Debug, "MIRA_UNMOUNT_IN_SANDBOX: 0x%08x", MIRA_UNMOUNT_IN_SANDBOX); + WriteLog(LL_Debug, "MIRA_GET_PROC_THREAD_CREDENTIALS: 0x%08x", MIRA_GET_PROC_THREAD_CREDENTIALS); + WriteLog(LL_Debug, "MIRA_GET_PID_LIST: 0x%08x", MIRA_GET_PID_LIST); + WriteLog(LL_Debug, "MIRA_GET_PROC_INFORMATION: 0x%08x", MIRA_GET_PROC_INFORMATION); + switch (s_ErrorDev) { case 0: @@ -179,6 +185,9 @@ int32_t CtrlDriver::OnIoctl(struct cdev* p_Device, u_long p_Command, caddr_t p_D case MIRA_MOUNT_IN_SANDBOX: return OnMiraMountInSandbox(p_Device, p_Command, p_Data, p_FFlag, p_Thread); + case MIRA_UNMOUNT_IN_SANDBOX: + return OnMiraUnmountInSandbox(p_Device, p_Command, p_Data, p_FFlag, p_Thread); + // Get/set the thread credentials case MIRA_GET_PROC_THREAD_CREDENTIALS: return OnMiraThreadCredentials(p_Device, p_Command, p_Data, p_FFlag, p_Thread); @@ -349,6 +358,15 @@ int32_t CtrlDriver::OnMiraMountInSandbox(struct cdev* p_Device, u_long p_Command return -EACCES; } + + // Check to make sure that there's some kind of name + if (s_Input.Name[0] == '\0') + { + WriteLog(LL_Error, "invalid input path."); + return -EACCES; + } + + // Get the jailed path char* s_SandboxPath = nullptr; char* s_FreePath = nullptr; @@ -375,9 +393,7 @@ int32_t CtrlDriver::OnMiraMountInSandbox(struct cdev* p_Device, u_long p_Command do { - // TODO: we want to get the name of the folder so we can mount it within - // under the same name - s_Result = snprintf(s_InSandboxPath, sizeof(s_InSandboxPath), "%s/%s", s_SandboxPath, "myFolderName"); + s_Result = snprintf(s_InSandboxPath, sizeof(s_InSandboxPath), "%s/%s", s_SandboxPath, s_Input.Name); if (s_Result <= 0) break; @@ -430,11 +446,11 @@ int32_t CtrlDriver::OnMiraMountInSandbox(struct cdev* p_Device, u_long p_Command s_CurrentThreadFd->fd_rdir = s_CurrentThreadFd->fd_jdir = *(struct vnode**)kdlsym(rootvnode); // Try and mount using the current credentials - s_Result = Mira::OrbisOS::Utilities::MountNullFS(s_SandboxPath, s_RealPath, MNT_RDONLY); + s_Result = Mira::OrbisOS::Utilities::MountNullFS(s_InSandboxPath, s_RealPath, MNT_RDONLY); if (s_Result < 0) { - WriteLog(LL_Error, "could not mount fs inside sandbox (%s). (%d).", s_SandboxPath, s_Result); - krmdir_t(s_SandboxPath, s_MainThread); + WriteLog(LL_Error, "could not mount fs inside sandbox (%s). (%d).", s_InSandboxPath, s_Result); + krmdir_t(s_InSandboxPath, s_MainThread); // Restore credentials and fd *s_CurrentThreadCred = s_OriginalThreadCred; @@ -457,6 +473,159 @@ int32_t CtrlDriver::OnMiraMountInSandbox(struct cdev* p_Device, u_long p_Command return s_Result; } +int32_t CtrlDriver::OnMiraUnmountInSandbox(struct cdev* p_Device, u_long p_Command, caddr_t p_Data, int32_t p_FFlag, struct thread* p_Thread) +{ + //auto copyout = (int(*)(const void *kaddr, void *udaddr, size_t len))kdlsym(copyout); + auto copyin = (int(*)(const void* uaddr, void* kaddr, size_t len))kdlsym(copyin); + + auto snprintf = (int(*)(char *str, size_t size, const char *format, ...))kdlsym(snprintf); + auto vn_fullpath = (int(*)(struct thread *td, struct vnode *vp, char **retbuf, char **freebuf))kdlsym(vn_fullpath); + //auto strstr = (char *(*)(const char *haystack, const char *needle) )kdlsym(strstr); + + + if (p_Device == nullptr) + { + WriteLog(LL_Error, "invalid device."); + return -1; + } + + if (p_Thread == nullptr) + { + WriteLog(LL_Error, "invalid thread."); + return -1; + } + + auto s_TargetProc = p_Thread->td_proc; + if (s_TargetProc == nullptr) + { + WriteLog(LL_Error, "thread does not have a parent process wtf?"); + return -1; + } + + auto s_Descriptor = s_TargetProc->p_fd; + if (s_Descriptor == nullptr) + { + WriteLog(LL_Error, "could not get the file descriptor for proc."); + return -1; + } + + auto s_MainThread = Mira::Framework::GetFramework()->GetMainThread(); + if (s_MainThread == nullptr) + { + WriteLog(LL_Error, "could not get mira main thread."); + return -1; + } + + // Read in the mount point and the flags + MiraUnmountInSandbox s_Input = { 0 }; + auto s_Result = copyin(p_Data, &s_Input, sizeof(s_Input)); + if (s_Result != 0) + { + WriteLog(LL_Error, "could not copyin all data (%d).", s_Result); + return (s_Result < 0 ? s_Result : -s_Result); + } + + // Check to make sure that there's some kind of name + if (s_Input.Name[0] == '\0') + { + WriteLog(LL_Error, "invalid input path."); + return -EACCES; + } + + + // Get the jailed path + char* s_SandboxPath = nullptr; + char* s_FreePath = nullptr; + s_Result = vn_fullpath(s_MainThread, s_Descriptor->fd_jdir, &s_SandboxPath, &s_FreePath); + if (s_Result != 0) + { + WriteLog(LL_Error, "could not get the full path (%d).", s_Result); + return (s_Result < 0 ? s_Result : -s_Result); + } + + // Validate that we got something back + if (s_SandboxPath == nullptr) + { + WriteLog(LL_Error, "could not get the sandbox path."); + + if (s_FreePath != nullptr) + delete s_FreePath; + + return -1; + } + + char s_InSandboxPath[PATH_MAX] = { 0 }; + + do + { + s_Result = snprintf(s_InSandboxPath, sizeof(s_InSandboxPath), "%s/%s", s_SandboxPath, s_Input.Name); + if (s_Result <= 0) + break; + + // Check to see if the real path directory actually exists + auto s_DirectoryHandle = kopen_t(s_InSandboxPath, O_RDONLY | O_DIRECTORY, 0777, s_MainThread); + if (s_DirectoryHandle < 0) + { + WriteLog(LL_Error, "could not open directory (%s) (%d).", s_InSandboxPath, s_DirectoryHandle); + break; + } + + // Close the directory once we know it exists + kclose_t(s_DirectoryHandle, s_MainThread); + + + // In order for the mount call, it uses the calling thread to see if it has permissions + auto s_CurrentThreadCred = curthread->td_proc->p_ucred; + auto s_CurrentThreadFd = curthread->td_proc->p_fd; + + // Validate that our cred and descriptor are valid + if (s_CurrentThreadCred == nullptr || s_CurrentThreadFd == nullptr) + { + WriteLog(LL_Error, "the cred and/or fd are nullptr."); + s_Result = -EACCES; + break; + } + + // Save backups of the original fd and credentials + auto s_OriginalThreadCred = *s_CurrentThreadCred; + auto s_OriginalThreadFd = *s_CurrentThreadFd; + + // Set maximum permissions + s_CurrentThreadCred->cr_uid = 0; + s_CurrentThreadCred->cr_ruid = 0; + s_CurrentThreadCred->cr_rgid = 0; + s_CurrentThreadCred->cr_groups[0] = 0; + + s_CurrentThreadCred->cr_prison = *(struct prison**)kdlsym(prison0); + s_CurrentThreadFd->fd_rdir = s_CurrentThreadFd->fd_jdir = *(struct vnode**)kdlsym(rootvnode); + + // Unmount folder if the folder exist + int ret = kunmount_t(s_InSandboxPath, MNT_FORCE, s_MainThread); + if (ret < 0) { + WriteLog(LL_Error, "could not unmount folder (%s) (%d), Trying to remove anyway ...", s_InSandboxPath, ret); + } + + // Remove folder + ret = krmdir_t(s_InSandboxPath, s_MainThread); + if (ret < 0) { + WriteLog(LL_Error, "could not remove substitute folder (%s) (%d).", s_InSandboxPath, ret); + break; + } + + // Restore credentials and fd + *s_CurrentThreadCred = s_OriginalThreadCred; + *s_CurrentThreadFd = s_OriginalThreadFd; + + s_Result = 0; + } while (false); + + // Cleanup the freepath + if (s_FreePath != nullptr) + delete s_FreePath; + + return s_Result; +} + bool CtrlDriver::GetProcessInfo(int32_t p_ProcessId, MiraProcessInformation*& p_Result) { auto spinlock_exit = (void(*)(void))kdlsym(spinlock_exit); @@ -674,6 +843,12 @@ int32_t CtrlDriver::OnMiraThreadCredentials(struct cdev* p_Device, u_long p_Comm return (s_Result < 0 ? s_Result : -s_Result); } + if (s_Input.ThreadId <= 0) + s_Input.ThreadId = p_Thread->td_tid; + + if (s_Input.ProcessId <= 0) + s_Input.ProcessId = p_Thread->td_proc->p_pid; + MiraThreadCredentials* s_Output = nullptr; switch (s_Input.State) diff --git a/kernel/src/Driver/CtrlDriver.hpp b/kernel/src/Driver/CtrlDriver.hpp index 14625586..6c7f9041 100644 --- a/kernel/src/Driver/CtrlDriver.hpp +++ b/kernel/src/Driver/CtrlDriver.hpp @@ -156,8 +156,14 @@ typedef struct _MiraMountInSandbox { int32_t Permissions; char Path[_MAX_PATH]; + char Name[50]; } MiraMountInSandbox; +typedef struct _MiraUnmountInSandbox +{ + char Name[50]; +} MiraUnmountInSandbox; + typedef struct _MiraCreateTrainerShm { struct thread* Thread; @@ -197,6 +203,9 @@ typedef struct _MiraGetTrainersShm // Mount a path within sandbox #define MIRA_MOUNT_IN_SANDBOX _IOC(IOC_IN, MIRA_IOCTL_BASE, 4, sizeof(MiraMountInSandbox)) +// Unmount a path within sandbox +#define MIRA_UNMOUNT_IN_SANDBOX _IOC(IOC_IN, MIRA_IOCTL_BASE, 4, sizeof(MiraUnmountInSandbox)) + // Create new Shm #define MIRA_CREATE_TRAINER_SHM _IOC(IOC_IN, MIRA_IOCTL_BASE, 5, sizeof(MiraCreateTrainerShm)) @@ -228,6 +237,7 @@ namespace Mira static int32_t OnMiraGetProcInformation(struct cdev* p_Device, u_long p_Command, caddr_t p_Data, int32_t p_FFlag, struct thread* p_Thread); static int32_t OnMiraGetProcList(struct cdev* p_Device, u_long p_Command, caddr_t p_Data, int32_t p_FFlag, struct thread* p_Thread); static int32_t OnMiraMountInSandbox(struct cdev* p_Device, u_long p_Command, caddr_t p_Data, int32_t p_FFlag, struct thread* p_Thread); + static int32_t OnMiraUnmountInSandbox(struct cdev* p_Device, u_long p_Command, caddr_t p_Data, int32_t p_FFlag, struct thread* p_Thread); static int32_t OnMiraThreadCredentials(struct cdev* p_Device, u_long p_Command, caddr_t p_Data, int32_t p_FFlag, struct thread* p_Thread); // Helper functions diff --git a/kernel/src/Mira.cpp b/kernel/src/Mira.cpp index e5b39e80..ee244e57 100644 --- a/kernel/src/Mira.cpp +++ b/kernel/src/Mira.cpp @@ -355,7 +355,7 @@ struct thread* Mira::Framework::GetSyscoreThread() { auto _mtx_lock_flags = (void(*)(struct mtx *mutex, int flags))kdlsym(_mtx_lock_flags); auto _mtx_unlock_flags = (void(*)(struct mtx *mutex, int flags))kdlsym(_mtx_unlock_flags); - auto s_Process = OrbisOS::Utilities::FindProcessByName("SceSysCore"); + auto s_Process = OrbisOS::Utilities::FindProcessByName("SceSysCore.elf"); if (s_Process == nullptr) { WriteLog(LL_Error, "could not get SceSysCore process."); diff --git a/kernel/src/Plugins/Substitute/Substitute.cpp b/kernel/src/Plugins/Substitute/Substitute.cpp index 51146486..1a845d23 100644 --- a/kernel/src/Plugins/Substitute/Substitute.cpp +++ b/kernel/src/Plugins/Substitute/Substitute.cpp @@ -1031,7 +1031,8 @@ void Substitute::LoadAllPrx(struct thread* td, const char* folder_path) // Create relative path for the load WriteLog(LL_Info, "[%s] Loading %s ...", s_TitleId, s_RelativeSprxPath); - Utilities::LoadPRXModule(td->td_proc, s_RelativeSprxPath); + Utilities::LoadPRXModule(td->td_proc, s_RelativeSprxPath); + WriteLog(LL_Info, "Loading PRX Done !"); } diff --git a/loader/Makefile b/loader/Makefile index ac4f51b2..fe22e947 100644 --- a/loader/Makefile +++ b/loader/Makefile @@ -1,6 +1,7 @@ # CHANGEME: Default Orbis Version ifeq ($(MIRA_PLATFORM),) -$(error No firmware version set for MIRA_PLATFORM) +MIRA_PLATFORM := MIRA_PLATFORM_ORBIS_BSD_505 +# $(error No firmware version set for MIRA_PLATFORM) endif # Check to see if we are building in CI/Checking mode