/* Find and execute hook. */ int tracy_execute_hook(struct tracy *t, char *syscall, struct tracy_event *e) { struct tracy_ll_item *item; int hash; union { void *pvoid; tracy_hook_func pfunc; } _hax; if (TRACY_PRINT_SYSCALLS(t)) printf(_y("%04d System call: %s (%ld) Pre: %d")"\n", e->child->pid, get_syscall_name_abi(e->syscall_num, e->abi), e->syscall_num, e->child->pre_syscall); hash = hash_syscall(syscall, e->abi); item = ll_find(t->hooks, hash); if (item) { /* printf("Executing hook for: %s\n", syscall); */ /* ANSI C has some disadvantages too ... */ _hax.pvoid = item->data; return _hax.pfunc(e); } if (t->defhook) return t->defhook(e); return TRACY_HOOK_NOHOOK; }
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; }