Exemple #1
0
/**
 * Function responsible for setting up the socket syscall for
 * the seccomp filter sandbox.
 */
static int
sb_socket(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
{
  int rc = 0;
  int i, j;
  (void) filter;

#ifdef __i386__
  rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket));
  if (rc)
    return rc;
#endif

  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
      SCMP_CMP(0, SCMP_CMP_EQ, PF_FILE),
      SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_STREAM));
  if (rc)
    return rc;

  for (i = 0; i < 2; ++i) {
    const int pf = i ? PF_INET : PF_INET6;
    for (j=0; j < 3; ++j) {
      const int type     = (j == 0) ? SOCK_STREAM :
                                      SOCK_DGRAM;
      const int protocol = (j == 0) ? IPPROTO_TCP :
                           (j == 1) ? IPPROTO_IP :
                                      IPPROTO_UDP;
      rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
        SCMP_CMP(0, SCMP_CMP_EQ, pf),
        SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, type),
        SCMP_CMP(2, SCMP_CMP_EQ, protocol));
      if (rc)
        return rc;
    }
  }

  rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
      SCMP_CMP(0, SCMP_CMP_EQ, PF_UNIX),
      SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_STREAM),
      SCMP_CMP(2, SCMP_CMP_EQ, 0));
  if (rc)
    return rc;

  rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
      SCMP_CMP(0, SCMP_CMP_EQ, PF_UNIX),
      SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_DGRAM),
      SCMP_CMP(2, SCMP_CMP_EQ, 0));
  if (rc)
    return rc;

  rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
      SCMP_CMP(0, SCMP_CMP_EQ, PF_NETLINK),
      SCMP_CMP(1, SCMP_CMP_EQ, SOCK_RAW),
      SCMP_CMP(2, SCMP_CMP_EQ, 0));
  if (rc)
    return rc;

  return 0;
}
Exemple #2
0
/**
 * Function responsible for setting up the openat syscall for
 * the seccomp filter sandbox.
 */
static int
sb_openat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
{
  int rc;
  sandbox_cfg_t *elem = NULL;

  // for each dynamic parameter filters
  for (elem = filter; elem != NULL; elem = elem->next) {
    smp_param_t *param = elem->param;

    if (param != NULL && param->prot == 1 && param->syscall
        == SCMP_SYS(openat)) {
      rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat),
          SCMP_CMP(0, SCMP_CMP_EQ, AT_FDCWD),
          SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value),
          SCMP_CMP(2, SCMP_CMP_EQ, O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|
              O_CLOEXEC));
      if (rc != 0) {
        log_err(LD_BUG,"(Sandbox) failed to add openat syscall, received "
            "libseccomp error %d", rc);
        return rc;
      }
    }
  }

  return 0;
}
Exemple #3
0
/**
 * Function responsible for setting up the socket syscall for
 * the seccomp filter sandbox.
 */
static int
sb_socket(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
{
  int rc = 0;
  int i;
  (void) filter;

#ifdef __i386__
  rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket));
  if (rc)
    return rc;
#endif

  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
      SCMP_CMP(0, SCMP_CMP_EQ, PF_FILE),
      SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_STREAM));
  if (rc)
    return rc;

  for (i = 0; i < 2; ++i) {
    const int pf = i ? PF_INET : PF_INET6;

    rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
      SCMP_CMP(0, SCMP_CMP_EQ, pf),
      SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_STREAM),
      SCMP_CMP(2, SCMP_CMP_EQ, IPPROTO_TCP));
    if (rc)
      return rc;

    rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
      SCMP_CMP(0, SCMP_CMP_EQ, pf),
      SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_DGRAM),
      SCMP_CMP(2, SCMP_CMP_EQ, IPPROTO_IP));
    if (rc)
      return rc;
  }

  rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
      SCMP_CMP(0, SCMP_CMP_EQ, PF_NETLINK),
      SCMP_CMP(1, SCMP_CMP_EQ, SOCK_RAW),
      SCMP_CMP(2, SCMP_CMP_EQ, 0));
  if (rc)
    return rc;

  return 0;
}
Exemple #4
0
/**
 * Protects all the strings in the sandbox's parameter list configuration. It
 * works by calculating the total amount of memory required by the parameter
 * list, allocating the memory using mmap, and protecting it from writes with
 * mprotect().
 */
static int
prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg)
{
  int ret = 0;
  size_t pr_mem_size = 0, pr_mem_left = 0;
  char *pr_mem_next = NULL, *pr_mem_base;
  sandbox_cfg_t *el = NULL;
  strmap_t *locations = NULL;

  // get total number of bytes required to mmap. (Overestimate.)
  for (el = cfg; el != NULL; el = el->next) {
    pr_mem_size += strlen((char*) el->param->value) + 1;
    if (el->param->value2)
      pr_mem_size += strlen((char*) el->param->value2) + 1;
  }

  // allocate protected memory with MALLOC_MP_LIM canary
  pr_mem_base = (char*) mmap(NULL, MALLOC_MP_LIM + pr_mem_size,
      PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
  if (pr_mem_base == MAP_FAILED) {
    log_err(LD_BUG,"(Sandbox) failed allocate protected memory! mmap: %s",
        strerror(errno));
    ret = -1;
    goto out;
  }

  pr_mem_next = pr_mem_base + MALLOC_MP_LIM;
  pr_mem_left = pr_mem_size;

  locations = strmap_new();

  // change el value pointer to protected
  for (el = cfg; el != NULL; el = el->next) {
    if (prot_strings_helper(locations, &pr_mem_next, &pr_mem_left,
                            &el->param->value) < 0) {
      ret = -2;
      goto out;
    }
    if (prot_strings_helper(locations, &pr_mem_next, &pr_mem_left,
                            &el->param->value2) < 0) {
      ret = -2;
      goto out;
    }
    el->param->prot = 1;
  }

  // protecting from writes
  if (mprotect(pr_mem_base, MALLOC_MP_LIM + pr_mem_size, PROT_READ)) {
    log_err(LD_BUG,"(Sandbox) failed to protect memory! mprotect: %s",
        strerror(errno));
    ret = -3;
    goto out;
  }

  /*
   * Setting sandbox restrictions so the string memory cannot be tampered with
   */
  // no mremap of the protected base address
  ret = seccomp_rule_add_1(ctx, SCMP_ACT_KILL, SCMP_SYS(mremap),
      SCMP_CMP(0, SCMP_CMP_EQ, (intptr_t) pr_mem_base));
  if (ret) {
    log_err(LD_BUG,"(Sandbox) mremap protected memory filter fail!");
    goto out;
  }

  // no munmap of the protected base address
  ret = seccomp_rule_add_1(ctx, SCMP_ACT_KILL, SCMP_SYS(munmap),
        SCMP_CMP(0, SCMP_CMP_EQ, (intptr_t) pr_mem_base));
  if (ret) {
    log_err(LD_BUG,"(Sandbox) munmap protected memory filter fail!");
    goto out;
  }

  /*
   * Allow mprotect with PROT_READ|PROT_WRITE because openssl uses it, but
   * never over the memory region used by the protected strings.
   *
   * PROT_READ|PROT_WRITE was originally fully allowed in sb_mprotect(), but
   * had to be removed due to limitation of libseccomp regarding intervals.
   *
   * There is a restriction on how much you can mprotect with R|W up to the
   * size of the canary.
   */
  ret = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
      SCMP_CMP(0, SCMP_CMP_LT, (intptr_t) pr_mem_base),
      SCMP_CMP(1, SCMP_CMP_LE, MALLOC_MP_LIM),
      SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE));
  if (ret) {
    log_err(LD_BUG,"(Sandbox) mprotect protected memory filter fail (LT)!");
    goto out;
  }

  ret = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
      SCMP_CMP(0, SCMP_CMP_GT, (intptr_t) pr_mem_base + pr_mem_size +
          MALLOC_MP_LIM),
      SCMP_CMP(1, SCMP_CMP_LE, MALLOC_MP_LIM),
      SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE));
  if (ret) {
    log_err(LD_BUG,"(Sandbox) mprotect protected memory filter fail (GT)!");
    goto out;
  }

 out:
  strmap_free(locations, NULL);
  return ret;
}