/* * See discussion at NaClDescXferableDataDescSendMsg for details. An * imc_recvmsg race is not substantively different from an imc_sendmsg * race. */ static ssize_t NaClDescXferableDataDescRecvMsg(struct NaClDesc *vself, struct NaClMessageHeader *dgram, int flags) { struct NaClDescXferableDataDesc *self = ((struct NaClDescXferableDataDesc *) vself); int result; NaClLog(4, "Entered NaClDescXferableDataDescRecvMsg, h = %d\n", self->base.h); if (0 != dgram->handle_count) { /* * A transferable descriptor is data-only, and it is an error to * try to receive any I/O descriptors with it. */ NaClLog(2, "NaClDescXferableDataDescRecvMsg:" " tranferable and non-zero handle_count\n"); return -NACL_ABI_EINVAL; } result = NaClReceiveDatagram(self->base.h, dgram, flags); if (-1 == result) { return -errno; } return result; }
/* * See discussion at NaClDescXferableDataDescLowLevelSendMsg for details. An * imc_recvmsg race is not substantively different from an imc_sendmsg * race. */ static ssize_t NaClDescXferableDataDescLowLevelRecvMsg( struct NaClDesc *vself, struct NaClMessageHeader *dgram, int flags) { struct NaClDescXferableDataDesc *self = ((struct NaClDescXferableDataDesc *) vself); int result; NaClLog(4, "Entered NaClDescXferableDataDescLowLevelRecvMsg, h = %d\n", self->base.h); if (0 != dgram->handle_count) { /* * A transferable descriptor is data-only, and it is an error to * try to receive any I/O descriptors with it. */ NaClLog(2, "NaClDescXferableDataDescLowLevelRecvMsg:" " tranferable and non-zero handle_count\n"); return -NACL_ABI_EINVAL; } result = NaClReceiveDatagram(self->base.h, dgram, flags); if (-1 == result) { #if NACL_WINDOWS return -NaClXlateSystemError(GetLastError()); #elif NACL_LINUX || NACL_OSX return -errno; #else # error "Unknown target platform: cannot translate error code(s) from RecvMsg" #endif } 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; }
/* * See discussion at NaClDescImcDescSendMsg for details. An * imc_recvmsg race is not substantively different from an imc_sendmsg * race. */ static ssize_t NaClDescImcDescRecvMsg(struct NaClDesc *vself, struct NaClMessageHeader *dgram, int flags) { struct NaClDescImcDesc *self = ((struct NaClDescImcDesc *) vself); int result; NaClLog(4, "Entered NaClDescImcDescRecvMsg, h=%d\n", self->base.h); NaClXMutexLock(&self->recvmsg_mu); result = NaClReceiveDatagram(self->base.h, dgram, flags); NaClXMutexUnlock(&self->recvmsg_mu); if (-1 == result) { return -errno; } return result; }
/* * See discussion at NaClDescImcDescLowLevelSendMsg for details. An * imc_recvmsg race is not substantively different from an imc_sendmsg * race. */ static ssize_t NaClDescImcDescLowLevelRecvMsg(struct NaClDesc *vself, struct NaClMessageHeader *dgram, int flags) { struct NaClDescImcDesc *self = ((struct NaClDescImcDesc *) vself); int result; NaClLog(4, "Entered NaClDescImcDescLowLevelRecvMsg, h=%d\n", self->base.h); NaClXMutexLock(&self->recvmsg_mu); result = NaClReceiveDatagram(self->base.h, dgram, flags); NaClXMutexUnlock(&self->recvmsg_mu); if (-1 == result) { #if NACL_WINDOWS return -NaClXlateSystemError(GetLastError()); #elif NACL_LINUX || NACL_OSX return -errno; #else # error "Unknown target platform: cannot translate error code(s) from RecvMsg" #endif } return result; }
static int NaClDescImcBoundDescAcceptConn(struct NaClDesc *vself, struct NaClDesc **result) { /* * See NaClDescConnCapConnectAddr code in nacl_desc_conn_cap.c */ struct NaClDescImcBoundDesc *self; int retval; NaClHandle nh; int nbytes; struct NaClMessageHeader conn_msg; struct NaClDescImcDesc *peer; self = (struct NaClDescImcBoundDesc *) vself; if (NULL == (peer = malloc(sizeof *peer))) { return -NACL_ABI_ENOMEM; } conn_msg.iov = 0; conn_msg.iov_length = 0; conn_msg.handle_count = 1; conn_msg.handles = &nh; conn_msg.flags = 0; nh = NACL_INVALID_HANDLE; NaClLog(3, ("NaClDescImcBoundDescAcceptConn(0x%08"NACL_PRIxPTR"):" " h = %d\n"), (uintptr_t) vself, self->h); if (-1 == (nbytes = NaClReceiveDatagram(self->h, &conn_msg, 0))) { NaClLog(LOG_ERROR, ("NaClDescImcBoundDescAcceptConn:" " could not receive connection message, errno %d\n"), errno); retval = -NACL_ABI_EMFILE; goto cleanup; } if (0 != nbytes) { NaClLog(LOG_ERROR, ("NaClDescImcBoundDescAcceptConn:" " connection message contains data?!?\n")); retval = -NACL_ABI_EMFILE; /* TODO(bsy): better errno? */ goto cleanup; } if (1 != conn_msg.handle_count) { NaClLog(LOG_ERROR, ("NaClDescImcBoundDescAcceptConn: connection" " message contains %"NACL_PRIdS" descriptors?!?\n"), conn_msg.handle_count); retval = -NACL_ABI_EMFILE; /* TODO(bsy): better errno? */ goto cleanup; } if (!NaClDescImcDescCtor(peer, nh)) { retval = -NACL_ABI_EMFILE; goto cleanup; } nh = NACL_INVALID_HANDLE; *result = (struct NaClDesc *) peer; retval = 0; cleanup: if (retval < 0) { if (NACL_INVALID_HANDLE != nh) { (void) NaClClose(nh); nh = NACL_INVALID_HANDLE; } free(peer); } return retval; }
int main(int argc, char **argv) { struct NaClApp app; struct NaClDesc *nd; NaClHandle handle_pair[2]; char *parse_args[] = {"prog", "parse"}; int return_code; char buffer[100]; NaClMessageHeader header; NaClIOVec vec; struct ncwebserver_t server; struct ncwebserver_conf_t conf; if (argc < 2){ usage(ncwebserver_usage_string); } NaClAllModulesInit(); NaClFileNameForValgrind(argv[1]); nd = (struct NaClDesc *) NaClDescIoDescOpen(argv[1], NACL_ABI_O_RDONLY, 0); CHECK(NULL != nd); CHECK(NaClAppCtor(&app)); /* Use a smaller guest address space size, because 32-bit Windows does not let us allocate 2GB of address space. We don't do this for x86-64 because there is an assertion in NaClAllocateSpace() that requires 4GB. */ #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32 app.addr_bits = 29; /* 512MB per process */ #endif /* * On x86-32, we cannot enable ASLR even when the address space is * 512MB. In particular, when on Windows where the available * contiguous address space is tight, if the random choice for the * base of the first 512MB address space puts that address space * in the middle of the available address space region, the * address space allocation code might not be able to (randomly) * find another contiguous 512MB region for the second NaCl * module. */ CHECK(NaClAppLoadFileAslr(nd, &app, NACL_DISABLE_ASLR) == LOAD_OK); NaClAppInitialDescriptorHookup(&app); CHECK(NaClAppPrepareToLaunch(&app) == LOAD_OK); /* Set up an IMC connection between the host and guest. */ CHECK(NaClSocketPair(handle_pair) == 0); NaClAddImcHandle(&app, handle_pair[0], SEND_DESC); CHECK(NaClCreateMainThread(&app, 2, parse_args, NULL)); return_code = NaClWaitForMainThreadToExit(&app); CHECK(return_code == 101); // receive message sent from HTML parser vec.base = buffer; vec.length = sizeof buffer; memset(buffer, 0, sizeof buffer); header.iov = &vec; header.iov_length = 1; header.handles = NULL; header.handle_count = 0; return_code = NaClReceiveDatagram(handle_pair[1], &header, 0); assert(return_code == sizeof buffer); printf("Server received \"%s\" (with size = %d)\n", buffer+16, return_code); // run web server memset(&conf, 0, sizeof(conf)); parse_argv(argc, argv, &conf); ncwebserver_init(&server, &conf); ncwebserver_start(&server); /* * Avoid calling exit() because it runs process-global destructors * which might break code that is running in our unjoined threads. */ NaClExit(0); }