/*
 * NaClDescXferableDataDescLowLevelSendMsg implements imc_sendmsg For
 * data-only descriptors.  We assume that whatever protocol exists at
 * the NaClSendDatagram level is still not thread safe, but that the
 * lack of thread safety will not have a significant impact on
 * security.  This is still somewhat brittle: the low-level Windows
 * IMC code can be convinced to do the wrong thing still via sender
 * races, but the receiver, because it expects zero handles, will have
 * called ReceiveDatagram in such a way that any "received handles"
 * are closed.  This implies that arbitrary Windows handles can be
 * made to be closed, including those not accessible by NaCl modules,
 * but fortunately this should only result in a denial of service as
 * the error caused by the use of an invalid handle is detected by the
 * service runtime and cause an abort.
 *
 * Note that it is still an application error to send or receive data
 * with a transferable data-only descriptor from two threads (or two
 * modules) simultaneously.
 */
static ssize_t
NaClDescXferableDataDescLowLevelSendMsg(struct NaClDesc                *vself,
                                        struct NaClMessageHeader const *dgram,
                                        int                            flags) {
  struct NaClDescXferableDataDesc *self = ((struct NaClDescXferableDataDesc *)
                                           vself);
  int result;

  if (0 != dgram->handle_count) {
    /*
     * A transferable descriptor cannot be used to transfer other
     * descriptors.
     */
    NaClLog(2,
            ("NaClDescXferableDataDescLowLevelSendMsg: tranferable and"
             " non-zero handle_count\n"));
    return -NACL_ABI_EINVAL;
  }

  result = NaClSendDatagram(self->base.h, dgram, flags);

  if (-1 == result) {
#if NACL_WINDOWS
    return -NaClXlateSystemError(GetLastError());
#elif NACL_LINUX || NACL_OSX
    return -NaClXlateErrno(errno);
#else
# error "Unknown target platform: cannot translate error code(s) from SendMsg"
#endif
  }
  return result;
}
示例#2
0
/*
 * NaClDescXferableDataDescSendMsg implements imc_sendmsg For
 * data-only descriptors.  We assume that whatever protocol exists at
 * the NaClSendDatagram level is still not thread safe, but that the
 * lack of thread safety will not have a significant impact on
 * security.  This is still somewhat brittle: the low-level Windows
 * IMC code can be convinced to do the wrong thing still via sender
 * races, but the receiver, because it expects zero handles, will have
 * called ReceiveDatagram in such a way that any "received handles"
 * are closed.  This implies that arbitrary Windows handles can be
 * made to be closed, including those not accessible by NaCl modules,
 * but fortunately this should only result in a denial of service as
 * the error caused by the use of an invalid handle is detected by the
 * service runtime and cause an abort.
 *
 * Note that it is still an application error to send or receive data
 * with a transferable data-only descriptor from two threads (or two
 * modules) simultaneously.
 */
static ssize_t
NaClDescXferableDataDescSendMsg(struct NaClDesc                *vself,
                                struct NaClMessageHeader const *dgram,
                                int                            flags) {
  struct NaClDescXferableDataDesc *self = ((struct NaClDescXferableDataDesc *)
                                           vself);
  int result;

  if (0 != dgram->handle_count) {
    /*
     * A transferable descriptor cannot be used to transfer other
     * descriptors.
     */
    NaClLog(2,
            ("NaClDescXferableDataDescSendMsg: tranferable and"
             " non-zero handle_count\n"));
    return -NACL_ABI_EINVAL;
  }

  result = NaClSendDatagram(self->base.h, dgram, flags);

  if (-1 == result) {
    return -NaClXlateErrno(errno);
  }
  return result;
}
示例#3
0
/*
 * In the level of NaClDescImcDescSendMsg, we do not know what
 * protocol is implemented by NaClSendDatagram (and indeed, in the
 * Windows implementation, the access rights transfer involves a more
 * complex protocol to get the peer process id).  Because the
 * underlying low-level IMC implementation does not provide thread
 * safety, this is the source of race conditions: two simultaneous
 * imc_sendmsg syscalls to the same descriptor could get their various
 * protcol bits interleaved, so the receiver will get garbled data
 * that cause the wrong underlying host OS descriptor to be made
 * available to the NaCl module.
 *
 * In order to address this issue, we (1) make descriptors that can
 * transfer other descriptors non-transferable, and (2) we use locking
 * so that only one thread can be performing (the low level bits of)
 * imc_msgsend at a time.  The non-transferability of such descriptors
 * addresses the multi-module scenario, as opposed to the
 * multi-threaded scenario, where a sender race cause receiver
 * confusion.
 */
static ssize_t NaClDescImcDescSendMsg(struct NaClDesc                *vself,
                                      struct NaClMessageHeader const *dgram,
                               int                            flags) {
  struct NaClDescImcDesc *self = ((struct NaClDescImcDesc *)
                                  vself);
  int result;

  NaClXMutexLock(&self->sendmsg_mu);
  result = NaClSendDatagram(self->base.h, dgram, flags);
  NaClXMutexUnlock(&self->sendmsg_mu);

  if (-1 == result) {
    return -NaClXlateErrno(errno);
  }
  return result;
}
int main(int argc, char* argv[]) {
  int result;
  NaClHandle pair[2];
  NaClMessageHeader header;
  NaClIOVec vec;
  char buffer[] = "Hello!";

  g_front = NaClBoundSocket(&test_address);
  if (g_front == NACL_INVALID_HANDLE) {
    PrintError("BoundSocket");
    exit(EXIT_FAILURE);
  }
  atexit(CleanUp);

  if (NaClSocketPair(pair) != 0) {
    PrintError("SocketPair");
    exit(EXIT_FAILURE);
  }

  vec.base = buffer;
  vec.length = sizeof buffer;

  /* Test SendDatagram */
  header.iov = &vec;
  header.iov_length = 1;
  header.handles = NULL;
  header.handle_count = 0;
  result = NaClSendDatagram(pair[0], &header, 0);
  assert(result == sizeof buffer);

  /* Test ReceiveDatagram */
  memset(buffer, 0, sizeof buffer);
  header.iov = &vec;
  header.iov_length = 1;
  header.handles = NULL;
  header.handle_count = 0;
  result = NaClReceiveDatagram(pair[1], &header, 0);
  assert(result == sizeof buffer);

  assert(strcmp(buffer, "Hello!") == 0);
  printf("%s\n", buffer);

  (void) NaClClose(pair[0]);
  (void) NaClClose(pair[1]);

  return 0;
}
/*
 * In the level of NaClDescImcDescLowLevelSendMsg, we do not know what
 * protocol is implemented by NaClSendDatagram (and indeed, in the
 * Windows implementation, the access rights transfer involves a more
 * complex protocol to get the peer process id).  Because the
 * underlying low-level IMC implementation does not provide thread
 * safety, this is the source of race conditions: two simultaneous
 * imc_sendmsg syscalls to the same descriptor could get their various
 * protcol bits interleaved, so the receiver will get garbled data
 * that cause the wrong underlying host OS descriptor to be made
 * available to the NaCl module.
 *
 * In order to address this issue, we (1) make descriptors that can
 * transfer other descriptors non-transferable, and (2) we use locking
 * so that only one thread can be performing (the low level bits of)
 * imc_msgsend at a time.  The non-transferability of such descriptors
 * addresses the multi-module scenario, as opposed to the
 * multi-threaded scenario, where a sender race cause receiver
 * confusion.
 */
static ssize_t NaClDescImcDescLowLevelSendMsg(
    struct NaClDesc                *vself,
    struct NaClMessageHeader const *dgram,
    int                            flags) {
  struct NaClDescImcDesc *self = ((struct NaClDescImcDesc *)
                                  vself);
  int result;

  NaClXMutexLock(&self->sendmsg_mu);
  result = NaClSendDatagram(self->base.h, dgram, flags);
  NaClXMutexUnlock(&self->sendmsg_mu);

  if (-1 == result) {
#if NACL_WINDOWS
    return -NaClXlateSystemError(GetLastError());
#elif NACL_LINUX || NACL_OSX
    return -NaClXlateErrno(errno);
#else
# error "Unknown target platform: cannot translate error code(s) from SendMsg"
#endif
  }
  return result;
}