/* * Look up by string name, resulting in a handle (if name is in the * preimage), a object proxy handle, and an error code. */ static void NaClReverseServiceManifestLookupRpc( struct NaClSrpcRpc *rpc, struct NaClSrpcArg **in_args, struct NaClSrpcArg **out_args, struct NaClSrpcClosure *done_cls) { struct NaClReverseService *nrsp = (struct NaClReverseService *) rpc->channel->server_instance_data; char *url_key = in_args[0]->arrays.str; int flags = in_args[0]->u.ival; struct NaClFileInfo info; struct NaClHostDesc *host_desc; struct NaClDescIoDesc *io_desc = NULL; struct NaClDesc *nacl_desc = NULL; memset(&info, 0, sizeof(info)); NaClLog(4, "Entered ManifestLookupRpc: 0x%08"NACL_PRIxPTR", %s, %d\n", (uintptr_t) nrsp, url_key, flags); NaClLog(4, "ManifestLookupRpc: invoking OpenManifestEntry\n"); if (!(*NACL_VTBL(NaClReverseInterface, nrsp->iface)-> OpenManifestEntry)(nrsp->iface, url_key, &info) || -1 == info.desc) { NaClLog(1, "ManifestLookupRpc: OpenManifestEntry failed.\n"); out_args[0]->u.ival = NACL_ABI_ENOENT; /* failed */ out_args[1]->u.hval = (struct NaClDesc *) NaClDescInvalidMake(); out_args[2]->u.lval = 0; out_args[3]->u.lval = 0; out_args[4]->u.count = 0; goto done; } NaClLog(4, "ManifestLookupRpc: OpenManifestEntry returned desc %d.\n", info.desc); host_desc = (struct NaClHostDesc *) malloc(sizeof *host_desc); CHECK(host_desc != NULL); CHECK(NaClHostDescPosixTake(host_desc, info.desc, NACL_ABI_O_RDONLY) == 0); io_desc = NaClDescIoDescMake(host_desc); CHECK(io_desc != NULL); nacl_desc = (struct NaClDesc *) io_desc; out_args[0]->u.ival = 0; /* OK */ out_args[1]->u.hval = nacl_desc; out_args[2]->u.lval = (int64_t) info.file_token.lo; out_args[3]->u.lval = (int64_t) info.file_token.hi; out_args[4]->u.count = 10; strncpy(out_args[4]->arrays.carr, "123456789", 10); /* * TODO(phosek): the array should be an object reference (issue 3035). */ done: rpc->result = NACL_SRPC_RESULT_OK; (*done_cls->Run)(done_cls); NaClDescSafeUnref((struct NaClDesc *) io_desc); }
struct NaClHostDesc *NaClHostDescPosixMake(int posix_d, int flags) { struct NaClHostDesc *nhdp; int error; nhdp = malloc(sizeof *nhdp); if (NULL == nhdp) { NaClLog(LOG_FATAL, "NaClHostDescPosixMake(%d,0x%x): malloc failed\n", posix_d, flags); } if (0 != (error = NaClHostDescPosixTake(nhdp, posix_d, flags))) { NaClLog(LOG_FATAL, "NaClHostDescPosixMake(%d,0x%x): Take failed, error %da\n", posix_d, flags, error); } return nhdp; }
/* * It is the responsibility of the invoking environment to delete the * file passed as command-line argument. See the build.scons file. */ int main(int ac, char **av) { char const *test_dir_name = "/tmp/nacl_host_desc_mmap_win_test"; struct NaClHostDesc hd; int test_passed; size_t error_count; size_t ix; int opt; int num_runs = 1; int test_run; HANDLE h; int d; while (EOF != (opt = getopt(ac, av, "c:t:"))) { switch (opt) { case 'c': num_runs = atoi(optarg); break; case 't': test_dir_name = optarg; break; default: fprintf(stderr, "Usage: nacl_host_desc_mmap_win_test [-c run_count]\n" " [-t test_temp_dir]\n"); exit(1); } } NaClPlatformInit(); error_count = 0; for (test_run = 0; test_run < num_runs; ++test_run) { printf("Test run %d\n\n", test_run); for (ix = 0; ix < NACL_ARRAY_SIZE(tests); ++ix) { char test_file_name[PATH_MAX]; _snprintf_s(test_file_name, sizeof test_file_name, _TRUNCATE, "%s/f%d.%"NACL_PRIuS, test_dir_name, test_run, ix); printf("%s\n", tests[ix].test_info); printf("-- %s\n", tests[ix].file_type->file_type_description); h = CreateTestFile(test_file_name, tests[ix].file_type); if (ERROR_SUCCESS == tests[ix].expected_open_error) { if (INVALID_HANDLE_VALUE == h) { DWORD err = GetLastError(); NaClLog(LOG_ERROR, "CreateTestFile for %s failed, error %d\n", test_file_name, err); printf("FAILED\n"); ++error_count; continue; } d = _open_osfhandle((intptr_t) h, tests[ix].oflags); NaClHostDescPosixTake(&hd, d, tests[ix].posix_flags); test_passed = TryToMap(&hd, tests[ix].map_bytes, tests[ix].prot, tests[ix].map_flags, tests[ix].expected_mmap_errno); error_count += !test_passed; printf("%s\n", test_passed ? "PASSED" : "FAILED"); CHECK(0 == NaClHostDescClose(&hd)); AttemptToDeleteTestFile(test_file_name); } else { if (INVALID_HANDLE_VALUE == h) { DWORD err = GetLastError(); if (err != tests[ix].expected_open_error) { NaClLog(LOG_ERROR, "Expected CreateTestFile for %s to failed with" " error %d, but got error %d\n", test_file_name, err, tests[ix].expected_open_error); printf("FAILED\n"); ++error_count; } else { printf("PASSED (open failed)\n"); } continue; } else { NaClLog(LOG_ERROR, "Expected CreateTestFile for %s to fail with error %d," " but succeeded instead!\n", test_file_name, tests[ix].expected_open_error); (void) CloseHandle(h); AttemptToDeleteTestFile(test_file_name); printf("FAILED\n"); ++error_count; continue; } } } } printf("Total of %d error%s.\n", error_count, (error_count == 1) ? "" : "s"); NaClPlatformFini(); /* we ignore the 2^32 or 2^64 total errors case */ return (error_count > 255) ? 255 : error_count; }
int main(int ac, char **av) { int opt; char const *message = NULL; char *conn_addr = NULL; ssize_t rv; struct NaClDesc *channel; struct NaClNrdXferEffector eff; struct NaClDescEffector *effp; struct NaClDesc *pair[2]; struct NaClSocketAddress nsa; struct NaClDescConnCap ndcc; struct NaClImcTypedMsgHdr msg_hdr; struct NaClImcMsgIoVec iov[1]; struct NaClDesc *desc_buffer[NACL_ABI_IMC_USER_DESC_MAX]; char data_buffer[4096]; size_t i; char *transfer_file = NULL; printf("Hello world\n"); NaClNrdAllModulesInit(); printf("Learning to walk... (parsing command line)\n"); while (EOF != (opt = getopt(ac, av, "c:m:st:v"))) { switch (opt) { case 'c': conn_addr = optarg; break; case 'm': message = optarg; break; case 's': server = 1; break; case 't': transfer_file = optarg; break; case 'v': NaClLogIncrVerbosity(); break; default: fprintf(stderr, "Usage: nrd_xfer_test [-sv] [-c connect-addr] [-m message]\n" " [-t transfer_file_name]\n" "\n"); fprintf(stderr, " -s run in server mode (prints NaCl sock addr)\n" " -v increases verbosity in the NRD xfer library\n" " -c run in client mode, with server NaCl sock addr as\n" " parameter\n" " -m message to be sent to peer (client sends message\n" " as payload data in IMC datagram; and if -t was\n" " specifed in the client to transfer a file\n" " descriptor to the server, the server will write its\n" " message into the file via the transferred\n" " descriptor\n"); return 1; } } printf("Learning to talk... (setting up channels)\n"); if (NULL == message) { if (server) { message = "\"Hello world!\", from server\n"; } else { message = "\"Goodbye cruel world!\", from client\n"; } } if (0 != (rv = NaClCommonDescMakeBoundSock(pair))) { fprintf(stderr, "make bound sock returned %"NACL_PRIdS"\n", rv); return 2; } if (!NaClNrdXferEffectorCtor(&eff, pair[0])) { fprintf(stderr, "EffectorCtor failed\n"); return 3; } effp = (struct NaClDescEffector *) &eff; memset(desc_buffer, 0, sizeof desc_buffer); memset(data_buffer, 0, sizeof data_buffer); if (server) { /* * print out our sockaddr, accept a connection, then receive a message, * and print it out */ /* not opaque type */ printf("Server socket address:\n%.*s\n", NACL_PATH_MAX, ((struct NaClDescConnCap *) pair[1])->cap.path); fflush(stdout); if (0 != (rv = (*pair[0]->vtbl->AcceptConn)(pair[0], effp))) { fprintf(stderr, "AcceptConn returned %"NACL_PRIdS"\n", rv); return 4; } channel = NaClNrdXferEffectorTakeDesc(&eff); if (NULL == channel) { fprintf(stderr, "Could not take descriptor from accept\n"); return 5; } iov[0].base = data_buffer; iov[0].length = sizeof data_buffer; msg_hdr.iov = iov; msg_hdr.iov_length = NACL_ARRAY_SIZE(iov); msg_hdr.ndescv = desc_buffer; msg_hdr.ndesc_length = NACL_ARRAY_SIZE(desc_buffer); rv = NaClImcRecvTypedMessage(channel, effp, &msg_hdr, 0); printf("Receive returned %"NACL_PRIdS"\n", rv); if (!NaClIsNegErrno(rv)) { /* Sanity check: make sure the return value is within range. * This is a panic check because NaClImcRecvTypedMessage should * never return more than the amount of data we asked for, and * that should never be more than INT_MAX. */ if(((size_t)rv > sizeof data_buffer) || (rv > INT_MAX)) { NaClLog(LOG_FATAL, "Buffer overflow in NaClImcRecvTypedMessage. " "Requested %"NACL_PRIdS" bytes, received %"NACL_PRIdS".", sizeof data_buffer, rv); } /* Casting rv to int here because otherwise the pedantic Mac compiler * will complain. Cast is safe due to the range check above. */ printf("Data bytes: %.*s\n", (int)rv, data_buffer); printf("Got %"NACL_PRIdNACL_SIZE" NaCl descriptors\n", msg_hdr.ndesc_length); for (i = 0; i < msg_hdr.ndesc_length; ++i) { struct NaClDesc *ndp; size_t msglen = strlen(message); ssize_t write_result; /* * TODO(bsy): a bit gross; we should expose type tags and RTTI * in a better way, e.g, downcast functions. (Though exposing * type tags allows users to use a switch statement on the * type tag, rather than linearly trying to downcast to all * subclasses.) */ ndp = msg_hdr.ndescv[i]; printf(" type %d\n", ndp->vtbl->typeTag); write_result = (*ndp->vtbl->Write)(ndp, effp, (void *) message, msglen); if (-1 == write_result || msglen != (size_t) write_result) { printf("Write failed: got %"NACL_PRIdS", expected %"NACL_PRIuS"\n", write_result, msglen); } NaClDescUnref(ndp); } } NaClDescUnref(channel); NaClDescUnref(pair[0]); NaClDescUnref(pair[1]); } else { if (NULL == conn_addr) { fprintf(stderr, "Client needs server socket address to which to connect\n"); return 100; } memset(&nsa, 0, sizeof nsa); strncpy(nsa.path, conn_addr, sizeof nsa.path); /* not nec'y NUL term'd */ if (!NaClDescConnCapCtor(&ndcc, &nsa)) { fprintf(stderr, "Client conn cap initialization failed\n"); return 101; } rv = (*ndcc.base.vtbl->ConnectAddr)((struct NaClDesc *) &ndcc, effp); printf("Connect returned %"NACL_PRIdS"\n", rv); if (0 != rv) { fprintf(stderr, "Client could not connect\n"); return 102; } channel = NaClNrdXferEffectorTakeDesc(&eff); if (NULL == channel) { fprintf(stderr, "Could not take descriptor from connect\n"); return 103; } strncpy(data_buffer, message, sizeof data_buffer); iov[0].base = data_buffer; iov[0].length = strlen(data_buffer); msg_hdr.iov = iov; msg_hdr.iov_length = NACL_ARRAY_SIZE(iov); msg_hdr.ndesc_length = 0; msg_hdr.ndescv = desc_buffer; if (NULL != transfer_file) { int xfer_fd; struct NaClHostDesc *nhdp = malloc(sizeof *nhdp); xfer_fd = OPEN(transfer_file, O_CREAT| O_WRONLY | O_TRUNC, 0777); if (-1 == xfer_fd) { fprintf(stderr, "Could not open file \"%s\" to transfer descriptor.\n", transfer_file); return 104; } NaClHostDescPosixTake(nhdp, xfer_fd, O_RDWR); desc_buffer[0] = (struct NaClDesc *) NaClDescIoDescMake(nhdp); msg_hdr.ndesc_length = 1; } rv = NaClImcSendTypedMessage(channel, effp, &msg_hdr, 0); if (NULL != desc_buffer[0]) { NaClDescUnref(desc_buffer[0]); desc_buffer[0] = NULL; } printf("Send returned %"NACL_PRIdS"\n", rv); } (*effp->vtbl->Dtor)(effp); NaClNrdAllModulesFini(); return 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; }