Ejemplo n.º 1
0
/* helper. sets custom user attributes for user */
static void SetCustomAttributes(struct SystemManifest *policy)
{
  int i;
  int count;
  char *environment;
  char *buf[BIG_ENOUGH_SPACE], **tokens = buf;

  assert(policy != NULL);
  assert(policy->envp == NULL);

  /* get environment */
  environment = GetValueByKey(MFT_ENVIRONMENT);
  if(environment == NULL) return;

  /* parse and check count of attributes */
  count = ParseValue(environment, ", \t", tokens, BIG_ENOUGH_SPACE);
  ZLOGFAIL(count % 2 != 0, EFAULT, "odd number of user environment variables");
  ZLOGFAIL(count == 0, EFAULT, "invalid user environment");
  ZLOGFAIL(count == BIG_ENOUGH_SPACE, EFAULT, "user environment exceeded the limit");

  /* allocate space to hold string pointers */
  count >>= 1;
  policy->envp = g_malloc0((count + 1) * sizeof(*policy->envp));

  /* construct array of environment variables */
  for(i = 0; i < count; ++i)
  {
    char *key = *tokens++;
    char *value = *tokens++;
    int length = strlen(key) + strlen(value) + 1 + 1; /* + '=' + '\0' */

    policy->envp[i] = g_malloc0((length + 1) * sizeof(*policy->envp[0]));
    sprintf(policy->envp[i], "%s=%s", key, value);
  }
}
Ejemplo n.º 2
0
Archivo: sel.c Proyecto: 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;
}
Ejemplo n.º 3
0
/*
 * set validation state according to zvm command line options
 * note: updates nap->validation_state
 */
static void ValidateNexe(struct NaClApp *nap)
{
  char *args[3] = {VALIDATOR_NAME, NULL, NULL};
  GError *error = NULL;
  int exit_status = 0;
  enum ValidationState {
    NotValidated,
    ValidationOK,
    ValidationFailed
  };

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

  /* skip validation? */
  nap->validation_state = NotValidated;
  if(nap->skip_validator != 0) return;

  /* prepare command line and run it */
  args[1] = nap->system_manifest->nexe;
  ZLOGFAIL(g_spawn_sync(NULL, args, NULL, G_SPAWN_SEARCH_PATH |
      G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL,
      NULL, NULL, &exit_status, &error) == 0, EPERM, "cannot start validator");

  /* check the result */
  nap->validation_state = exit_status == 0 ? ValidationOK : ValidationFailed;
  ZLOGFAIL(nap->validation_state != ValidationOK, ENOEXEC, "validation failed");
}
Ejemplo n.º 4
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);
}
Ejemplo n.º 5
0
/* preallocate memory area of given size. abort if fail */
static void PreallocateUserMemory(struct NaClApp *nap)
{
  uintptr_t i;
  int64_t heap;
  void *p;

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

  /* quit function if max_mem is not specified or invalid */
  ZLOGFAIL(nap->heap_end == 0 || nap->heap_end > FOURGIG,
      ENOMEM, "invalid memory size");

  /* calculate user heap size (must be allocated next to the data_end) */
  p = (void*)NaClRoundAllocPage(nap->data_end);
  heap = nap->heap_end - nap->stack_size;
  heap = NaClRoundAllocPage(heap) - NaClRoundAllocPage(nap->data_end);
  ZLOGFAIL(heap <= LEAST_USER_HEAP_SIZE, ENOMEM, "user heap size is too small");

  /* since 4gb of user space is already allocated just set protection to the heap */
  p = (void*)NaClUserToSys(nap, (uintptr_t)p);
  i = NaCl_mprotect(p, heap, PROT_READ | PROT_WRITE);
  ZLOGFAIL(0 != i, -i, "cannot set protection on user heap");
  nap->heap_end = NaClSysToUser(nap, (uintptr_t)p + heap);

  nap->mem_map[HeapIdx].size += heap;
  nap->mem_map[HeapIdx].end += heap;
}
Ejemplo n.º 6
0
/* helper. sets command line parameters for the user */
static void SetCommandLine(struct SystemManifest *policy)
{
  int i;
  char *parameters;
  char *buf[BIG_ENOUGH_SPACE], **tokens = buf;

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

  /* get parameters */
  parameters = GetValueByKey(MFT_COMMANDLINE);

  /* if there is command line parse and check count of parameters */
  if(parameters != NULL)
  {
    policy->cmd_line_size = ParseValue(parameters, " \t", tokens, BIG_ENOUGH_SPACE);
    ZLOGFAIL(policy->cmd_line_size == 0, EFAULT, "invalid user parameters");
    ZLOGFAIL(policy->cmd_line_size == BIG_ENOUGH_SPACE, EFAULT, "too long user command line");
  }

  /*
   * allocate space to hold string pointers. 0st element reserved for argv[0].
   * also, the last element should be NULL so 1 extra element must be reserved
   */
  ++policy->cmd_line_size;
  policy->cmd_line = g_malloc0((policy->cmd_line_size + 1) * sizeof *policy->cmd_line);

  /* populate command line arguments array with pointers */
  for(i = 0; i < policy->cmd_line_size - 1; ++i)
    policy->cmd_line[i + 1] = tokens[i];
}
Ejemplo n.º 7
0
void NameServiceCtor(struct Manifest *manifest, uint32_t b, uint32_t c)
{
  char *parcel;
  uint32_t psize;
  uint32_t control_psize;
  uint32_t control_nsources;

  assert(manifest != NULL);
  assert(manifest->channels != NULL);
  assert(b + c <= MAX_CHANNELS_NUMBER);

  /* return if there is no name service or network sources */
  if(manifest->name_server == NULL) return;
  if(b + c < 1) return;

  /* create parcel */
  ZLOGFAIL(manifest->node < 1, EFAULT, "invalid node: %d", manifest->node);
  ZLOGFAIL(manifest->name_server->protocol != ProtoUDP,
      EFAULT, "name server only support udp protocol");
  parcel = ParcelCtor(manifest, &psize, b, c);

  /* exchange parcels with name server */
  control_psize = PollServer(manifest->name_server, parcel, psize);
  ZLOGFAIL(control_psize != psize, EFAULT,
      "received parcel size %u is not equal to sent one %u",
      control_psize, psize);

  /* decode received parcel to channels */
  control_nsources = ParcelDtor(manifest, parcel);
  ZLOGFAIL(control_nsources != b + c, EFAULT,
      "received parcel records %u is not equal to sent ones %u",
      control_nsources, b + c);
}
Ejemplo n.º 8
0
void NaClRunSelQualificationTests()
{
  /* fail if Operating system platform is not supported */
  ZLOGFAIL(!NaClOsIsSupported(), EFAULT, "os not supported");

  /* fail if Data Execution Prevention is required but is not supported */
  ZLOGFAIL(!NaClCheckDEP(), EFAULT, "dep not supported");
}
Ejemplo n.º 9
0
/* get manifest data */
static void GetManifestData(const char *name, char *buf)
{
  FILE *h = fopen(name, "r");

  ZLOGFAIL(h == NULL, ENOENT, "manifest open error");
  ZLOGFAIL(fread(buf, 1, MANIFEST_SIZE_LIMIT, h) < 1, EIO, "manifest read error");
  fclose(h);
}
Ejemplo n.º 10
0
/* serve trap invoked from the untrusted code */
NORETURN void SyscallHook()
{
  struct NaClApp *nap;
  struct ThreadContext *user;
  uintptr_t tramp_ret;
  nacl_reg_t user_ret;
  size_t sysnum;
  uintptr_t sp_user;
  uintptr_t sp_sys;

  /* restore trusted side environment */
  nap = gnap; /* restore NaClApp object */
  user = nacl_user;
  sp_user = GetThreadCtxSp(user);
  sp_sys = sp_user;

  /*
   * sp_sys points to the top of user stack where there is a retaddr to
   * trampoline slot
   */
  tramp_ret = *(uintptr_t *)sp_sys;
  sysnum = (tramp_ret - (nap->mem_start + NACL_SYSCALL_START_ADDR))
      >> NACL_SYSCALL_BLOCK_SHIFT;

  /*
   * getting user return address (the address where we need to return after
   * system call) from the user stack. (see stack layout above)
   */
  user_ret = *(uintptr_t *)(sp_sys + NACL_USERRET_FIX);

  /*
   * Fix the user stack, throw away return addresses from the top of the stack.
   * After this fix, the first argument to a system call must be on the top of
   * the user stack (see user stack layout above)
   */
  sp_sys += NACL_SYSARGS_FIX;
  sp_user += NACL_SYSCALLRET_FIX;
  SetThreadCtxSp(user, sp_user);

  /* fail if nacl syscall received */
  ZLOGFAIL(sysnum != 0, EINVAL, "nacl syscall #%d received", sysnum);

  /*
   * syscall_args must point to the first argument of a system call.
   * System call arguments are placed on the untrusted user stack.
   */
  nap->sysret = TrapHandler(nap, *(uint32_t*)sp_sys);

  /*
   * before switching back to user module, we need to make sure that the
   * user_ret is properly sandboxed.
   */
  user_ret = (nacl_reg_t)NaClSandboxCodeAddr(nap, (uintptr_t)user_ret);

  /* d'b: give control to the user side */
  SwitchToApp(nap, user_ret);
  ZLOGFAIL(1, EFAULT, "the unreachable has been reached");
}
Ejemplo n.º 11
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;
}
Ejemplo n.º 12
0
/*
 * check if obligatory keywords appeared and check if the fields
 * which should appear only once did so
 */
static void CheckCounters(int *counters, int n)
{
  while(--n)
  {
    ZLOGFAIL(counters[n] == 0 && (CHECK_KEYWORDS[n] & 1),
        EFAULT, "%s not specified", XSTR(KEYWORDS, n));
    ZLOGFAIL(counters[n] > 1 && (CHECK_KEYWORDS[n] & 2),
        EFAULT, "duplicate %s keyword", XSTR(KEYWORDS, n));
  }
}
Ejemplo n.º 13
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 */
  }
}
Ejemplo n.º 14
0
void ValidateElfHeader(const struct ElfImage *image)
{
  const Elf_Ehdr *hdr = &image->ehdr;

  ZLOGFAIL(memcmp(hdr->e_ident, ELFMAG, SELFMAG), ENOEXEC, "bad elf magic");
  ZLOGFAIL(ELFCLASS64 != hdr->e_ident[EI_CLASS], ENOEXEC, "bad elf class");
  ZLOGFAIL(ET_EXEC != hdr->e_type, ENOEXEC, "non executable");
  ZLOGFAIL(EM_EXPECTED_BY_NACL != hdr->e_machine, ENOEXEC,
      "bad machine: %x", hdr->e_machine);
  ZLOGFAIL(EV_CURRENT != hdr->e_version, ENOEXEC, "bad elf version: %x", hdr->e_version);
}
Ejemplo n.º 15
0
/* set timeout. by design timeout must be specified in manifest */
static void SetTimeout(struct SystemManifest *policy)
{
  struct rlimit rl;

  assert(policy != NULL);

  GET_INT_BY_KEY(policy->timeout, MFT_TIMEOUT);
  ZLOGFAIL(policy->timeout < 1, EFAULT, "invalid or absent timeout");
  rl.rlim_cur = policy->timeout;
  rl.rlim_max = -1;
  setrlimit(RLIMIT_CPU, &rl);
  ZLOGFAIL(setrlimit(RLIMIT_CPU, &rl) != 0, errno, "cannot set timeout");
}
Ejemplo n.º 16
0
/* construct system_manifest object and initialize it from manifest */
void SystemManifestCtor(struct NaClApp *nap)
{
  struct SystemManifest *policy;

  /* check for design errors */
  assert(nap != NULL);
  assert(nap->system_manifest != NULL);

  policy = nap->system_manifest;
  policy->syscallback = 0;

  /* get zerovm settings from manifest */
  policy->version = GetValueByKey("Version");
  policy->nexe_etag = GetValueByKey("NexeEtag");

  /* check mandatory manifest keys */
  ZLOGFAIL(nap->system_manifest->version == NULL, EFAULT,
      "the manifest version is not provided");
  ZLOGFAIL(STRCMP(nap->system_manifest->version, MANIFEST_VERSION),
      EFAULT, "manifest version not supported");
  SetTimeout(policy);

  /* user data (environment, command line) */
  policy->envp = NULL;
  SetCustomAttributes(policy);

  /* prepare command line arguments for nexe */
  policy->cmd_line = NULL;
  policy->cmd_line_size = 0;
  SetCommandLine(policy);

  /* get node name and id */
  SetNodeName(nap);

  /* construct and initialize all channels */
  ChannelsCtor(nap);

  /*
   * allocate "whole memory chunk" if specified. should be the last allocation
   * in raw because after chunk allocated there will be no free user memory
   * note: will set "heap_ptr"
   */
  GET_INT_BY_KEY(nap->heap_end, "MemMax");
  PreallocateUserMemory(nap);

  /* zerovm return code */
  nap->system_manifest->ret_code = OK_CODE;
}
Ejemplo n.º 17
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");
}
Ejemplo n.º 18
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;
  }
}
Ejemplo n.º 19
0
/*
 * Check that signal handlers are not registered.  We want to
 * discourage Chrome or libraries from registering signal handlers
 * themselves, because those signal handlers are often not safe when
 * triggered from untrusted code.  For background, see:
 * http://code.google.com/p/nativeclient/issues/detail?id=1607
 */
void NaClSignalAssertNoHandlers()
{
  int i;

  for(i = 0; i < SIGNAL_COUNT; i++)
  {
    int signum = s_Signals[i];
    struct sigaction sa;

    ZLOGFAIL(-1 == sigaction(signum, NULL, &sa), errno, "sigaction() call failed");

    ZLOGFAIL((sa.sa_flags & SA_SIGINFO) != 0 ? sa.sa_sigaction != NULL
        : (sa.sa_handler != SIG_DFL && sa.sa_handler != SIG_IGN), EFAULT,
        "A signal handler is registered for signal %d. Did Breakpad register this?", signum);
  }
}
Ejemplo n.º 20
0
Archivo: sel.c Proyecto: 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");
}
Ejemplo n.º 21
0
int NaClSignalStackAllocate(void **result)
{
  /*
   * We use mmap() to allocate the signal stack for two reasons:
   *
   * 1) By page-aligning the memory allocation (which malloc() does
   * not do for small allocations), we avoid allocating any real
   * memory in the common case in which the signal handler is never
   * run.
   *
   * 2) We get to create a guard page, to guard against the unlikely
   * occurrence of the signal handler both overrunning and doing so in
   * an exploitable way.
   */
  uint8_t *stack = mmap(NULL, SIGNAL_STACK_SIZE + STACK_GUARD_SIZE,
      PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  if(stack == MAP_FAILED) return 0;

  /* We assume that the stack grows downwards. */
  ZLOGFAIL(-1 == mprotect(stack, STACK_GUARD_SIZE, PROT_NONE),
      errno, "Failed to mprotect() the stack guard page");

  *result = stack;
  return 1;
}
Ejemplo n.º 22
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");
}
Ejemplo n.º 23
0
/* set timeout. by design timeout must be specified in manifest */
static void SetTimeout(struct Manifest *manifest)
{
  assert(manifest != NULL);

  ZLOGFAIL(manifest->timeout < 1, EFAULT, "invalid timeout %d", manifest->timeout);
  alarm(manifest->timeout);
}
Ejemplo n.º 24
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;
  }
}
Ejemplo n.º 25
0
Archivo: etag.c Proyecto: Abioy/zerovm
void *TagCtor()
{
  GChecksum *ctx;

  ctx = g_checksum_new(TAG_ENCRYPTION);
  ZLOGFAIL(ctx == NULL, EFAULT, "error initializing tag context");
  return ctx;
}
Ejemplo n.º 26
0
/* switch to the nacl module (untrusted content) after signal */
NORETURN void NaClSwitchToAppAfterSignal(struct NaClApp *nap)
{
  /* prevent rdtsc execution */
  ZLOGFAIL(prctl(PR_SET_TSC, PR_TSC_SIGSEGV) == -1,
      errno, "cannot prevent rdtsc execution");

  NaClSwitch(nacl_user);
}
Ejemplo n.º 27
0
/*
 * prepare "bind" channel information for the name service
 * note: should be called before name service invocation
 */
static void PrepareBind(const struct ChannelDesc *channel)
{
  struct ChannelConnection *record;
  static uint16_t port = LOWEST_AVAILABLE_PORT;
  int result = 1;

  assert(channel != NULL);

  /* update netlist with the connection info */
  StoreChannelConnectionInfo(channel);

  /* if no name service is available just use given url and return */
  if(!NameServiceSet())
  {
    result = DoBind(channel);
    ZLOGFAIL(result != 0, EFAULT, "cannot bind %s", channel->alias);
    return;
  }

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

  /* in case channel has port assigned (full url) bind it and return */
  if(record->port != 0)
  {
    result = DoBind(channel);
    ZLOGFAIL(result != 0, EFAULT, "cannot bind %s", channel->alias);
    return;
  }

  /*
   * if channel does not have port pick up the port in the loop
   * todo(d'b): check upcoming zmq version for port 0 binding
   */
  assert(record != NULL);
  for(;port >= LOWEST_AVAILABLE_PORT; ++port)
  {
    record->port = port;
    result = DoBind(channel);
    if(result == 0) break;
  }

  ZLOGFAIL(result != 0, EFAULT ,"cannot get port to bind %s", channel->alias);
  ZLOGS(LOG_DEBUG, "host = %u, port = %u", record->host, record->port);
}
Ejemplo n.º 28
0
/* preallocate channel space if not disabled with "-P" */
static void PreallocateChannel(const struct ChannelDesc *channel, int n)
{
  int code;
  int handle = GPOINTER_TO_INT(CH_HANDLE(channel, n));

  if(disable_preallocation) return;
  code = ftruncate(handle, channel->limits[PutSizeLimit]);
  ZLOGFAIL(code == -1, errno, "cannot preallocate %s", channel->alias);
}
Ejemplo n.º 29
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");
}
Ejemplo n.º 30
0
/* set channels field */
static void Channel(struct Manifest *manifest, char *value)
{
  char **tokens;
  char **names;
  int i;
  struct ChannelDesc *channel;

  /* allocate a new channel */
  channel = g_malloc0(sizeof *channel);
  channel->source = g_ptr_array_new();

  /* get tokens from channel description */
  tokens = g_strsplit(value, VALUE_DELIMITER, ChannelTokensNumber);

  /* TODO(d'b): fix "invalid numeric value ', 0'" bug here */
  ZLOGFAIL(tokens[ChannelTokensNumber] != NULL || tokens[PutSize] == NULL,
      EFAULT, "invalid channel tokens number");

  /* parse alias and name(s) */
  channel->alias = g_strdup(g_strstrip(tokens[Alias]));
  names = g_strsplit(tokens[Name], TOKEN_DELIMITER, MANIFEST_TOKENS_LIMIT);
  for(i = 0; names[i] != NULL; ++i)
    ParseName(names[i], channel->source);

  channel->type = ToInt(tokens[Type]);

  i = ToInt(tokens[Tag]);
  ZLOGFAIL(i != 0 && i != 1, EFAULT, "invalid channel mumeric token");

  channel->tag = i == 0 ? NULL : TagCtor();

  for(i = 0; i < LimitsNumber; ++i)
  {
    channel->limits[i] = ToInt(tokens[i + Gets]);
    ZLOGFAIL(channel->limits[i] < 0, EFAULT,
        "negative limits for %s", channel->alias);
  }

  /* append a new channel */
  g_ptr_array_add(manifest->channels, channel);
  g_strfreev(names);
  g_strfreev(tokens);
}