static int hook_fileaccess(struct tracy_event *e) { unsigned int i; for (i = 0; i < ARRAY_SIZE(info); i++) { if (info[i].syscall_number == e->syscall_num) { bool resolve_symlinks = info[i].resolve_symlinks; int atflags_pos = info[i].atflags; if (atflags_pos >= 0) { long *argptr = &e->args.a0; resolve_symlinks = !(argptr[atflags_pos] & AT_SYMLINK_NOFOLLOW); } if (e->syscall_num == get_syscall_number_abi("open", e->abi)) resolve_symlinks = !(e->args.a1 & O_NOFOLLOW); else if (e->syscall_num == get_syscall_number_abi("openat", e->abi)) resolve_symlinks = !(e->args.a3 & O_NOFOLLOW); return redirect_file_access(e, info[i].argnum, resolve_symlinks); } } return TRACY_HOOK_ABORT; }
static int soxy_connect(struct tracy_event *e, int sockfd, const struct sockaddr *addr, socklen_t addrlen) { #ifdef __i386__ ssize_t args_len; unsigned long *args; long ret; tracy_child_addr_t mem; if(tracy_mmap(e->child, &mem, NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) != 0) { fprintf(stderr, "soxy_connect: tracy_mmap failed\n"); _exit(1); } args_len = sizeof(int) + sizeof(const struct sockaddr *) + sizeof(socklen_t); args = malloc(args_len); args[0] = sockfd; args[1] = (long)addr; args[2] = addrlen; if(tracy_write_mem(e->child, mem, args, args_len) != (ssize_t) args_len) { fprintf(stderr, "soxy_connect: tracy_write_mem failed\n"); _exit(1); } e->args.a0 = SYS_CONNECT; e->args.a1 = (long)mem; ret = 0; if (tracy_inject_syscall(e->child, __NR_socketcall, &(e->args), &ret) || ret < 0) { tracee_perror(-ret, "soxy_connect: socketcall, tracy_inject_syscall failed"); _exit(1); } return ret; /* TODO: munmap */ #else long ret = 0; e->args.a0 = sockfd; e->args.a1 = (long)addr; e->args.a2 = addrlen; if (tracy_inject_syscall(e->child, get_syscall_number_abi("connect", TRACY_ABI_NATIVE), &(e->args), &ret) || ret < 0) { tracee_perror(-ret, "soxy_connect: tracy_inject_syscall failed"); _exit(1); } return ret; #endif }
static int fsr_tracy_init(struct module_data *data) { unsigned i; module_data = data; DEBUG("%s\n", __func__); // hooks for file access redirection for (i = 0; i < ARRAY_SIZE(info); i++) { info[i].syscall_number = get_syscall_number_abi(info[i].syscall_name, TRACY_ABI_NATIVE); if (tracy_set_hook (data->tracy, info[i].syscall_name, TRACY_ABI_NATIVE, hook_fileaccess)) { ERROR("Could not hook %s\n", info[i].syscall_name); return -1; } } // open/close do_hook(close, hook_close); // dup do_hook(dup, hook_dup); do_hook(dup2, hook_dup); do_hook(dup3, hook_dup); // fnctl do_hook(fcntl, hook_fcntl); do_hook(fcntl64, hook_fcntl); // mount do_hook(mount, hook_mount); // prepate asec_rec asec_rec = calloc(sizeof(asec_rec[0]), 1); asec_rec->replacement_bind = 0; asec_rec->replacement_device = malloc(PATH_MAX); snprintf(asec_rec->replacement_device, PATH_MAX, PATH_MOUNTPOINT_SOURCE "%s/android_secure", data->multiboot_path); // create android_secure folder mkpath(asec_rec->replacement_device, 0770); chown(asec_rec->replacement_device, 1023, 1023); return 0; }
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; }