static int redirect_file_access(struct tracy_event *e, int argpos, bool resolve_symlinks) { struct tracy_sc_args a; int rc = TRACY_HOOK_CONTINUE; char *path = NULL; tracy_child_addr_t devname_new = NULL; struct fstab_rec *fstabrec; long *argptr; struct multiboot_child_data *mbc = e->child->custom; // call hook_open if (e->syscall_num == get_syscall_number_abi("open", e->abi) || e->syscall_num == get_syscall_number_abi("openat", e->abi)) { int rc_open = hook_open(e, argpos, resolve_symlinks); if (rc_open) return rc_open; } if (e->child->pre_syscall) { // get path argptr = &e->args.a0; path = get_patharg(e->child, argptr[argpos], resolve_symlinks); if (!path) { rc = TRACY_HOOK_ABORT; goto out; } // check if we need to redirect this file fstabrec = get_fstab_rec(path); if (!fstabrec) { goto out; } // ignore symlinks for calls which don't resolve them struct stat sb; if (!resolve_symlinks && !lstat(path, &sb) && S_ISLNK(sb.st_mode)) { goto out; } char *replacement = fstabrec->replacement_bind ? fstabrec-> stub_device : fstabrec->replacement_device; DEBUG("%s(%s): redirect %s->%s arg=%d\n", __func__, get_syscall_name_abi(e->syscall_num, e->abi), path, replacement, argpos); // copy new devname devname_new = copy_patharg(e->child, replacement); if (!devname_new) { kperror("copy_patharg"); rc = TRACY_HOOK_ABORT; goto out; } // copy args memcpy(&a, &(e->args), sizeof(struct tracy_sc_args)); // modify args argptr = &a.a0; argptr[argpos] = (long)devname_new; // write new args if (tracy_modify_syscall_args(e->child, a.syscall, &a)) { kperror("tracy_modify_syscall_args"); rc = TRACY_HOOK_ABORT; goto out; } // set devname so we can free it later mbc->memory = devname_new; } else { // free previous data if (mbc->memory) { free_patharg(e->child, mbc->memory); mbc->memory = NULL; } } out: if (path) free(path); if (devname_new && rc) free_patharg(e->child, devname_new); return rc; }
static int hook_mount(struct tracy_event *e) { struct tracy_sc_args a; struct fstab_rec *fstabrec; tracy_child_addr_t devname_new = NULL; char *devname = NULL, *mountpoint = NULL; int rc = TRACY_HOOK_CONTINUE; struct multiboot_child_data *mbc = e->child->custom; if (e->child->pre_syscall) { // get args devname = get_patharg(e->child, e->args.a0, 1); if (!devname) { rc = TRACY_HOOK_ABORT; goto out; } mountpoint = get_patharg(e->child, e->args.a1, 1); if (!mountpoint) { rc = TRACY_HOOK_ABORT; goto out; } unsigned long flags = (unsigned long)e->args.a3; DEBUG("mount %s on %s remount=%lu, ro=%lu\n", devname, mountpoint, (flags & MS_REMOUNT), (flags & MS_RDONLY)); if (!strcmp(mountpoint, "/mnt/secure/asec")) { fstabrec = asec_rec; } else { // check if we need to redirect this partition fstabrec = get_fstab_rec(devname); if (!fstabrec) { goto out; } } DEBUG("hijack: mount %s on %s\n", devname, mountpoint); // copy new devname devname_new = copy_patharg(e->child, fstabrec->replacement_device); if (!devname_new) { kperror("copy_patharg"); rc = TRACY_HOOK_ABORT; goto out; } // copy args memcpy(&a, &(e->args), sizeof(struct tracy_sc_args)); // modify args a.a0 = (long)devname_new; if (fstabrec->replacement_bind) { a.a2 = 0; a.a3 |= MS_BIND; } // write new args if (tracy_modify_syscall_args(e->child, a.syscall, &a)) { kperror("tracy_modify_syscall_args"); rc = TRACY_HOOK_ABORT; goto out; } // set devname so we can free it later mbc->memory = devname_new; } else { // free previous data if (mbc->memory) { free_patharg(e->child, mbc->memory); mbc->memory = NULL; } } out: if (devname) free(devname); if (mountpoint) free(mountpoint); if (devname_new && rc) free_patharg(e->child, devname_new); return rc; }
/** * Call by the exeption to handle the syscall * \private */ void syscall_handler(registers_t * regs) { int32_t res = 0; int32_t syscall = regs->v_reg[0]; // code of the syscall switch (syscall) { case FOURCHETTE: res = create_proc(get_arg((char **) regs->a_reg[2], 0), regs->a_reg[0], regs->a_reg[1], (char **) regs->a_reg[2]); break; case PRINT: res = print_string((char *) regs->a_reg[0]); return; /* We save the good return value in the pcb */ case READ: res = read_string((char *) regs->a_reg[0], regs->a_reg[1]); return; /* We save the good return value in the pcb */ case FPRINT: if (regs->a_reg[0] == CONSOLE) kprint((char *) regs->a_reg[1]); else kmaltaprint8((char *) regs->a_reg[1]); break; case SLEEP: res = go_to_sleep(regs->a_reg[0]); break; case BLOCK: res = kblock(regs->a_reg[0], BLOCKED); break; case UNBLOCK: kwakeup(regs->a_reg[0]); break; case WAIT: res = waitfor(regs->a_reg[0], (int32_t *) regs->a_reg[1]); break; case SEND: res = send_msg(pcb_get_pid(get_current_pcb()), (msg_arg *) regs->a_reg[0]); break; case RECV: res = recv_msg(pcb_get_pid(get_current_pcb()), (msg_arg *) regs->a_reg[0]); if (res == NOTFOUND) go_to_sleep(((msg_arg *) regs->a_reg[0])->timeout); break; case PERROR: kperror((char *) regs->a_reg[0]); break; case GERROR: res = kgerror(); break; case SERROR: kserror(regs->a_reg[0]); break; case GETPINFO: res = get_pinfo(regs->a_reg[0], (pcbinfo *) regs->a_reg[1]); break; case GETPID: res = pcb_get_pid(get_current_pcb()); break; case GETALLPID: res = get_all_pid((int *) regs->a_reg[0]); break; case CHGPPRI: res = chg_ppri(regs->a_reg[0], regs->a_reg[1]); break; case KILL: res = kkill(regs->a_reg[0]); break; case EXIT: kexit(regs->a_reg[0]); break; default: kprintln("ERROR: Unknown syscall"); break; } // saves the return code regs->v_reg[0] = res; return; }