Example #1
0
/*
 * NaClAllocatePow2AlignedMemory is for allocating a large amount of
 * memory of mem_sz bytes that must be address aligned, so that
 * log_alignment low-order address bits must be zero.
 *
 * Returns the aligned region on success, or NULL on failure.
 */
static void *NaClAllocatePow2AlignedMemory(size_t mem_sz, size_t log_alignment)
{
  uintptr_t pow2align;
  size_t request_sz;
  void *mem_ptr;
  uintptr_t orig_addr;
  uintptr_t rounded_addr;
  size_t extra;

  pow2align = ((uintptr_t)1) << log_alignment;
  request_sz = mem_sz + pow2align;
  ZLOGS(LOG_INSANE, "%25s %016lx", " Ask:", request_sz);

  /* d'b: try to get the fixed address r15 (user base register) */
  /*
   * WARNING: mmap can overwrite the zerovm dynamically linked code.
   * to prevent it the code should be linked statically
   */
  mem_ptr = mmap(R15_CONST, request_sz, PROT_NONE, ABSOLUTE_MMAP, -1, (off_t)0);
  if(MAP_FAILED == mem_ptr)
  {
    ZLOG(LOG_ERROR, "the base register absolute address allocation failed!"
        " trying to allocate user space in NOT DETERMINISTIC WAY");
    mem_ptr = mmap(NULL, request_sz, PROT_NONE, RELATIVE_MMAP, -1, (off_t)0);
    ZLOGFAIL(MAP_FAILED == mem_ptr, ENOMEM, FAILED_MSG);
  }

  orig_addr = (uintptr_t)mem_ptr;
  ZLOGS(LOG_INSANE, "%25s %016lx", "orig memory at", orig_addr);

  rounded_addr = (orig_addr + (pow2align - 1)) & ~(pow2align - 1);
  extra = rounded_addr - orig_addr;
  if(0 != extra)
  {
    ZLOGS(LOG_INSANE, "%25s %016lx, %016lx", "Freeing front:", orig_addr, extra);
    ZLOGFAIL(-1 == munmap((void *)orig_addr, extra), errno, "munmap front failed");
  }

  extra = pow2align - extra;
  if(0 != extra)
  {
    ZLOGS(LOG_INSANE, "%25s %016lx, %016lx", "Freeing tail:", rounded_addr + mem_sz, extra);
    ZLOGFAIL(-1 == munmap((void *)(rounded_addr + mem_sz), extra), errno, "munmap tail failed");
  }

  ZLOGS(LOG_INSANE, "%25s %016lx", "Aligned memory:", rounded_addr);

  /*
   * we could also mmap again at rounded_addr w/o MAP_NORESERVE etc to
   * ensure that we have the memory, but that's better done in another
   * utility function.  the semantics here is no paging space
   * reserved, as in Windows MEM_RESERVE without MEM_COMMIT.
   */

  return (void *)rounded_addr;
}
Example #2
0
/*
 * read specified amount of bytes from given desc/offset to buffer
 * return amount of read bytes or negative error code if call failed
 */
static int32_t ZVMReadHandle(struct NaClApp *nap,
    int ch, char *buffer, int32_t size, int64_t offset)
{
  struct ChannelDesc *channel;
  int64_t tail;
  char *sys_buffer;

  assert(nap != NULL);
  assert(nap->manifest != NULL);
  assert(nap->manifest->channels != NULL);

  /* check the channel number */
  if(ch < 0 || ch >= nap->manifest->channels->len)
  {
    ZLOGS(LOG_DEBUG, "channel_id=%d, buffer=%p, size=%d, offset=%ld",
        ch, buffer, size, offset);
    return -EINVAL;
  }
  channel = CH_CH(nap->manifest, ch);
  ZLOGS(LOG_INSANE, "channel %s, buffer=%p, size=%d, offset=%ld",
      channel->alias, buffer, size, offset);

  /* check buffer and convert address */
  if(CheckRAMAccess(nap, (uintptr_t)buffer, size, PROT_WRITE) == -1) return -EINVAL;
  sys_buffer = (char*)NaClUserToSys(nap, (uintptr_t)buffer);

  /* ignore user offset for sequential access read */
  if(CH_SEQ_READABLE(channel))
    offset = channel->getpos;
  else
  /* prevent reading beyond the end of the random access channels */
    size = MIN(channel->size - offset, size);

  /* check arguments sanity */
  if(size == 0) return 0; /* success. user has read 0 bytes */
  if(size < 0) return -EFAULT;
  if(offset < 0) return -EINVAL;

  /* check for eof */
  if(channel->eof) return 0;

  /* check limits */
  if(channel->counters[GetsLimit] >= channel->limits[GetsLimit])
    return -EDQUOT;
  if(CH_RND_READABLE(channel))
    if(offset >= channel->limits[PutSizeLimit] - channel->counters[PutSizeLimit]
      + channel->size) return -EINVAL;

  /* calculate i/o leftovers */
  tail = channel->limits[GetSizeLimit] - channel->counters[GetSizeLimit];
  if(size > tail) size = tail;
  if(size < 1) return -EDQUOT;

  /* read data */
  return ChannelRead(channel, sys_buffer, (size_t)size, (off_t)offset);
}
Example #3
0
File: trap.c Project: Abioy/zerovm
int32_t TrapHandler(struct NaClApp *nap, uint32_t args)
{
  uint64_t *sargs;
  int retcode = 0;
  int i;

  assert(nap != NULL);
  assert(nap->manifest != NULL);

  /*
   * translate address from user space to system
   * note: cannot set "trap error"
   */
  sargs = (uint64_t*)NaClUserToSys(nap, (uintptr_t)args);
  i = FunctionIndexById(*sargs);
  ZLOGS(LOG_DEBUG, "%s called", function[i]);
  ZTrace("untrusted code");

  switch(*sargs)
  {
    case TrapFork:
      if(Daemon(nap) == 0)
      {
        SyscallZTrace(5, function[5]);
        ZVMExitHandle(nap, 0);
      }
      break;
    case TrapExit:
      ZVMExitHandle(nap, (int32_t)sargs[2]);
      break;
    case TrapRead:
      retcode = ZVMReadHandle(nap,
          (int)sargs[2], (char*)sargs[3], (int32_t)sargs[4], sargs[5]);
      break;
    case TrapWrite:
      retcode = ZVMWriteHandle(nap,
          (int)sargs[2], (char*)sargs[3], (int32_t)sargs[4], sargs[5]);
      break;
    case TrapJail:
      retcode = ZVMJailHandle(nap, (uint32_t)sargs[2], (int32_t)sargs[3]);
      break;
    case TrapUnjail:
      retcode = ZVMUnjailHandle(nap, (uint32_t)sargs[2], (int32_t)sargs[3]);
      break;
    default:
      retcode = -EPERM;
      ZLOG(LOG_ERROR, "function %ld is not supported", *sargs);
      break;
  }

  /* report, ztrace and return */
  FastReport();
  ZLOGS(LOG_DEBUG, "%s returned %d", function[i], retcode);
  SyscallZTrace(i, function[i], sargs[2], sargs[3], sargs[4], sargs[5], retcode);
  return retcode;
}
Example #4
0
void ElfImageLoad(const struct ElfImage *image,
    struct Gio *gp, uint8_t addr_bits, uintptr_t mem_start)
{
  int               segnum;
  uintptr_t         paddr;
  uintptr_t         end_vaddr;

  for(segnum = 0; segnum < image->ehdr.e_phnum; ++segnum)
  {
    const Elf_Phdr *php = &image->phdrs[segnum];

    /* did we decide that we will load this segment earlier? */
    if(!image->loadable[segnum]) continue;

    ZLOGS(LOG_INSANE, "loading segment %d", segnum);

    if(0 == php->p_filesz)
    {
      ZLOGS(LOG_INSANE, "zero-sized segment. ignoring...");
      continue;
    }
    end_vaddr = php->p_vaddr + php->p_filesz;

    /* integer overflow? */
    ZLOGFAIL(end_vaddr < php->p_vaddr, EFAULT,
        "parameter error should have been detected already");

    /*
     * is the end virtual address within the NaCl application's
     * address space?  if it is, it implies that the start virtual
     * address is also.
     */
    ZLOGFAIL(end_vaddr >= ((uintptr_t)1U << addr_bits), EFAULT,
        "parameter error should have been detected already");

    paddr = mem_start + php->p_vaddr;

    ZLOGS(LOG_INSANE, "Seek to position %d (0x%x)", php->p_offset, php->p_offset);

    /*
     * NB: php->p_offset may not be a valid off_t on 64-bit systems, but
     * in that case Seek() will error out.
     * d'b: fail if ELF executable segment header parameter error
     */
    ZLOGFAIL((*gp->vtbl->Seek)(gp, (off_t)php->p_offset, SEEK_SET) == (off_t)-1,
        ENOEXEC, "seek failure segment %d", segnum);

    ZLOGS(LOG_INSANE, "Reading %d (0x%x) bytes to address 0x%x",
        php->p_filesz, php->p_filesz, paddr);

    ZLOGFAIL((Elf_Word)(*gp->vtbl->Read)(gp, (void *)paddr, php->p_filesz) != php->p_filesz,
        ENOEXEC, "load failure segment %d", segnum);
    /* region from p_filesz to p_memsz should already be zero filled */
  }
}
Example #5
0
/* log user memory map */
static void LogMemMap(struct NaClApp *nap, int verbosity)
{
    int i;

    ZLOGS(verbosity, "user memory map (in pages):");

    for(i = 0; i < MemMapSize; ++i)
        ZLOGS(verbosity, "%s: address = 0x%08x, size = 0x%08x, protection = x",
              nap->mem_map[i].name, (uint32_t) nap->mem_map[i].start,
              (uint32_t) nap->mem_map[i].size, nap->mem_map[i].prot);
}
Example #6
0
/*
 * "One Ring" syscall main routine. the nacl syscalls replacement.
 * "args" is an array of syscall name and its arguments
 * note: since nacl patch two 1st arguments if they are pointers, arg[1] are not used
 * todo(d'b): check how nacl decide to patch arguments.
 */
int32_t TrapHandler(struct NaClApp *nap, uint32_t args)
{
  uint64_t *sys_args;
  int retcode = 0;

  assert(nap != NULL);
  assert(nap->system_manifest != NULL);

  /*
   * translate address from user space to system
   * note: cannot set "trap error"
   */
  sys_args = (uint64_t*)NaClUserToSys(nap, (uintptr_t) args);
  ZLOGS(LOG_DEBUG, "%s called", FunctionNameById(sys_args[0]));

  switch(*sys_args)
  {
    case TrapExit:
      retcode = ZVMExitHandle(nap, (int32_t) sys_args[2]);
      break;
    case TrapRead:
      retcode = ZVMReadHandle(nap,
          (int)sys_args[2], (char*)sys_args[3], (int32_t)sys_args[4], sys_args[5]);
      break;
    case TrapWrite:
      retcode = ZVMWriteHandle(nap,
          (int)sys_args[2], (char*)sys_args[3], (int32_t)sys_args[4], sys_args[5]);
      break;
    case TrapSyscallback:
      retcode = ZVMSyscallback(nap, (int32_t)sys_args[2]);
      break;
    case TrapChannels:
      retcode = ZVMChannels(nap, (struct ZVMChannel*)sys_args[2]);
      break;
    case TrapChannelName:
      retcode = ZVMChannelName(nap, (struct ZVMChannel*)sys_args[2], (int32_t)sys_args[3]);
      break;
    case TrapHeapEnd:
      retcode = ZVMHeapEnd(nap);
      break;
    case TrapHeapPtr:
      retcode = ZVMHeapPtr(nap);
      break;
    default:
      retcode = -EPERM;
      ZLOG(LOG_ERROR, "function %ld is not supported", *sys_args);
      break;
  }

  ZLOGS(LOG_DEBUG, "%s returned %d", FunctionNameById(sys_args[0]), retcode);
  return retcode;
}
Example #7
0
void NaClAllocAddrSpace(struct NaClApp *nap)
{
  void        *mem;
  uintptr_t   hole_start;
  size_t      hole_size;
  uintptr_t   stack_start;

  ZLOGS(LOG_DEBUG, "calling NaClAllocateSpace(*,0x%016x)", ((size_t)1 << nap->addr_bits));
  NaClAllocateSpace(&mem, (uintptr_t) 1U << nap->addr_bits);

  nap->mem_start = (uintptr_t) mem;
  ZLOGS(LOG_DEBUG, "allocated memory at 0x%08x", nap->mem_start);

  hole_start = NaClRoundAllocPage(nap->data_end);

  ZLOGFAIL(nap->stack_size >= ((uintptr_t) 1U) << nap->addr_bits,
      EFAULT, "NaClAllocAddrSpace: stack too large!");
  stack_start = (((uintptr_t) 1U) << nap->addr_bits) - nap->stack_size;
  stack_start = NaClTruncAllocPage(stack_start);

  ZLOGFAIL(stack_start < hole_start, EFAULT,
      "Memory 'hole' between end of BSS and start of stack is negative in size");

  hole_size = stack_start - hole_start;
  hole_size = NaClTruncAllocPage(hole_size);

  /*
   * mprotect and madvise unused data space to "free" it up, but
   * retain mapping so no other memory can be mapped into those
   * addresses.
   */
  if(hole_size != 0)
  {
    ZLOGS(LOG_DEBUG, "madvising 0x%08x, 0x%08x, MADV_DONTNEED",
        nap->mem_start + hole_start, hole_size);

    ZLOGFAIL(0 != NaCl_madvise((void*)(nap->mem_start + hole_start), hole_size,
        MADV_DONTNEED), errno, "madvise failed. cannot release unused data segment");

    ZLOGS(LOG_DEBUG, "mprotecting 0x%08x, 0x%08x, PROT_NONE",
        nap->mem_start + hole_start, hole_size);

    ZLOGFAIL(0 != NaCl_mprotect((void *)(nap->mem_start + hole_start), hole_size,
        PROT_NONE), errno, "mprotect failed. cannot protect pages");
  }
  else
    ZLOGS(LOG_DEBUG, "there is no hole between end of data and the beginning of stack");
}
Example #8
0
/*
 * write specified amount of bytes from buffer to given desc/offset
 * return amount of read bytes or negative error code if call failed
 */
static int32_t ZVMWriteHandle(struct NaClApp *nap,
    int ch, const char *buffer, int32_t size, int64_t offset)
{
  struct ChannelDesc *channel;
  int64_t tail;
  const char *sys_buffer;

  assert(nap != NULL);
  assert(nap->manifest != NULL);
  assert(nap->manifest->channels != NULL);

  /* check the channel number */
  if(ch < 0 || ch >= nap->manifest->channels->len)
  {
    ZLOGS(LOG_DEBUG, "channel_id=%d, buffer=%p, size=%d, offset=%ld",
        ch, buffer, size, offset);
    return -EINVAL;
  }
  channel = CH_CH(nap->manifest, ch);
  ZLOGS(LOG_INSANE, "channel %s, buffer=%p, size=%d, offset=%ld",
      channel->alias, buffer, size, offset);

  /* check buffer and convert address */
  if(CheckRAMAccess(nap, (uintptr_t)buffer, size, PROT_READ) == -1) return -EINVAL;
  sys_buffer = (char*)NaClUserToSys(nap, (uintptr_t) buffer);

  /* ignore user offset for sequential access write */
  if(CH_SEQ_WRITEABLE(channel)) offset = channel->putpos;

  /* check arguments sanity */
  if(size == 0) return 0; /* success. user has read 0 bytes */
  if(size < 0) return -EFAULT;
  if(offset < 0) return -EINVAL;

  /* check limits */
  if(channel->counters[PutsLimit] >= channel->limits[PutsLimit])
    return -EDQUOT;
  tail = channel->limits[PutSizeLimit] - channel->counters[PutSizeLimit];
  if(offset >= channel->limits[PutSizeLimit] &&
      !((CH_RW_TYPE(channel) & 1) == 1)) return -EINVAL;

  if(offset >= channel->size + tail) return -EINVAL;
  if(size > tail) size = tail;
  if(size < 1) return -EDQUOT;

  /* write data */
  return ChannelWrite(channel, sys_buffer, (size_t)size, (off_t)offset);
}
Example #9
0
NORETURN void CreateSession(struct NaClApp *nap)
{
  uintptr_t stack_ptr;

  assert(nap != NULL);

  /* set up user stack */
  stack_ptr = nap->mem_start + ((uintptr_t)1U << nap->addr_bits);
  stack_ptr -= STACK_USER_DATA_SIZE;
  memset((void*)stack_ptr, 0, STACK_USER_DATA_SIZE);
  ((uint32_t*)stack_ptr)[4] = 1;
  ((uint32_t*)stack_ptr)[5] = 0xfffffff0;

  /* construct "nacl_user" global */
  ThreadContextCtor(nacl_user, nap, nap->initial_entry_pt, stack_ptr, 0);
  nacl_user->sysret = nap->break_addr;
  nacl_user->prog_ctr = NaClUserToSys(nap, nap->initial_entry_pt);
  nacl_user->new_prog_ctr = NaClUserToSys(nap, nap->initial_entry_pt);

  /* initialize "nacl_sys" global */
  nacl_sys->rbp = GetStackPtr();
  nacl_sys->rsp = GetStackPtr();

  /* pass control to the user side */
  ZLOGS(LOG_DEBUG, "SESSION %d STARTED", nap->manifest->node);
  SwitchToApp(nap, nacl_user->new_prog_ctr);
  ZLOGFAIL(1, EFAULT, "the unreachable has been reached");
}
Example #10
0
/* part of report class dtor */
static void Report(struct NaClApp *nap)
{
  GString *report = g_string_sized_new(BIG_ENOUGH_STRING);
  char *eol = hide_report ? "; " : "\n";

  /* report validator state and user return code */
  g_string_append_printf(report, "%s%d%s", REPORT_VALIDATOR, validation_state, eol);
  g_string_append_printf(report, "%s%d%s", REPORT_RETCODE, user_code, eol);

  /* add memory digest to cumulative digests if asked */
  if(nap != NULL && nap->manifest != NULL)
    if(nap->manifest->mem_tag != NULL)
      ReportTag(STDRAM, GetMemoryDigest(nap));

  /* report tags digests and remove ending " " if exist */
  g_string_append_printf(report, "%s", REPORT_ETAG);
  g_string_append_printf(report, "%s", digests->len == 0
      ? TAG_ENGINE_DISABLED : digests->str);
  g_string_truncate(report, report->len - 1);

  /* report accounting and session message */
  g_string_append_printf(report, "%s%s%s%s", eol, REPORT_ACCOUNTING, GetAccountingInfo(), eol);
  g_string_append_printf(report, "%s%s%s", REPORT_STATE, zvm_state, eol);

  /* output report */
  if(hide_report)
    ZLOGS(LOG_ERROR, "%s", report->str);
  else
    ZLOGIF(write(STDOUT_FILENO, report->str, report->len) != report->len,
        "report write error %d: %s", errno, strerror(errno));

  g_string_free(report, TRUE);
  g_string_free(digests, TRUE);
}
Example #11
0
File: sel.c Project: Abioy/zerovm
NORETURN void CreateSession(struct NaClApp *nap)
{
  uintptr_t stack_ptr;

  assert(nap != NULL);

  /* set up user stack */
  stack_ptr = nap->mem_start + ((uintptr_t)1U << nap->addr_bits);
  stack_ptr -= STACK_USER_DATA_SIZE;
  memset((void*)stack_ptr, 0, STACK_USER_DATA_SIZE);
  ((uint32_t*)stack_ptr)[4] = 1;
  ((uint32_t*)stack_ptr)[5] = 0xfffffff0;

  /*
   * construct "nacl_user" and "nacl_sys" globals
   * note: nacl_sys->prog_ctr meaningless but should not be 0
   */
  ThreadContextCtor(nacl_user, nap, nap->initial_entry_pt, stack_ptr);
  ThreadContextCtor(nacl_sys, nap, 1, GetStackPtr());

  /* pass control to the user side */
  ZLOGS(LOG_DEBUG, "SESSION %d STARTED", nap->manifest->node);
  ContextSwitch(nacl_user);
  ZLOGFAIL(1, EFAULT, "the unreachable has been reached");
}
Example #12
0
int PreloadChannelDtor(struct ChannelDesc *channel, int n)
{
  int code = 0;
  int handle;

  assert(channel != NULL);
  assert(n < channel->source->len);

  /* adjust the size of writable channels */
  handle = GPOINTER_TO_INT(CH_HANDLE(channel, n));
  if(channel->limits[PutSizeLimit] && channel->limits[PutsLimit]
     && CH_PROTO(channel, n) == ProtoRegular)
    code = ftruncate(handle, channel->size);

  ZLOGS(LOG_DEBUG,
      "%s closed with getsize = %ld, putsize = %ld", channel->alias,
      channel->counters[GetSizeLimit], channel->counters[PutSizeLimit]);

  if(handle != 0)
  {
    if(CH_PROTO(channel, n) == ProtoRegular)
      close(handle);
    else
      fclose(CH_HANDLE(channel, n));
  }

  g_ptr_array_remove(channel->source, CH_FILE(channel, n));
  return -(code != 0);
}
Example #13
0
void PreloadChannelCtor(struct ChannelDesc *channel, int n)
{
  assert(channel != NULL);
  assert(n < channel->source->len);

  /* check the given channel */
  ZLOGS(LOG_DEBUG, "mounting file %s to alias %s",
      CH_NAME(channel, n), channel->alias);

  SetChannelSource(channel, n);

  switch(CH_PROTO(channel, n))
  {
    case ProtoRegular:
      RegularChannel(channel, n);
      break;
    case ProtoCharacter:
    case ProtoFIFO:
      CharacterChannel(channel, n);
      break;
    default:
      ZLOGFAIL(1, EPROTONOSUPPORT, "invalid %s source type %d",
          channel->alias, channel->type);
      break;
  }
}
Example #14
0
void ReportDtor(int zvm_ret)
{
  SetExitCode(zvm_ret);

  /*
   * patch to show special messages instead of signals 24, 25
   * and do not calculate etag if session failed
   */
  if(zvm_code != 0)
  {
    SpecSignals();
    ZLOGS(LOG_ERROR, "SESSION %d FAILED WITH ERROR %d: %s",
        gnap->manifest == NULL ? 0 : gnap->manifest->node,
        zvm_code, strerror(zvm_code));
  }

  if(zvm_code != 0) FinalDump(gnap);

  AccountingDtor(gnap);
  ChannelsDtor(gnap->manifest);
  Report(gnap);
  NaClAppDtor(gnap); /* free user space and globals */
  ManifestDtor(gnap->manifest); /* dispose manifest and channels */
  FreeDispatchThunk();
  ZLogDtor();

  _exit(zvm_code);
}
Example #15
0
/* sets node_id in nap object and user argv[0] */
static void SetNodeName(struct NaClApp *nap)
{
  int i;
  char *buf[BIG_ENOUGH_SPACE], **tokens = buf;
  char *pgm_name = GetValueByKey(MFT_NODE);

  assert(nap != NULL);
  assert(nap->system_manifest != NULL);
  assert(nap->system_manifest->cmd_line != NULL);
  assert(nap->system_manifest->cmd_line_size > 0);

  /* set the node name (0st parameter) and node id (n/a for the user) */
  if(pgm_name == NULL)
  {
    nap->system_manifest->cmd_line[0] = NEXE_PGM_NAME;
    nap->system_manifest->node_id = 0;
  }
  else
  {
    i = ParseValue(pgm_name, ",", tokens, BIG_ENOUGH_SPACE);
    ZLOGFAIL(i != 2, EFAULT, "invalid NodeName specified");
    ZLOGFAIL(tokens[0] == NULL, EFAULT, "invalid node name");
    ZLOGFAIL(tokens[1] == NULL, EFAULT, "invalid node id");
    nap->system_manifest->cmd_line[0] = tokens[0];
    nap->system_manifest->node_id = ATOI(tokens[1]);
    ZLOGFAIL(nap->system_manifest->node_id == 0, EFAULT, "node id must be > 0");
  }

  /* put node name and id to the log */
  ZLOGS(LOG_DEBUG, "node name = %s, node id = %d",
      nap->system_manifest->cmd_line[0], nap->system_manifest->node_id);
}
Example #16
0
/* TODO(d'b): rework "-t" and update the function */
static void OutputReport(char *r)
{
    char *p = NULL;
    int size = strlen(r);

#define REPORT(p) ZLOGIF(write(report_handle, p, size) != size, \
  "report write error %d: %s", errno, strerror(errno))

    switch(report_mode)
    {
    case 3: /* unix socket */
        p = g_strdup_printf("0x%06x%s", size, r);
        size = strlen(p);
        REPORT(p);
        g_free(p);
        break;
    case 0: /* stdout */
        REPORT(r);
        break;
    case 1: /* syslog */
        ZLOGS(LOG_ERROR, "%s", r);
        break;
    default:
        ZLOG(LOG_ERROR, "invalid report mode %d", report_mode);
        break;
    }
#undef REPORT
}
Example #17
0
File: sel.c Project: Abioy/zerovm
/*
 * Fill from static_text_end to end of that page with halt
 * instruction, which is at least NACL_HALT_LEN in size when no
 * dynamic text is present.  Does not touch dynamic text region, which
 * should be pre-filled with HLTs.
 *
 * By adding NACL_HALT_SLED_SIZE, we ensure that the code region ends
 * with HLTs, just in case the CPU has a bug in which it fails to
 * check for running off the end of the x86 code segment.
 */
void static FillEndOfTextRegion(struct NaClApp *nap)
{
  size_t page_pad;

  /*
   * NOTE: make sure we are not silently overwriting data.  It is the
   * toolchain's responsibility to ensure that a NACL_HALT_SLED_SIZE
   * gap exists.
   */
  ZLOGFAIL(0 != nap->data_start && nap->static_text_end
      + NACL_HALT_SLED_SIZE > nap->data_start, EFAULT,
      "Missing gap between text and data for halt_sled");

  ZLOGFAIL(0 != nap->rodata_start && nap->static_text_end
      + NACL_HALT_SLED_SIZE > nap->rodata_start, EFAULT,
      "Missing gap between text and rodata for halt_sled");

  /* No dynamic text exists.  Space for NACL_HALT_SLED_SIZE must exist */
  page_pad = ROUNDUP_64K(nap->static_text_end + NACL_HALT_SLED_SIZE)
      - nap->static_text_end;
  ZLOGFAIL(page_pad < NACL_HALT_SLED_SIZE, EFAULT, FAILED_MSG);
  ZLOGFAIL(page_pad >= NACL_MAP_PAGESIZE + NACL_HALT_SLED_SIZE, EFAULT, FAILED_MSG);

  ZLOGS(LOG_INSANE, "Filling with halts: %08lx, %08lx bytes",
          nap->mem_start + nap->static_text_end, page_pad);

  FillMemoryRegionWithHalt((void*)(nap->mem_start + nap->static_text_end), page_pad);
  nap->static_text_end += page_pad;
}
Example #18
0
void  NaClLoadTrampoline(struct NaClApp *nap) {
  int         num_syscalls;
  int         i;
  uintptr_t   addr;

  ZLOGFAIL(!NaClMakeDispatchThunk(nap), EFAULT, FAILED_MSG);
  NaClFillTrampolineRegion(nap);

  /*
   * Do not bother to fill in the contents of page 0, since we make it
   * inaccessible later (see sel_addrspace.c, NaClMemoryProtection)
   * anyway to help detect NULL pointer errors, and we might as well
   * not dirty the page.
   *
   * The last syscall entry point is reserved (nacl springboard code)
   */
  num_syscalls = ((NACL_TRAMPOLINE_END - NACL_SYSCALL_START_ADDR) / NACL_SYSCALL_BLOCK_SIZE) - 1;
  ZLOGS(LOG_INSANE, "num_syscalls = %d (0x%x)", num_syscalls, num_syscalls);

  addr = nap->mem_start + NACL_SYSCALL_START_ADDR;
  for (i = 0; i < num_syscalls; ++i)
  {
    NaClPatchOneTrampoline(nap, addr);
    addr += NACL_SYSCALL_BLOCK_SIZE;
  }
}
Example #19
0
static void FinalDump(struct NaClApp *nap)
{
    ZLOGS(LOG_INSANE, "exiting -- printing NaClApp details");
    PrintAppDetails(nap, LOG_INSANE);
    LogMemMap(nap, LOG_INSANE);

    SignalHandlerFini();
}
Example #20
0
void NaClInitSwitchToApp(struct NaClApp *nap)
{
  int cpu = CPUTest();

  UNREFERENCED_PARAMETER(nap);
  ZLOGFAIL(cpu == -1, EFAULT, "zerovm needs SSE CPU");
  NaClSwitch = cpu == 0 ? NaClSwitchSSE : NaClSwitchAVX;
  ZLOGS(LOG_DEBUG, "%s cpu detected", cpu == 0 ? "SSE" : "AVX");
}
/* d'b: duplicate of trap() exit. remove it when trap() replace syscalls */
int32_t NaClSysExit(struct NaClApp *nap, int status)
{
  ZLOGS(LOG_DEBUG, "Exit syscall handler: %d", status);
  nap->system_manifest->user_ret_code = status;
  longjmp(user_exit, status);

  /* NOTREACHED */
  return -EINVAL;
}
/* tls create */
int32_t NaClSysTls_Init(struct NaClApp *nap, void *thread_ptr)
{
  uintptr_t sys_tls;

  ZLOGS(LOG_DEBUG, "tls init with 0x%08lx", (uintptr_t)thread_ptr);

  /*
   * Verify that the address in the app's range and translated from
   * nacl module address to service runtime address - a nop on ARM
   */
  sys_tls = NaClUserToSysAddrRange(nap, (uintptr_t) thread_ptr, 4);
  ZLOGS(LOG_INSANE, "thread_ptr 0x%p, sys_tls 0x%lx", thread_ptr, sys_tls);

  if(kNaClBadAddress == sys_tls) return -EFAULT;

  nap->sys_tls = sys_tls;
  return 0;
}
Example #23
0
/* user exit. invokes long jump to main(). uses global var */
static int32_t ZVMExitHandle(struct NaClApp *nap, int32_t code)
{
  assert(nap != NULL);
  nap->system_manifest->user_ret_code = code;
  ZLOGS(LOG_DEBUG, "Exit syscall handler: %d", code);
  longjmp(user_exit, code);

  return code; /* prevent compiler warning. not reached */
}
Example #24
0
/* user exit. session is finished */
static void ZVMExitHandle(struct NaClApp *nap, int32_t code)
{
  assert(nap != NULL);

  SetUserCode(code);
  if(GetExitCode() == 0)
    SetExitState(OK_STATE);
  ZLOGS(LOG_DEBUG, "SESSION %d RETURNED %d", nap->manifest->node, code);
  ReportDtor(0);
}
Example #25
0
static void FinalDump(struct NaClApp *nap)
{
  ZLOGS(LOG_INSANE, "exiting -- printing NaClApp details");

  /* NULL can be used because syslog used for nacl log */
  PrintAppDetails(nap, (struct Gio *) NULL, LOG_INSANE);
  LogMemMap(nap, LOG_INSANE);

  SignalHandlerFini();
}
Example #26
0
/* user exit. session is finished */
static int32_t ZVMExitHandle(struct NaClApp *nap, int32_t code)
{
  assert(nap != NULL);

  nap->system_manifest->user_ret_code = code;
  ZLOGS(LOG_DEBUG, "SESSION RETURNED %d", code);
  SetExitState(OK_STATE);
  NaClExit(0);

  return 0; /* unreachable */
}
Example #27
0
/*
 * Platform-specific routine to allocate memory space for the NaCl
 * module.  mem is an out argument; addrsp_size is the requested
 * address space size, currently always ((size_t) 1) <<
 * nap->addr_bits.  On x86-64, there's a further requirement that this
 * is 4G.
 *
 * The actual amount of memory allocated is larger than requested on
 * x86-64 and on the ARM, since guard pages are also allocated to be
 * contiguous with the allocated address space.
 *
 * If successful, the guard pages are not yet memory protected.  The
 * function NaClMprotectGuards must be called for the guard pages to
 * be active.
 *
 * update: abort zvm if failed
 */
static void NaClAllocateSpace(void **mem, size_t addrsp_size)
{
  size_t mem_sz = 2 * GUARDSIZE + FOURGIG; /* 40G guard on each side */
  size_t log_align = ALIGN_BITS;
  void *mem_ptr;

  ZLOGS(LOG_INSANE, "NaClAllocateSpace(*, 0x%016lx bytes)", addrsp_size);
  ZLOGFAIL(addrsp_size != FOURGIG, EFAULT, "addrsp_size != FOURGIG");

  errno = 0;
  mem_ptr = NaClAllocatePow2AlignedMemory(mem_sz, log_align);
  ZLOGFAIL(NULL == mem_ptr, errno, "NaClAllocatePow2AlignedMemory failed");

  /*
   * The module lives in the middle FOURGIG of the allocated region --
   * we skip over an initial 40G guard.
   */
  *mem = (void *)(((char *)mem_ptr) + GUARDSIZE);
  ZLOGS(LOG_INSANE, "addr space at 0x%016lx", (uintptr_t)*mem);
}
Example #28
0
static void DumpElfHeader(int loglevel, const Elf_Ehdr *elf_hdr)
{
  ZLOGS(loglevel, "%020o (Elf header) %020o", 0, 0);

  DUMP(e_ident+1, ".3s");
  DUMP(e_type, "#x");
  DUMP(e_machine, "#x");
  DUMP(e_version, "#x");
  DUMP(e_entry, "#x");
  DUMP(e_phoff, "#x");
  DUMP(e_shoff, "#x");
  DUMP(e_flags, "#x");
  DUMP(e_ehsize, "#x");
  DUMP(e_phentsize, "#x");
  DUMP(e_phnum, "#x");
  DUMP(e_shentsize, "#x");
  DUMP(e_shnum, "#x");
  DUMP(e_shstrndx, "#x");
  ZLOGS(loglevel, "sizeof(Elf32_Ehdr) = 0x%x", (int) sizeof *elf_hdr);
}
Example #29
0
/* log zerovm command line */
static void ZVMCommandLine(int argc, char **argv)
{
  char cmd[BIG_ENOUGH_SPACE];
  int offset = 0;
  int i;

  offset += sprintf(cmd, "zerovm command line:");
  for(i = 0; i < argc; ++i)
    offset += g_snprintf(cmd + offset, BIG_ENOUGH_SPACE - offset, " %s", argv[i]);

  ZLOGS(LOG_DEBUG, "%s", cmd);
}
Example #30
0
/*
 * bind the given channel using info from netlist
 * returns not 0 if failed
 * note: replaces PrepareBind if no name service available
 */
static int DoBind(const struct ChannelDesc* channel)
{
  struct ChannelConnection *record;
  char buf[BIG_ENOUGH_STRING], *url = buf;

  record = GetChannelConnectionInfo(channel);
  assert(record != NULL);

  MakeURL(url, BIG_ENOUGH_STRING, channel, record);
  ZLOGS(LOG_DEBUG, "bind url %s", url);
  return zmq_bind(channel->socket, url);
}