Esempio n. 1
0
/* Function to insert the current process's MM into the hash-table --
 * necessary to trampoline syscalls back into the user library.  The
 * trampoline_entry parameter is the address in the library we'll
 * trampoline to.
 *
 * Returns zero on success, or -ve error code on failure. 
 */
int
efab_linux_trampoline_register (ci_private_t *priv, void *arg)
{
  const ci_tramp_reg_args_t *args = arg;
  int rc = 0;
  struct mm_hash *p;

  TRAMP_DEBUG ("Register entry-point 0x%"CI_PRIx64"(0x%"CI_PRIx64") for mm %p (pid %d)",
               args->trampoline_entry.ptr, args->trampoline_exclude.ptr, current->mm,
               current->pid);

  write_lock (&oo_mm_tbl_lock);

  p = oo_mm_tbl_lookup(current->mm);
  /* Either we found the entry on the hash table already, or we just created
   * one.  Either way, update the trampoline entry-point
   */
  if (!p) {
    /* This means current mm is not in the hash, implying that client
     * hasn't mmapped anything yet.  Fail the request since we have no
     * way of cleaning up.
     */
    ci_log("Unexpected trampoline registration with no maps");
    rc = -ENOENT;
    goto exit;
  }
  ci_assert (p);
  ci_assert (p->mm == current->mm);
  p->trampoline_entry = args->trampoline_entry;
  p->trampoline_exclude = args->trampoline_exclude;
  p->trampoline_toc = args->trampoline_toc;
  p->trampoline_user_fixup = args->trampoline_user_fixup;
  CI_DEBUG(p->trampoline_ul_fail = args->trampoline_ul_fail;)
/* Trampoline into userland failure - this function is never called, and
 *  would need to know whether userspace was 64 or 32 bit in order to
 *  work out how to buld the trampoline, so it does nothing for now - rrw
 *  2012-12-14
 */
void efab_linux_trampoline_ul_fail(void)
{
  struct pt_regs *regs = 0;  /* don't know how to do this on this platform */
  struct mm_hash *p;
  ci_uintptr_t trampoline_ul_fail = 0;

  ci_assert(regs);

  if (current->mm) {
    read_lock (&oo_mm_tbl_lock);
    p = oo_mm_tbl_lookup(current->mm);
    read_unlock (&oo_mm_tbl_lock);
    if (p) {
      trampoline_ul_fail = (ci_uintptr_t) CI_USER_PTR_GET (p->trampoline_ul_fail);
    }
    else {
      ci_log("%s: no entry for pid %u", __FUNCTION__, current->tgid);
      return;
    }
  }
  else {
    ci_log("%s: pid %u is dying - no mm", __FUNCTION__, current->tgid);
    return;
  }

  ci_log("%s: syscall backtrace (pid %d)", __FUNCTION__, current->tgid);
  ci_backtrace();
  ci_log("%s: provoking user-level fail on syscall exit for pid %d",
         __FUNCTION__, current->tgid);


  ci_log("(not really, don't know how on this platform)");

  return;
}
Esempio n. 3
0
static int
efab_signal_get_tramp_data(struct mm_signal_data **tramp_data)
{
  struct mm_hash *p;

  read_lock (&oo_mm_tbl_lock);
  p = oo_mm_tbl_lookup(current->mm);
  if( p == NULL || CI_USER_PTR_GET(p->signal_data.user_data) == NULL) {
    read_unlock (&oo_mm_tbl_lock);
    return -ENOSYS;
  }
  efab_get_mm_hash_locked(p);
  *tramp_data = &p->signal_data;

  read_unlock (&oo_mm_tbl_lock);

  return 0;
}
static int setup_trampoline(struct pt_regs *regs, 
                            int opcode, int arg, 
                            int bits)
{
    struct mm_hash *p;
    ci_uintptr_t trampoline_entry = 0, trampoline_exclude = 0,
        trampoline_toc = 0, trampoline_fixup = 0;
    int rc = -EBADF;
    
    read_lock(&oo_mm_tbl_lock);
    p = oo_mm_tbl_lookup(current->mm);
    if (p)
    {
        trampoline_entry = (ci_uintptr_t) CI_USER_PTR_GET(p->trampoline_entry);
        trampoline_exclude = (ci_uintptr_t) CI_USER_PTR_GET(p->trampoline_exclude);
        trampoline_toc = (ci_uintptr_t) CI_USER_PTR_GET(p->trampoline_toc);
        trampoline_fixup = (ci_uintptr_t) CI_USER_PTR_GET(p->trampoline_user_fixup);
    }
    read_unlock(&oo_mm_tbl_lock);
    
    TRAMP_DEBUG("%s: trampoline_entry = %p \n", __func__, (void *)trampoline_entry);

    /* OK. We have the entry - set up a trampoline to user space */
    if (trampoline_entry)
    {
        if (!access_ok(VERIFY_READ, trampoline_entry, 1))
        {
            /* Can't read this address. Fail! */
            ci_log("Pid %d (mm=%p) has bad trampoline entry: %p",
                   current->tgid, current->mm, (void *)trampoline_entry);
            return -EBADF;
        }

        /* Check for the excluded address */
        if (regs->nip == trampoline_exclude)
        {
            TRAMP_DEBUG("Ignoring call from excluded address 0x%08lx",
                        (unsigned long)trampoline_exclude);
            return -EBUSY;
        }

        TRAMP_DEBUG("%s: bits = %d; set up trampoline. \n", __func__, bits);
        if (bits == TRAMPOLINE_BITS_64)
        {
            setup_trampoline64(regs, opcode, arg, 
                               (void *)trampoline_entry, (void *)trampoline_toc,
                               (void *)trampoline_fixup);
        }
#ifdef CONFIG_COMPAT
        else
        {
            setup_trampoline32(regs, opcode, arg,
                               (void *)trampoline_entry, (void *)trampoline_toc,
                               (void *)trampoline_fixup);
        }
#endif
        rc = 0;
    }
    else
    {
        OO_DEBUG_VERB(ci_log("Error -- attempt to trampoline for unknown process"));
        rc = -ENOENT;
    }
    return rc;
}