Exemplo n.º 1
0
ssize_t NaClDescQuotaPWrite(struct NaClDesc *vself,
                            void const *buf,
                            size_t len,
                            nacl_off64_t offset) {
  struct NaClDescQuota  *self = (struct NaClDescQuota *) vself;
  uint64_t              len_u64;
  int64_t               allowed;
  ssize_t               rv;

  if (0 == len) {
    allowed = 0;
  } else {
    NACL_COMPILE_TIME_ASSERT(SIZE_T_MAX <= NACL_UMAX_VAL(uint64_t));
    /*
     * Write can always return a short, non-zero transfer count.
     */
    len_u64 = (uint64_t) len;
    /* get rid of the always-true/always-false comparison warning */
    if (len_u64 > NACL_MAX_VAL(int64_t)) {
      len = (size_t) NACL_MAX_VAL(int64_t);
    }

    if (NULL == self->quota_interface) {
      /* If there is no quota_interface, do not allow writes. */
      allowed = 0;
    } else {
      allowed = (*NACL_VTBL(NaClDescQuotaInterface, self->quota_interface)->
                 WriteRequest)(self->quota_interface,
                               self->file_id, offset, len);
    }
    if (allowed <= 0) {
      rv = -NACL_ABI_EDQUOT;
      goto abort;
    }
    /*
     * allowed <= len should be a post-condition, but we check for
     * it anyway.
     */
    if ((uint64_t) allowed > len) {
      NaClLog(LOG_WARNING,
              ("NaClDescQuotaPWrite: WriteRequest returned an allowed quota"
               " that is larger than that requested; reducing to original"
               " request amount.\n"));
      allowed = len;
    }
  }

  /*
   * It is possible for Write to write fewer than bytes than the quota
   * that was granted, in which case quota will leak.
   * TODO(sehr,bsy): eliminate quota leakage.
   */
  rv = (*NACL_VTBL(NaClDesc, self->desc)->PWrite)(self->desc,
                                                  buf, (size_t) allowed,
                                                  offset);
abort:
  return rv;
}
Exemplo n.º 2
0
/* set *out_desc to struct NaClDescIo * output */
int NaClDescIoInternalize(struct NaClDesc               **out_desc,
                          struct NaClDescXferState      *xfer,
                          struct NaClDescQuotaInterface *quota_interface) {
  int                   rv;
  NaClHandle            h;
  int                   d;
  int                   flags;
  struct NaClHostDesc   *nhdp;
  struct NaClDescIoDesc *ndidp;

  UNREFERENCED_PARAMETER(quota_interface);
  rv = -NACL_ABI_EIO;  /* catch-all */
  h = NACL_INVALID_HANDLE;
  nhdp = NULL;
  ndidp = NULL;

  nhdp = malloc(sizeof *nhdp);
  if (NULL == nhdp) {
    rv = -NACL_ABI_ENOMEM;
    goto cleanup;
  }
  ndidp = malloc(sizeof *ndidp);
  if (!ndidp) {
    rv = -NACL_ABI_ENOMEM;
    goto cleanup;
  }
  if (!NaClDescInternalizeCtor((struct NaClDesc *) ndidp, xfer)) {
    rv = -NACL_ABI_ENOMEM;
    goto cleanup;
  }
  if (xfer->next_handle == xfer->handle_buffer_end ||
      xfer->next_byte + sizeof ndidp->hd->flags > xfer->byte_buffer_end) {
    rv = -NACL_ABI_EIO;
    goto cleanup_ndidp_dtor;
  }

  NACL_COMPILE_TIME_ASSERT(sizeof flags == sizeof(ndidp->hd->flags));
  memcpy(&flags, xfer->next_byte, sizeof flags);
  xfer->next_byte += sizeof flags;

  h = *xfer->next_handle;
  *xfer->next_handle++ = NACL_INVALID_HANDLE;
#if NACL_WINDOWS
  if (-1 == (d = _open_osfhandle((intptr_t) h, _O_RDWR | _O_BINARY))) {
    rv = -NACL_ABI_EIO;
    goto cleanup_ndidp_dtor;
  }
#else
  d = h;
#endif
  /*
   * We mark it as read/write, but don't really know for sure until we
   * try to make those syscalls (in which case we'd get EBADF).
   */
  if ((rv = NaClHostDescPosixTake(nhdp, d, flags)) < 0) {
    goto cleanup_ndidp_dtor;
  }
  h = NACL_INVALID_HANDLE;  /* nhdp took ownership of h */

  if (!NaClDescIoDescSubclassCtor(ndidp, nhdp)) {
    rv = -NACL_ABI_ENOMEM;
    goto cleanup_nhdp_dtor;
  }
  /*
   * ndidp took ownership of nhdp, now give ownership of ndidp to caller.
   */
  *out_desc = (struct NaClDesc *) ndidp;
  rv = 0;
 cleanup_nhdp_dtor:
  if (rv < 0) {
    if (0 != NaClHostDescClose(nhdp)) {
      NaClLog(LOG_FATAL, "NaClDescIoInternalize: NaClHostDescClose failed\n");
    }
  }
 cleanup_ndidp_dtor:
  if (rv < 0) {
    NaClDescSafeUnref((struct NaClDesc *) ndidp);
    ndidp = NULL;
  }
 cleanup:
  if (rv < 0) {
    free(nhdp);
    free(ndidp);
    if (NACL_INVALID_HANDLE != h) {
      (void) NaClClose(h);
    }
  }
  return rv;
}