aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReiko Asakura2021-02-22 16:10:10 -0500
committerReiko Asakura2021-02-22 16:12:47 -0500
commit5e555eedc481d06fb15b2680f504331328682ac6 (patch)
treeb12d85bdb44b01b693073bc2d92a97b88056fdf6
parentUpdate libsubstitute (diff)
downloadtaihen-5e555eedc481d06fb15b2680f504331328682ac6.tar.gz
Set caller context in module related syscallsrelease/0.12.1
While not necessary for non-remote function, a kernel module loaded from a user thread may in turn call a remote module load function. The caller context is set to keep backward compatibility. An example is the Adrenaline kernel module.
-rw-r--r--taihen-user.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/taihen-user.c b/taihen-user.c
index 39aa47b..03ad105 100644
--- a/taihen-user.c
+++ b/taihen-user.c
@@ -25,6 +25,35 @@
#define MAX_ARGS_SIZE 256
/**
+ * @brief Sets TPIDRURO for a syscall requiring caller
+ * context identification.
+ *
+ * @return Previous TPIDRURO value.
+ */
+__attribute__ ((naked))
+static int shift_tpidruro(void) {
+ asm (
+ "mrc p15, 0, r0, c13, c0, 3\n"
+ "lsls r1, r0, 16\n"
+ "mcr p15, 0, r1, c13, c0, 3\n"
+ "bx lr\n"
+ );
+}
+
+/**
+ * @brief Restores TPIDRURO value.
+ *
+ * @param[in] TPIDRURO value to restore.
+ */
+__attribute__ ((naked))
+static void restore_tpidruro(int v) {
+ asm (
+ "mcr p15, 0, r0, c13, c0, 3\n"
+ "bx lr\n"
+ );
+}
+
+/**
* @brief Add a hook to a module function export for the calling process
*
* @see taiHookFunctionExportForKernel
@@ -350,12 +379,15 @@ SceUID taiLoadKernelModule(const char *path, int flags, void *opt) {
char k_path[MAX_NAME_LEN];
SceUID pid;
int ret;
+ int state;
pid = sceKernelGetProcessId();
if (sceSblACMgrIsShell(0)) {
if (opt == NULL) {
if (sceKernelStrncpyUserToKernel(k_path, (uintptr_t)path, MAX_NAME_LEN) < MAX_NAME_LEN) {
+ state = shift_tpidruro();
ret = sceKernelLoadModule(k_path, flags, NULL);
+ restore_tpidruro(state);
LOG("loaded %s: %x", k_path, ret);
if (ret >= 0) {
ret = sceKernelCreateUserUid(pid, ret);
@@ -392,6 +424,7 @@ int taiStartKernelModuleForUser(SceUID modid, tai_module_args_t *args, void *opt
int ret;
int k_res;
SceUID pid;
+ int state;
pid = sceKernelGetProcessId();
if (sceSblACMgrIsShell(0)) {
@@ -405,7 +438,9 @@ int taiStartKernelModuleForUser(SceUID modid, tai_module_args_t *args, void *opt
ret = sceKernelMemcpyUserToKernel(buf, (uintptr_t)kargs.argp, kargs.args);
if (ret >= 0) {
k_res = 0;
+ state = shift_tpidruro();
ret = sceKernelStartModule(modid, kargs.args, buf, kargs.flags, NULL, &k_res);
+ restore_tpidruro(state);
if (res) {
sceKernelMemcpyKernelToUser((uintptr_t)res, &k_res, sizeof(*res));
}
@@ -443,6 +478,7 @@ SceUID taiLoadStartKernelModuleForUser(const char *path, tai_module_args_t *args
SceUID modid;
int ret;
SceUID pid;
+ int state;
pid = sceKernelGetProcessId();
if (sceSblACMgrIsShell(0)) {
@@ -453,7 +489,9 @@ SceUID taiLoadStartKernelModuleForUser(const char *path, tai_module_args_t *args
ret = sceKernelMemcpyUserToKernel(buf, (uintptr_t)kargs.argp, kargs.args);
if (ret >= 0) {
if (sceKernelStrncpyUserToKernel(k_path, (uintptr_t)path, MAX_NAME_LEN) < MAX_NAME_LEN) {
+ state = shift_tpidruro();
ret = sceKernelLoadStartModule(k_path, kargs.args, buf, kargs.flags, NULL, NULL);
+ restore_tpidruro(state);
LOG("loaded %s: %x", k_path, ret);
if (ret >= 0) {
ret = sceKernelCreateUserUid(pid, ret);
@@ -492,6 +530,7 @@ SceUID taiLoadStartModuleForPidForUser(const char *path, tai_module_args_t *args
char k_path[MAX_NAME_LEN];
SceUID modid;
int ret;
+ int state;
if (sceSblACMgrIsShell(0)) {
@@ -502,7 +541,9 @@ SceUID taiLoadStartModuleForPidForUser(const char *path, tai_module_args_t *args
ret = sceKernelMemcpyUserToKernel(buf, (uintptr_t)kargs.argp, kargs.args);
if (ret >= 0) {
if (sceKernelStrncpyUserToKernel(k_path, (uintptr_t)path, MAX_NAME_LEN) < MAX_NAME_LEN) {
+ state = shift_tpidruro();
ret = sceKernelLoadStartModuleForPid(kargs.pid, k_path, kargs.args, buf, kargs.flags, NULL, NULL);
+ restore_tpidruro(state);
LOG("loaded %s: %x", k_path, ret);
if (ret >= 0) {
ret = sceKernelCreateUserUid(kargs.pid, ret);
@@ -544,6 +585,7 @@ int taiStopKernelModuleForUser(SceUID modid, tai_module_args_t *args, void *opt,
int k_res;
SceUID pid;
SceUID kid;
+ int state;
pid = sceKernelGetProcessId();
if (sceSblACMgrIsShell(0)) {
@@ -556,7 +598,9 @@ int taiStopKernelModuleForUser(SceUID modid, tai_module_args_t *args, void *opt,
ret = sceKernelMemcpyUserToKernel(buf, (uintptr_t)kargs.argp, kargs.args);
if (ret >= 0) {
k_res = 0;
+ state = shift_tpidruro();
ret = sceKernelStopModule(kid, kargs.args, buf, kargs.flags, NULL, &k_res);
+ restore_tpidruro(state);
if (res) {
sceKernelMemcpyKernelToUser((uintptr_t)res, &k_res, sizeof(*res));
}
@@ -595,13 +639,16 @@ int taiUnloadKernelModule(SceUID modid, int flags, void *opt) {
SceUID pid;
SceUID kid;
int ret;
+ int state;
pid = sceKernelGetProcessId();
if (sceSblACMgrIsShell(0)) {
if (opt == NULL) {
kid = sceKernelKernelUidForUserUid(pid, modid);
if (kid >= 0) {
+ state = shift_tpidruro();
ret = sceKernelUnloadModule(kid, flags, NULL);
+ restore_tpidruro(state);
if (ret >= 0) {
sceKernelDeleteUserUid(pid, modid);
}
@@ -637,6 +684,7 @@ int taiStopUnloadKernelModuleForUser(SceUID modid, tai_module_args_t *args, void
int k_res;
SceUID pid;
SceUID kid;
+ int state;
pid = sceKernelGetProcessId();
if (sceSblACMgrIsShell(0)) {
@@ -649,7 +697,9 @@ int taiStopUnloadKernelModuleForUser(SceUID modid, tai_module_args_t *args, void
ret = sceKernelMemcpyUserToKernel(buf, (uintptr_t)kargs.argp, kargs.args);
if (ret >= 0) {
k_res = 0;
+ state = shift_tpidruro();
ret = sceKernelStopUnloadModule(kid, kargs.args, buf, kargs.flags, NULL, &k_res);
+ restore_tpidruro(state);
if (res) {
sceKernelMemcpyKernelToUser((uintptr_t)res, &k_res, sizeof(*res));
}
@@ -692,6 +742,7 @@ int taiStopModuleForPidForUser(SceUID modid, tai_module_args_t *args, void *opt,
int ret;
int k_res;
SceUID kid;
+ int state;
if (sceSblACMgrIsShell(0)) {
kargs.size = 0;
@@ -703,7 +754,9 @@ int taiStopModuleForPidForUser(SceUID modid, tai_module_args_t *args, void *opt,
ret = sceKernelMemcpyUserToKernel(buf, (uintptr_t)kargs.argp, kargs.args);
if (ret >= 0) {
k_res = 0;
+ state = shift_tpidruro();
ret = sceKernelStopModuleForPid(kargs.pid, kid, kargs.args, buf, kargs.flags, NULL, &k_res);
+ restore_tpidruro(state);
if (res) {
sceKernelMemcpyKernelToUser((uintptr_t)res, &k_res, sizeof(*res));
}
@@ -741,12 +794,15 @@ int taiStopModuleForPidForUser(SceUID modid, tai_module_args_t *args, void *opt,
int taiUnloadModuleForPid(SceUID pid, SceUID modid, int flags, void *opt) {
SceUID kid;
int ret;
+ int state;
if (sceSblACMgrIsShell(0)) {
if (opt == NULL) {
kid = sceKernelKernelUidForUserUid(pid, modid);
if (kid >= 0) {
+ state = shift_tpidruro();
ret = sceKernelUnloadModuleForPid(pid, kid, flags, NULL);
+ restore_tpidruro(state);
if (ret >= 0) {
sceKernelDeleteUserUid(pid, modid);
}
@@ -781,6 +837,7 @@ int taiStopUnloadModuleForPidForUser(SceUID modid, tai_module_args_t *args, void
int ret;
int k_res;
SceUID kid;
+ int state;
if (sceSblACMgrIsShell(0)) {
kargs.size = 0;
@@ -792,7 +849,9 @@ int taiStopUnloadModuleForPidForUser(SceUID modid, tai_module_args_t *args, void
ret = sceKernelMemcpyUserToKernel(buf, (uintptr_t)kargs.argp, kargs.args);
if (ret >= 0) {
k_res = 0;
+ state = shift_tpidruro();
ret = sceKernelStopUnloadModuleForPid(kargs.pid, kid, kargs.args, buf, kargs.flags, NULL, &k_res);
+ restore_tpidruro(state);
if (res) {
sceKernelMemcpyKernelToUser((uintptr_t)res, &k_res, sizeof(*res));
}