Example #1
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;
}
Example #2
0
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;
}
Example #3
0
/**
 * 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;
}